changeset 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents 2a5011c7e641
children 28d41adc0d79
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BadLongOverflowSpecializationTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CreateCastTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExpectError.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/IntegerLiteralGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MergeSpecializationsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NameDuplicationTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildNoNameTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullLiteralGuardsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestSerialization.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/Compile.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/TruffleProcessorTest.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GenerateNodeFactory.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeField.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFields.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SlowPathEvent.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializedNode.java graal/com.oracle.truffle.api.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Execute.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignObjectAccessHeadNode.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GetSize.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/HasSize.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsBoxed.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsExecutable.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsNull.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/KnownMessage.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ObjectAccessNode.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Read.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/TruffleObject.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/UnaryMessage.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Unbox.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Write.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/ReadOnlyArrayList.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/package-info.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BaseLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BooleanLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DoubleLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObjectFactory.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IntLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutFactory.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Location.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationFactory.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LongLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectLocation.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Property.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/NodeUtilTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderSerializerTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestSerializerConstantPool.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/VariableLengthIntBufferTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/BytesSourceSectionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceSectionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/NeverValidAssumptionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/PrimitiveValueProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java graal/com.oracle.truffle.api/.checkstyle_checks.xml graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerOptions.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/LoopCountReceiver.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/OptimizationFailedException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCompilerOptions.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTag.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultProbeListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InvalidAssumptionException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCloneable.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInterface.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/UnsupportedConstantPoolTypeException.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/VariableLengthIntBuffer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/BytesDecoder.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/NeverValidAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/package.html graal/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ExpectError.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/FallbackParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/verify/VerifyTruffleProcessor.java graal/com.oracle.truffle.object.basic/src/META-INF/services/com.oracle.truffle.api.object.LayoutFactory graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicAllocator.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLayout.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLocations.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultLayoutFactory.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DynamicObjectBasic.java graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugShapeVisitor.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/JSONShapeVisitor.java graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestSuite.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java graal/com.oracle.truffle.sl.test/tests/Add.output graal/com.oracle.truffle.sl.test/tests/Add.sl graal/com.oracle.truffle.sl.test/tests/Arithmetic.output graal/com.oracle.truffle.sl.test/tests/Arithmetic.sl graal/com.oracle.truffle.sl.test/tests/Break.output graal/com.oracle.truffle.sl.test/tests/Break.sl graal/com.oracle.truffle.sl.test/tests/Builtins.output graal/com.oracle.truffle.sl.test/tests/Builtins.sl graal/com.oracle.truffle.sl.test/tests/CalcShell.input graal/com.oracle.truffle.sl.test/tests/CalcShell.output graal/com.oracle.truffle.sl.test/tests/CalcShell.sl graal/com.oracle.truffle.sl.test/tests/Call.output graal/com.oracle.truffle.sl.test/tests/Call.sl graal/com.oracle.truffle.sl.test/tests/Comparison.output graal/com.oracle.truffle.sl.test/tests/Comparison.sl graal/com.oracle.truffle.sl.test/tests/ControlFlow.output graal/com.oracle.truffle.sl.test/tests/ControlFlow.sl graal/com.oracle.truffle.sl.test/tests/DefineFunction.output graal/com.oracle.truffle.sl.test/tests/DefineFunction.sl graal/com.oracle.truffle.sl.test/tests/Div.output graal/com.oracle.truffle.sl.test/tests/Div.sl graal/com.oracle.truffle.sl.test/tests/Fibonacci.output graal/com.oracle.truffle.sl.test/tests/Fibonacci.sl graal/com.oracle.truffle.sl.test/tests/FunctionLiteral.output graal/com.oracle.truffle.sl.test/tests/FunctionLiteral.sl graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl graal/com.oracle.truffle.sl.test/tests/HelloWorld.output graal/com.oracle.truffle.sl.test/tests/HelloWorld.sl graal/com.oracle.truffle.sl.test/tests/Inlining.output graal/com.oracle.truffle.sl.test/tests/Inlining.sl graal/com.oracle.truffle.sl.test/tests/Loop.output graal/com.oracle.truffle.sl.test/tests/Loop.sl graal/com.oracle.truffle.sl.test/tests/LoopCall.output graal/com.oracle.truffle.sl.test/tests/LoopCall.sl graal/com.oracle.truffle.sl.test/tests/LoopInvalidate.output graal/com.oracle.truffle.sl.test/tests/LoopInvalidate.sl graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl graal/com.oracle.truffle.sl.test/tests/LoopPrint.output graal/com.oracle.truffle.sl.test/tests/LoopPrint.sl graal/com.oracle.truffle.sl.test/tests/Mul.output graal/com.oracle.truffle.sl.test/tests/Mul.sl graal/com.oracle.truffle.sl.test/tests/Null.output graal/com.oracle.truffle.sl.test/tests/Null.sl graal/com.oracle.truffle.sl.test/tests/Object.output graal/com.oracle.truffle.sl.test/tests/Object.sl graal/com.oracle.truffle.sl.test/tests/String.output graal/com.oracle.truffle.sl.test/tests/String.sl graal/com.oracle.truffle.sl.test/tests/Sub.output graal/com.oracle.truffle.sl.test/tests/Sub.sl graal/com.oracle.truffle.sl.test/tests/Sum.output graal/com.oracle.truffle.sl.test/tests/Sum.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError01.output graal/com.oracle.truffle.sl.test/tests/error/TypeError01.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output graal/com.oracle.truffle.sl.test/tests/error/TypeError02.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError03.output graal/com.oracle.truffle.sl.test/tests/error/TypeError03.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output graal/com.oracle.truffle.sl.test/tests/error/TypeError04.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError05.output graal/com.oracle.truffle.sl.test/tests/error/TypeError05.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError06.output graal/com.oracle.truffle.sl.test/tests/error/TypeError06.sl graal/com.oracle.truffle.sl.test/tests/error/TypeError07.output graal/com.oracle.truffle.sl.test/tests/error/TypeError07.sl graal/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.output graal/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.sl graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDispatchNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUndefinedFunctionException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/EagerStackTraceDecorator.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/GCAfterTestDecorator.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TimingDecorator.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitCore.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListener.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListenerDecorator.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTextListener.java graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleVerboseTextListener.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/Breakpoint.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/FrameDebugDescription.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpoint.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpoint.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/package-info.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLClient.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLServer.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLClientContext.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLCommand.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLContinueException.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLFrame.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLineLocation.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/package-info.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TestNodes.java graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java graal/overview.html mx/suite.py truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BadLongOverflowSpecializationTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CreateCastTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExpectError.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/IntegerLiteralGuardsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MergeSpecializationsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NameDuplicationTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildNoNameTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullLiteralGuardsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestSerialization.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/Compile.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/TruffleProcessorTest.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GenerateNodeFactory.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeField.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFields.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SlowPathEvent.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializedNode.java truffle/com.oracle.truffle.api.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Execute.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignObjectAccessHeadNode.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GetSize.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/HasSize.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsBoxed.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsExecutable.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsNull.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/KnownMessage.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ObjectAccessNode.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Read.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/TruffleObject.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/UnaryMessage.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Unbox.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Write.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/ReadOnlyArrayList.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/package-info.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BaseLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BooleanLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DoubleLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObjectFactory.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IntLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutFactory.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Location.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationFactory.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LongLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectLocation.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Property.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/NodeUtilTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderSerializerTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestSerializerConstantPool.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/VariableLengthIntBufferTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/BytesSourceSectionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceSectionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/NeverValidAssumptionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/PrimitiveValueProfileTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java truffle/com.oracle.truffle.api/.checkstyle_checks.xml truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerOptions.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/LoopCountReceiver.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/OptimizationFailedException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCompilerOptions.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTag.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultProbeListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InvalidAssumptionException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCloneable.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInterface.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/UnsupportedConstantPoolTypeException.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/VariableLengthIntBuffer.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/BytesDecoder.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/NeverValidAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/package.html truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml truffle/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ExpectError.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/FallbackParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/verify/VerifyTruffleProcessor.java truffle/com.oracle.truffle.object.basic/src/META-INF/services/com.oracle.truffle.api.object.LayoutFactory truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicAllocator.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLayout.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLocations.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultLayoutFactory.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DynamicObjectBasic.java truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugShapeVisitor.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/JSONShapeVisitor.java truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestSuite.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java truffle/com.oracle.truffle.sl.test/tests/Add.output truffle/com.oracle.truffle.sl.test/tests/Add.sl truffle/com.oracle.truffle.sl.test/tests/Arithmetic.output truffle/com.oracle.truffle.sl.test/tests/Arithmetic.sl truffle/com.oracle.truffle.sl.test/tests/Break.output truffle/com.oracle.truffle.sl.test/tests/Break.sl truffle/com.oracle.truffle.sl.test/tests/Builtins.output truffle/com.oracle.truffle.sl.test/tests/Builtins.sl truffle/com.oracle.truffle.sl.test/tests/CalcShell.input truffle/com.oracle.truffle.sl.test/tests/CalcShell.output truffle/com.oracle.truffle.sl.test/tests/CalcShell.sl truffle/com.oracle.truffle.sl.test/tests/Call.output truffle/com.oracle.truffle.sl.test/tests/Call.sl truffle/com.oracle.truffle.sl.test/tests/Comparison.output truffle/com.oracle.truffle.sl.test/tests/Comparison.sl truffle/com.oracle.truffle.sl.test/tests/ControlFlow.output truffle/com.oracle.truffle.sl.test/tests/ControlFlow.sl truffle/com.oracle.truffle.sl.test/tests/DefineFunction.output truffle/com.oracle.truffle.sl.test/tests/DefineFunction.sl truffle/com.oracle.truffle.sl.test/tests/Div.output truffle/com.oracle.truffle.sl.test/tests/Div.sl truffle/com.oracle.truffle.sl.test/tests/Fibonacci.output truffle/com.oracle.truffle.sl.test/tests/Fibonacci.sl truffle/com.oracle.truffle.sl.test/tests/FunctionLiteral.output truffle/com.oracle.truffle.sl.test/tests/FunctionLiteral.sl truffle/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output truffle/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl truffle/com.oracle.truffle.sl.test/tests/HelloWorld.output truffle/com.oracle.truffle.sl.test/tests/HelloWorld.sl truffle/com.oracle.truffle.sl.test/tests/Inlining.output truffle/com.oracle.truffle.sl.test/tests/Inlining.sl truffle/com.oracle.truffle.sl.test/tests/Loop.output truffle/com.oracle.truffle.sl.test/tests/Loop.sl truffle/com.oracle.truffle.sl.test/tests/LoopCall.output truffle/com.oracle.truffle.sl.test/tests/LoopCall.sl truffle/com.oracle.truffle.sl.test/tests/LoopInvalidate.output truffle/com.oracle.truffle.sl.test/tests/LoopInvalidate.sl truffle/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output truffle/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl truffle/com.oracle.truffle.sl.test/tests/LoopPrint.output truffle/com.oracle.truffle.sl.test/tests/LoopPrint.sl truffle/com.oracle.truffle.sl.test/tests/Mul.output truffle/com.oracle.truffle.sl.test/tests/Mul.sl truffle/com.oracle.truffle.sl.test/tests/Null.output truffle/com.oracle.truffle.sl.test/tests/Null.sl truffle/com.oracle.truffle.sl.test/tests/Object.output truffle/com.oracle.truffle.sl.test/tests/Object.sl truffle/com.oracle.truffle.sl.test/tests/String.output truffle/com.oracle.truffle.sl.test/tests/String.sl truffle/com.oracle.truffle.sl.test/tests/Sub.output truffle/com.oracle.truffle.sl.test/tests/Sub.sl truffle/com.oracle.truffle.sl.test/tests/Sum.output truffle/com.oracle.truffle.sl.test/tests/Sum.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError01.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError01.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError02.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError02.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError03.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError03.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError04.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError04.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError05.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError05.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError06.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError06.sl truffle/com.oracle.truffle.sl.test/tests/error/TypeError07.output truffle/com.oracle.truffle.sl.test/tests/error/TypeError07.sl truffle/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.output truffle/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.sl truffle/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output truffle/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDispatchNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUndefinedFunctionException.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/EagerStackTraceDecorator.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/GCAfterTestDecorator.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TimingDecorator.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitCore.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListener.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListenerDecorator.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTextListener.java truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleVerboseTextListener.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/Breakpoint.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/FrameDebugDescription.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpoint.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpoint.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/package-info.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLClient.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLServer.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLClientContext.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLCommand.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLContinueException.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLFrame.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLineLocation.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/package-info.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TestNodes.java truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java truffle/overview.html
diffstat 1215 files changed, 83201 insertions(+), 83201 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ArrayTestFactory.TestNode1NodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class ArrayTest {
-
-    @Test
-    public void testNode1() {
-        final TestNode1 node = TestNode1NodeGen.create(null);
-        RootNode root = new RootNode() {
-            @Child TestNode1 test = node;
-
-            @Override
-            public Object execute(VirtualFrame frame) {
-                return test.executeWith(frame, frame.getArguments()[0]);
-            }
-        };
-        CallTarget target = Truffle.getRuntime().createCallTarget(root);
-
-        Assert.assertEquals(1, (int) target.call(1));
-        Assert.assertArrayEquals(new double[0], (double[]) target.call(new int[0]), 0.0d);
-        Assert.assertArrayEquals(new double[0], (double[]) target.call(new double[0]), 0.0d);
-        Assert.assertArrayEquals(new String[0], (String[]) target.call((Object) new String[0]));
-    }
-
-    @TypeSystemReference(ArrayTypeSystem.class)
-    abstract static class BaseNode extends Node {
-
-        abstract Object execute(VirtualFrame frame);
-
-        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
-            return ArrayTypeSystemGen.expectInteger(execute(frame));
-        }
-
-        int[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException {
-            return ArrayTypeSystemGen.expectIntArray(execute(frame));
-        }
-
-        String[] executeStringArray(VirtualFrame frame) throws UnexpectedResultException {
-            return ArrayTypeSystemGen.expectStringArray(execute(frame));
-        }
-
-        double[] executeDoubleArray(VirtualFrame frame) throws UnexpectedResultException {
-            return ArrayTypeSystemGen.expectDoubleArray(execute(frame));
-        }
-    }
-
-    @NodeChild
-    abstract static class TestNode1 extends BaseNode {
-
-        abstract Object executeWith(VirtualFrame frame, Object operand);
-
-        @Specialization
-        int doInt(int value) {
-            return value;
-        }
-
-        @Specialization
-        double[] doDoubleArray(double[] value) {
-            return value;
-        }
-
-        @Specialization
-        String[] doStringArray(String[] value) {
-            return value;
-        }
-
-    }
-
-    @TypeSystem({int.class, int[].class, double[].class, String[].class, Object[].class})
-    public static class ArrayTypeSystem {
-
-        @ImplicitCast
-        public static double[] castFromInt(int[] array) {
-            double[] newArray = new double[array.length];
-            for (int i = 0; i < array.length; i++) {
-                newArray[i] = array[i];
-            }
-            return newArray;
-        }
-
-        @TypeCheck(int[].class)
-        public static boolean isIntArray2(Object array) {
-            return array instanceof int[];
-        }
-
-        @TypeCast(int[].class)
-        public static int[] asIntArray(Object array) {
-            return (int[]) array;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.AssumptionArrayTestFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.CacheAssumptionTestFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.FieldTestFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MethodTestFactory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.NodeFieldTest2Factory;
-import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.StaticFieldTestFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class AssumptionsTest {
-
-    @Test
-    public void testField() {
-        CallTarget root = createCallTarget(FieldTestFactory.getInstance());
-        FieldTest node = getNode(root);
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(42));
-        node.field.invalidate();
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class FieldTest extends ValueNode {
-
-        protected final Assumption field = Truffle.getRuntime().createAssumption();
-
-        @Specialization(assumptions = "field")
-        static int do1(int value) {
-            return value;
-        }
-    }
-
-    @Test
-    public void testNodeField() {
-        Assumption assumption = Truffle.getRuntime().createAssumption();
-        CallTarget root = createCallTarget(NodeFieldTest2Factory.getInstance(), assumption);
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(42));
-        assumption.invalidate();
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    @NodeField(name = "field", type = Assumption.class)
-    static class NodeFieldTest2 extends ValueNode {
-
-        @Specialization(assumptions = "field")
-        static int do1(int value) {
-            return value;
-        }
-    }
-
-    @Test
-    public void testStaticField() {
-        CallTarget root = createCallTarget(StaticFieldTestFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(42));
-        StaticFieldTest.FIELD.invalidate();
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class StaticFieldTest extends ValueNode {
-
-        static final Assumption FIELD = Truffle.getRuntime().createAssumption();
-
-        @Specialization(assumptions = "FIELD")
-        static int do1(int value) {
-            return value;
-        }
-    }
-
-    @Test
-    public void testMethod() {
-        CallTarget root = createCallTarget(MethodTestFactory.getInstance());
-        MethodTest node = getNode(root);
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(42));
-        node.hiddenAssumption.invalidate();
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class MethodTest extends ValueNode {
-
-        private final Assumption hiddenAssumption = Truffle.getRuntime().createAssumption();
-
-        @Specialization(assumptions = "getAssumption()")
-        static int do1(int value) {
-            return value;
-        }
-
-        Assumption getAssumption() {
-            return hiddenAssumption;
-        }
-    }
-
-    @Test
-    public void testCacheAssumption() {
-        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
-        CacheAssumptionTest node = getNode(root);
-        assertEquals("do1", root.call(42));
-        assertEquals("do1", root.call(43));
-        assertEquals("do1", root.call(44));
-        node.assumptions.get(42).invalidate();
-        node.assumptions.put(42, null); // clear 42
-        node.assumptions.get(43).invalidate();
-        node.assumptions.get(44).invalidate();
-        assertEquals("do1", root.call(42)); // recreates 42
-        assertEquals("do2", root.call(43)); // invalid 43 -> remove -> insert do2
-        assertEquals("do2", root.call(46)); // no more lines can be created.
-    }
-
-    @Test
-    public void testCacheAssumptionLimit() {
-        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
-        assertEquals("do1", root.call(42));
-        assertEquals("do1", root.call(43));
-        assertEquals("do1", root.call(44));
-        assertEquals("do2", root.call(45));
-        assertEquals("do1", root.call(43));
-        assertEquals("do1", root.call(44));
-    }
-
-    @NodeChild
-    @SuppressWarnings("unused")
-    static class CacheAssumptionTest extends ValueNode {
-
-        private final Map<Integer, Assumption> assumptions = new HashMap<>();
-
-        @Specialization(guards = "value == cachedValue", assumptions = "getAssumption(cachedValue)")
-        static String do1(int value, @Cached("value") int cachedValue) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        Assumption getAssumption(int value) {
-            Assumption assumption = assumptions.get(value);
-            if (assumption == null) {
-                assumption = Truffle.getRuntime().createAssumption();
-                assumptions.put(value, assumption);
-            }
-            return assumption;
-        }
-    }
-
-    @Test
-    public void testAssumptionArrays() {
-        CallTarget root = createCallTarget(AssumptionArrayTestFactory.getInstance());
-        AssumptionArrayTest node = getNode(root);
-
-        Assumption a1 = Truffle.getRuntime().createAssumption();
-        Assumption a2 = Truffle.getRuntime().createAssumption();
-
-        node.assumptions = new Assumption[]{a1, a2};
-
-        assertEquals("do1", root.call(42));
-
-        a2.invalidate();
-
-        assertEquals("do2", root.call(42));
-    }
-
-    @NodeChild
-    @SuppressWarnings("unused")
-    static class AssumptionArrayTest extends ValueNode {
-
-        Assumption[] assumptions;
-
-        @Specialization(assumptions = "assumptions")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-    }
-
-    @NodeChild
-    static class ErrorIncompatibleReturnType extends ValueNode {
-        @ExpectError("Incompatible return type int. Assumptions must be assignable to Assumption or Assumption[].")
-        @Specialization(assumptions = "3")
-        static int do1(int value) {
-            return value;
-        }
-    }
-
-    @NodeChild
-    static class ErrorBoundDynamicValue extends ValueNode {
-
-        @ExpectError("Assumption expressions must not bind dynamic parameter values.")
-        @Specialization(assumptions = "createAssumption(value)")
-        static int do1(int value) {
-            return value;
-        }
-
-        Assumption createAssumption(int value) {
-            return Truffle.getRuntime().createAssumption(String.valueOf(value));
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BadLongOverflowSpecializationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.BadLongOverflowSpecializationTestFactory.ImplicitCastExclusionFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class BadLongOverflowSpecializationTest {
-
-    /* Regression test for */
-
-    @NodeChild
-    @SuppressWarnings("unused")
-    abstract static class ImplicitCastExclusion extends ValueNode {
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        String f1(long a) {
-            return "triggered1";
-        }
-
-        @Specialization
-        String f2(long a) {
-            return "triggered2";
-        }
-    }
-
-    @Test
-    public void testAdd() {
-        TestRootNode<ImplicitCastExclusion> node = createRoot(ImplicitCastExclusionFactory.getInstance());
-        assertEquals("triggered1", executeWith(node, -1));
-        assertEquals("triggered1", executeWith(node, 5000L));
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.BinaryNodeTestFactory.AddNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class BinaryNodeTest {
-
-    @Test
-    public void testAdd() {
-        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
-        assertEquals(42, executeWith(node, 19, 23));
-        assertEquals(42d, executeWith(node, 19d, 23d));
-        assertEquals(42d, executeWith(node, "19", "23"));
-        assertEquals(42, executeWith(node, 19, 23));
-    }
-
-    @Test(expected = RuntimeException.class)
-    public void testAddUnsupported() {
-        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
-        executeWith(node, new Object(), new Object());
-    }
-
-    @NodeChildren({@NodeChild("left"), @NodeChild("right")})
-    abstract static class BinaryNode extends ValueNode {
-    }
-
-    abstract static class AddNode extends BinaryNode {
-
-        @Specialization
-        int add(int left, int right) {
-            return left + right;
-        }
-
-        @Fallback
-        Object add(Object left, Object right) {
-            return convertDouble(left) + convertDouble(right);
-        }
-
-        static double convertDouble(Object value) {
-            if (value instanceof Number) {
-                return ((Number) value).doubleValue();
-            } else if (value instanceof String) {
-                return Double.parseDouble((String) value);
-            }
-            throw new RuntimeException("Invalid datatype");
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-public class BoxedString {
-
-    private final String delegate;
-
-    public BoxedString(String delegate) {
-        this.delegate = delegate;
-    }
-
-    public String getDelegate() {
-        return delegate;
-    }
-
-    @Override
-    public String toString() {
-        return getDelegate();
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheOverflowFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestBoundCacheOverflowContainsFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheNodeFieldFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithCachedAndDynamicParameterFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithJustCachedParameterFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestMultipleCachesFactory;
-import com.oracle.truffle.api.dsl.test.CachedTestFactory.UnboundCacheFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class CachedTest {
-
-    @Test
-    public void testUnboundCache() {
-        CallTarget root = createCallTarget(UnboundCacheFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(43));
-        assertEquals(42, root.call(44));
-    }
-
-    @NodeChild
-    static class UnboundCache extends ValueNode {
-        @Specialization
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-    }
-
-    @Test
-    public void testBoundCache() {
-        CallTarget root = createCallTarget(BoundCacheFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        assertEquals(44, root.call(44));
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class BoundCache extends ValueNode {
-
-        @Specialization(guards = "value == cachedValue", limit = "3")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-    }
-
-    @Test
-    public void testBoundCacheOverflow() {
-        CallTarget root = createCallTarget(BoundCacheOverflowFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        assertEquals(-1, root.call(44));
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        assertEquals(-1, root.call(44));
-    }
-
-    @NodeChild
-    static class BoundCacheOverflow extends ValueNode {
-
-        @Specialization(guards = "value == cachedValue", limit = "2")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-        @Specialization
-        static int do2(int value) {
-            return -1;
-        }
-
-    }
-
-    @Test
-    public void testBoundCacheOverflowContains() {
-        CallTarget root = createCallTarget(TestBoundCacheOverflowContainsFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        assertEquals(-1, root.call(44));
-        assertEquals(-1, root.call(42));
-        assertEquals(-1, root.call(43));
-        assertEquals(-1, root.call(44));
-    }
-
-    @NodeChild
-    static class TestBoundCacheOverflowContains extends ValueNode {
-
-        @Specialization(guards = "value == cachedValue", limit = "2")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-        @Specialization(contains = "do1")
-        static int do2(int value) {
-            return -1;
-        }
-
-    }
-
-    @Test
-    public void testCacheField() {
-        CallTarget root = createCallTarget(TestCacheFieldFactory.getInstance());
-        assertEquals(3, root.call(42));
-        assertEquals(3, root.call(43));
-    }
-
-    @NodeChild
-    static class TestCacheField extends ValueNode {
-
-        protected int field = 3;
-
-        @Specialization()
-        static int do1(int value, @Cached("field") int cachedValue) {
-            return cachedValue;
-        }
-
-    }
-
-    @Test
-    public void testCacheNodeField() {
-        CallTarget root = createCallTarget(TestCacheNodeFieldFactory.getInstance(), 21);
-        assertEquals(21, root.call(42));
-        assertEquals(21, root.call(43));
-    }
-
-    @NodeChild
-    @NodeField(name = "field", type = int.class)
-    static class TestCacheNodeField extends ValueNode {
-
-        @Specialization
-        static int do1(int value, @Cached("field") int cachedValue) {
-            return cachedValue;
-        }
-
-    }
-
-    @Test
-    public void testCacheMethod() {
-        TestCacheMethod.invocations = 0;
-        CallTarget root = createCallTarget(TestCacheMethodFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(43));
-        assertEquals(42, root.call(44));
-        assertEquals(1, TestCacheMethod.invocations);
-    }
-
-    @NodeChild
-    static class TestCacheMethod extends ValueNode {
-
-        static int invocations = 0;
-
-        @Specialization
-        static int do1(int value, @Cached("someMethod(value)") int cachedValue) {
-            return cachedValue;
-        }
-
-        static int someMethod(int value) {
-            invocations++;
-            return value;
-        }
-
-    }
-
-    @Test
-    public void testGuardWithJustCachedParameter() {
-        TestGuardWithJustCachedParameter.invocations = 0;
-        CallTarget root = createCallTarget(TestGuardWithJustCachedParameterFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(43));
-        assertEquals(42, root.call(44));
-        // guards with just cached parameters are just invoked on the slow path
-        assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithJustCachedParameter.invocations);
-    }
-
-    @NodeChild
-    static class TestGuardWithJustCachedParameter extends ValueNode {
-
-        static int invocations = 0;
-
-        @Specialization(guards = "someMethod(cachedValue)")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-        static boolean someMethod(int value) {
-            invocations++;
-            return true;
-        }
-
-    }
-
-    @Test
-    public void testGuardWithCachedAndDynamicParameter() {
-        TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations = 0;
-        TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations = 0;
-        CallTarget root = createCallTarget(TestGuardWithCachedAndDynamicParameterFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(42, root.call(43));
-        assertEquals(42, root.call(44));
-        // guards with just cached parameters are just invoked on the slow path
-        assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations);
-        assertEquals(4, TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations);
-    }
-
-    @NodeChild
-    static class TestGuardWithCachedAndDynamicParameter extends ValueNode {
-
-        static int cachedMethodInvocations = 0;
-        static int dynamicMethodInvocations = 0;
-
-        @Specialization(guards = {"dynamicMethod(value)", "cachedMethod(cachedValue)"})
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-        static boolean cachedMethod(int value) {
-            cachedMethodInvocations++;
-            return true;
-        }
-
-        static boolean dynamicMethod(int value) {
-            dynamicMethodInvocations++;
-            return true;
-        }
-
-    }
-
-    /*
-     * Node should not produce any warnings in isIdentical of the generated code. Unnecessary casts
-     * were generated for isIdentical on the fast path.
-     */
-    @NodeChildren({@NodeChild, @NodeChild})
-    static class RegressionTestWarningInIsIdentical extends ValueNode {
-
-        @Specialization(guards = {"cachedName == name"})
-        protected Object directAccess(String receiver, String name, //
-                        @Cached("name") String cachedName, //
-                        @Cached("create(receiver, name)") Object callHandle) {
-            return receiver;
-        }
-
-        protected static Object create(String receiver, String name) {
-            return receiver;
-        }
-
-    }
-
-    @NodeChild
-    static class TestMultipleCaches extends ValueNode {
-
-        @Specialization
-        static int do1(int value, @Cached("value") int cachedValue1, @Cached("value") int cachedValue2) {
-            return cachedValue1 + cachedValue2;
-        }
-
-    }
-
-    @Test
-    public void testMultipleCaches() {
-        CallTarget root = createCallTarget(TestMultipleCachesFactory.getInstance());
-        assertEquals(42, root.call(21));
-        assertEquals(42, root.call(22));
-        assertEquals(42, root.call(23));
-    }
-
-    @NodeChild
-    static class CachedError1 extends ValueNode {
-        @Specialization
-        static int do1(int value, @ExpectError("Incompatible return type int. The expression type must be equal to the parameter type double.")//
-                        @Cached("value") double cachedValue) {
-            return value;
-        }
-    }
-
-    @NodeChild
-    static class CachedError2 extends ValueNode {
-
-        // caches are not allowed to make backward references
-
-        @Specialization
-        static int do1(int value,
-                        @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1,
-                        @Cached("value") int cachedValue2) {
-            return cachedValue1 + cachedValue2;
-        }
-
-    }
-
-    @NodeChild
-    static class CachedError3 extends ValueNode {
-
-        // cyclic dependency between cached expressions
-        @Specialization
-        static int do1(int value,
-                        @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1,
-                        @Cached("cachedValue1") int cachedValue2) {
-            return cachedValue1 + cachedValue2;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.CodeFormatTestFactory.LineWrappingTestFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-/**
- * Tests the generated code compiles without warnings for unusual large guard names.
- */
-public class CodeFormatTest {
-
-    @Test
-    public void test() {
-        Assert.assertEquals(42, TestHelper.createCallTarget(LineWrappingTestFactory.create()).call());
-    }
-
-    abstract static class LineWrappingTest extends ValueNode {
-
-        public LineWrappingTest() {
-        }
-
-        protected static boolean guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1() {
-            return true;
-        }
-
-        protected static boolean guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2() {
-            return true;
-        }
-
-        @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
-                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()"})
-        public int execute() {
-            return 42;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class CompilerErrorTest {
-
-    abstract static class Visiblity01 extends ValueNode {
-
-        @Specialization
-        @SuppressWarnings("static-method")
-        @ExpectError("Method annotated with @Specialization must not be private.")
-        private Object s() {
-            return null;
-        }
-
-    }
-
-    @ExpectError("Classes containing a @Specialization annotation must not be private.")
-    private abstract static class Visiblity02 extends ValueNode {
-
-        @Specialization
-        public Object s() {
-            return null;
-        }
-
-    }
-
-    // assert no error
-    @ExpectError({})
-    private abstract static class Visiblity03 extends ValueNode {
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,555 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains1Factory;
-import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains2Factory;
-import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains3Factory;
-import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains4Factory;
-import com.oracle.truffle.api.dsl.test.ContainsTestFactory.PolymorphicToMonomorphic0Factory;
-import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-
-@SuppressWarnings("unused")
-public class ContainsTest {
-
-    /*
-     * Tests a simple monomorphic inclusion.
-     */
-    @Test
-    public void testContains1() {
-        assertRuns(Contains1Factory.getInstance(), //
-                        array(1, "a", 2, "b"), //
-                        array(2, "aa", 3, "ba"), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (value instanceof String) {
-                                    if (node.getNode() instanceof DSLNode) {
-                                        // assert that the final specialization is always Object
-                                        Assert.assertEquals(Object.class, ((DSLNode) node.getNode()).getMetadata0().getSpecializedTypes()[0]);
-                                    } else {
-                                        Assert.assertTrue(((SpecializedNode) node.getNode()).getSpecializationNode().toString().startsWith("F2Node_"));
-                                    }
-                                }
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Contains1 extends ValueNode {
-
-        @Specialization
-        int f1(int a) {
-            return a + 1;
-        }
-
-        @Specialization(contains = "f1")
-        Object f2(Object a) {
-            if (a instanceof Integer) {
-                return ((Integer) a) + 1;
-            }
-            return a + "a";
-        }
-    }
-
-    /*
-     * Tests an inclusion in within a polymorphic chain.
-     */
-    @Test
-    public void testContains2() {
-        assertRuns(Contains2Factory.getInstance(), //
-                        array(true, 1, 0, false), //
-                        array(false, -1, 1, true) //
-        );
-    }
-
-    @NodeChild("a")
-    abstract static class Contains2 extends ValueNode {
-
-        static boolean isZero(int a) {
-            return a == 0;
-        }
-
-        @Specialization(guards = "isZero(a)")
-        int f1(int a) {
-            return a + 1;
-        }
-
-        @Specialization(contains = "f1")
-        int f2(int a) {
-            if (a == 0) {
-                return a + 1;
-            }
-            return -a;
-        }
-
-        @Specialization
-        boolean f3(boolean a) {
-            return !a;
-        }
-    }
-
-    /*
-     * Tests transitive monomorphic inclusion.
-     */
-    @Test
-    public void testContains3() {
-        assertRuns(Contains3Factory.getInstance(), //
-                        array(2, 1, 2, -3, -4), //
-                        array(-2, 2, -2, -3, -4), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                // assert that we are always monomorphic
-                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Contains3 extends ValueNode {
-
-        static boolean isGreaterZero(int a) {
-            return a > 0;
-        }
-
-        static boolean isOne(int a) {
-            return a == 1;
-        }
-
-        @Specialization(guards = {"isOne(a)"})
-        int f1(int a) {
-            return a + 1;
-        }
-
-        @Specialization(contains = "f1", guards = {"isGreaterZero(a)"})
-        int f2(int a) {
-            if (a == 1) {
-                return 2;
-            }
-            return -a;
-        }
-
-        @Specialization(contains = "f2")
-        int f3(int a) {
-            if (a > 0) {
-                return a == 1 ? 2 : -a;
-            } else {
-                return a;
-            }
-        }
-
-    }
-
-    /*
-     * Tests that if it can be derived that two specializations actually a as powerful as the latter
-     * we can combine them. Therefore operation should always become monomorphic in the end.
-     */
-    @Test
-    public void testContains4() {
-        assertRuns(Contains4Factory.getInstance(), //
-                        array(-1, 0, 1, 2), //
-                        array(1, 0, 1, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Contains4 extends ValueNode {
-
-        static boolean isOne(int a) {
-            return a == 1;
-        }
-
-        @Specialization(guards = "isOne(a)")
-        int f0(int a) {
-            return 1;
-        }
-
-        @Specialization(contains = "f0", guards = "a >= 0")
-        int f1(int a) {
-            return a;
-        }
-
-        @Specialization(contains = {"f1"})
-        int f2(int a) {
-            return Math.abs(a);
-        }
-
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsError1 extends ValueNode {
-        @ExpectError("The contained specialization 'f1' must be declared before the containing specialization.")
-        @Specialization(contains = "f1")
-        int f0(int a) {
-            return a;
-        }
-
-        @Specialization
-        Object f1(String a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsError2 extends ValueNode {
-
-        @ExpectError("The referenced specialization 'does not exist' could not be found.")
-        @Specialization(contains = "does not exist")
-        int f0(int a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsError3 extends ValueNode {
-
-        @Specialization
-        int f0(int a) {
-            return a;
-        }
-
-        @ExpectError("Duplicate contains declaration 'f0'.")
-        @Specialization(contains = {"f0", "f0"})
-        Object f1(double a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsError4 extends ValueNode {
-
-        @ExpectError("Circular contained specialization 'f1(double)' found.")
-        @Specialization(contains = {"f1"})
-        Object f1(double a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsError5 extends ValueNode {
-
-        @ExpectError({"Circular contained specialization 'f0(int)' found.", "Circular contained specialization 'f1(double)' found.",
-                        "The contained specialization 'f1' must be declared before the containing specialization."})
-        @Specialization(contains = "f1")
-        int f0(int a) {
-            return a;
-        }
-
-        @ExpectError("Circular contained specialization 'f1(double)' found.")
-        @Specialization(contains = {"f0"})
-        Object f1(double a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsType1 extends ValueNode {
-        @Specialization
-        int f0(int a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by f0(int).")
-        @Specialization(contains = "f0")
-        Object f1(int a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsType2 extends ValueNode {
-        @Specialization
-        int f0(int a) {
-            return a;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1(Object a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsType3 extends ValueNode {
-        @Specialization
-        int f0(int a) {
-            return a;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1(double a) { // implicit type
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class ContainsType4 extends ValueNode {
-        @Specialization
-        double f0(double a) {
-            return a;
-        }
-
-        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double)."})
-        @Specialization(contains = "f0")
-        int f1(int a) { // implicit type
-            return a;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class ContainsType5 extends ValueNode {
-        @Specialization
-        Object f0(Object a, int b) {
-            return a;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1(int a, Object b) {
-            return a;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class ContainsType6 extends ValueNode {
-        @Specialization
-        Object f0(double a, int b) {
-            return a;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1(int a, double b) { // implicit type
-            return a;
-        }
-    }
-
-    abstract static class ContainsGuard1 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        @Specialization(guards = "g1()")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard2 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        @Specialization
-        Object f0() {
-            return null;
-        }
-
-        @ExpectError({"Specialization is not reachable. It is shadowed by f0()."})
-        @Specialization(guards = "g1()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard3 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        @Specialization(guards = "g1()")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(guards = "!g1()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard4 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        boolean g2() {
-            return true;
-        }
-
-        @Specialization(guards = "g1()")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(guards = "g2()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard5 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        boolean g2() {
-            return true;
-        }
-
-        @Specialization(guards = "g1()")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(guards = "g2()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard6 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        boolean g2() {
-            return true;
-        }
-
-        @Specialization(guards = "g1()")
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(guards = "!g2()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsGuard7 extends ValueNode {
-
-        boolean g1() {
-            return true;
-        }
-
-        boolean g2() {
-            return true;
-        }
-
-        @Specialization(guards = {"g1()", "g2()"})
-        Object f0() {
-            return null;
-        }
-
-        @Specialization(guards = "g2()", contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsThrowable1 extends ValueNode {
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        Object f0() throws RuntimeException {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "f0")
-        Object f1() {
-            return null;
-        }
-    }
-
-    abstract static class ContainsThrowable2 extends ValueNode {
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        Object f0() throws RuntimeException {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "f0", rewriteOn = RuntimeException.class)
-        Object f1() throws RuntimeException {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "f1")
-        Object f2() {
-            return null;
-        }
-    }
-
-    @Test
-    public void testPolymorphicToMonomorphic0() {
-        TestRootNode<PolymorphicToMonomorphic0> root = createRoot(PolymorphicToMonomorphic0Factory.getInstance());
-        assertThat((int) executeWith(root, 1), is(1));
-        assertThat((int) executeWith(root, 2), is(2));
-        assertThat((int) executeWith(root, 3), is(3));
-        assertThat(root.getNode().getCost(), is(NodeCost.MONOMORPHIC));
-    }
-
-    @NodeChild("a")
-    static class PolymorphicToMonomorphic0 extends ValueNode {
-
-        @Specialization(guards = "a == 1")
-        int do1(int a) {
-            return a;
-        }
-
-        @Specialization(guards = "a == 2")
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization(contains = {"do1", "do2"})
-        int do3(int a) {
-            return a;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CreateCastTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode1Factory;
-import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode2Factory;
-import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode3Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-
-@SuppressWarnings("unused")
-public class CreateCastTest {
-
-    @Test
-    public void testCastNode1() {
-        TestRootNode<CreateCastNode1> root = TestHelper.createRoot(CreateCastNode1Factory.getInstance());
-        Assert.assertEquals(1, root.getNode().invocations);
-    }
-
-    @Test
-    public void testCastNode2() {
-        TestRootNode<CreateCastNode2> root = TestHelper.createRoot(CreateCastNode2Factory.getInstance());
-        Assert.assertEquals(2, root.getNode().invocations);
-    }
-
-    @Test
-    public void testCastNode3() {
-        TestRootNode<CreateCastNode3> root = TestHelper.createRoot(CreateCastNode3Factory.getInstance());
-        Assert.assertEquals(1, root.getNode().invocations);
-    }
-
-    @NodeChild("a")
-    abstract static class CreateCastNode1 extends ValueNode {
-
-        int invocations = 0;
-
-        @CreateCast({"a"})
-        public ValueNode createCast(ValueNode node) {
-            invocations++;
-            return node;
-        }
-
-        @Specialization
-        public int doInteger(int a) {
-            throw new AssertionError();
-        }
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class CreateCastNode2 extends ValueNode {
-
-        int invocations = 0;
-
-        @CreateCast({"a", "b"})
-        public ValueNode createCast(ValueNode node) {
-            invocations++;
-            return node;
-        }
-
-        @Specialization
-        public int doInteger(int a, int b) {
-            throw new AssertionError();
-        }
-    }
-
-    abstract static class CreateCastNode3 extends ChildrenNode {
-
-        int invocations = 0;
-
-        @CreateCast("children")
-        public ValueNode[] createCast(ValueNode[] node) {
-            invocations++;
-            return node;
-        }
-
-        @Specialization
-        public int doInteger(int a) {
-            throw new AssertionError();
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class CreateCastFailNode1 extends ValueNode {
-
-        @ExpectError({"Specified child '' not found."})
-        @CreateCast({""})
-        public ValueNode createCast(Node child) {
-            throw new AssertionError();
-        }
-
-        @Specialization
-        public int doInteger(int a) {
-            throw new AssertionError();
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedGenerationFactory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs0Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs1Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs2Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs3Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs4Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs5Factory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated1NodeFactory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated2NodeFactory;
-import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class ExecuteEvaluatedTest {
-
-    @Test
-    public void testSingleEvaluated() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null)));
-
-        Assert.assertEquals(43, callTarget.call(new Object[]{42}));
-        Assert.assertEquals(1, arg0.getInvocationCount());
-    }
-
-    @NodeChild("exp")
-    abstract static class EvaluatedNode extends ValueNode {
-
-        @Specialization
-        int doExecuteWith(int exp) {
-            return exp + 1;
-        }
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue);
-
-        public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException;
-    }
-
-    @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")})
-    abstract static class UseEvaluatedNode extends ValueNode {
-
-        @Specialization
-        int call(int exp0, int exp1) {
-            Assert.assertEquals(exp0 + 1, exp1);
-            return exp1;
-        }
-    }
-
-    @Test
-    public void testDoubleEvaluated1() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated1NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null)));
-
-        Assert.assertEquals(42, callTarget.call(new Object[]{43, 1}));
-        Assert.assertEquals(1, arg0.getInvocationCount());
-        Assert.assertEquals(1, arg1.getInvocationCount());
-    }
-
-    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")})
-    abstract static class DoubleEvaluatedNode extends ValueNode {
-
-        @Specialization
-        int doExecuteWith(int exp0, int exp1) {
-            return exp0 - exp1;
-        }
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1);
-
-        public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException;
-    }
-
-    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})})
-    abstract static class UseDoubleEvaluated1Node extends ValueNode {
-
-        @Specialization
-        int call(int exp0, int exp1, int exp2) {
-            Assert.assertEquals(exp0 - exp1, exp2);
-            return exp2;
-        }
-    }
-
-    @Test
-    public void testDoubleEvaluated2() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated2NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null)));
-
-        Assert.assertEquals(42, callTarget.call(new Object[]{1, 43}));
-        Assert.assertEquals(1, arg0.getInvocationCount());
-        Assert.assertEquals(1, arg1.getInvocationCount());
-    }
-
-    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp1", "exp0"})})
-    abstract static class UseDoubleEvaluated2Node extends ValueNode {
-
-        @Specialization
-        int call(int exp0, int exp1, int exp2) {
-            Assert.assertEquals(exp1 - exp0, exp2);
-            return exp2;
-        }
-    }
-
-    @Test
-    public void testEvaluatedGeneration() throws UnexpectedResultException {
-        TestRootNode<TestEvaluatedGeneration> root = TestHelper.createRoot(TestEvaluatedGenerationFactory.getInstance());
-
-        Assert.assertEquals(42, root.getNode().executeEvaluated1(null, 42));
-        Assert.assertEquals(42, root.getNode().executeEvaluated2(null, 42));
-        Assert.assertEquals(42, root.getNode().executeEvaluated3(null, 42));
-        Assert.assertEquals(42, root.getNode().executeEvaluated4(null, 42));
-    }
-
-    @NodeChildren({@NodeChild("exp0")})
-    abstract static class TestEvaluatedGeneration extends ValueNode {
-
-        public abstract Object executeEvaluated1(VirtualFrame frame, Object value);
-
-        public abstract Object executeEvaluated2(VirtualFrame frame, int value);
-
-        public abstract int executeEvaluated3(VirtualFrame frame, Object value) throws UnexpectedResultException;
-
-        public abstract int executeEvaluated4(VirtualFrame frame, int value) throws UnexpectedResultException;
-
-        @Specialization
-        int call(int exp0) {
-            return exp0;
-        }
-    }
-
-    @Test
-    public void test0VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs0> root = TestHelper.createRoot(TestEvaluatedVarArgs0Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null));
-    }
-
-    abstract static class TestEvaluatedVarArgs0 extends ChildrenNode {
-
-        @Override
-        public final Object execute(VirtualFrame frame) {
-            return execute1(frame);
-        }
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call() {
-            return 42;
-        }
-    }
-
-    @Test
-    public void test1VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs1> root = TestHelper.createRoot(TestEvaluatedVarArgs1Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null, 42));
-    }
-
-    @Test(expected = Throwable.class)
-    public void test1VarArgs2() {
-        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
-        root.getNode().execute1(null);
-    }
-
-    abstract static class TestEvaluatedVarArgs1 extends ChildrenNode {
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call(int exp0) {
-            return exp0;
-        }
-    }
-
-    @Test
-    public void test2VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null, 21, 21));
-    }
-
-    @Test(expected = Throwable.class)
-    public void test2VarArgs2() {
-        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
-        root.getNode().execute1(null, 42);
-    }
-
-    @Test(expected = Throwable.class)
-    public void test2VarArgs3() {
-        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
-        root.getNode().execute1(null);
-    }
-
-    abstract static class TestEvaluatedVarArgs2 extends ChildrenNode {
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call(int exp0, int exp1) {
-            return exp0 + exp1;
-        }
-    }
-
-    @Test
-    public void test3VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs3> root = TestHelper.createRoot(TestEvaluatedVarArgs3Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null, 42));
-    }
-
-    @NodeChild
-    abstract static class TestEvaluatedVarArgs3 extends ValueNode {
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call(int exp0) {
-            return exp0;
-        }
-    }
-
-    @Test
-    public void test4VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs4> root = TestHelper.createRoot(TestEvaluatedVarArgs4Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null, 21, 21));
-    }
-
-    @NodeChildren({@NodeChild, @NodeChild})
-    abstract static class TestEvaluatedVarArgs4 extends ValueNode {
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call(int exp0, int exp1) {
-            return exp0 + exp1;
-        }
-    }
-
-    @Test
-    public void test5VarArgs1() {
-        TestRootNode<TestEvaluatedVarArgs5> root = TestHelper.createRoot(TestEvaluatedVarArgs5Factory.getInstance());
-        Assert.assertEquals(42, root.getNode().execute1(null));
-    }
-
-    abstract static class TestEvaluatedVarArgs5 extends ValueNode {
-
-        @Override
-        public final Object execute(VirtualFrame frame) {
-            return execute1(frame);
-        }
-
-        public abstract Object execute1(VirtualFrame frame, Object... value);
-
-        @Specialization
-        int call() {
-            return 42;
-        }
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)})
-    abstract static class TestEvaluatedShortCircuit1 extends Node {
-
-        public abstract Object execute1(VirtualFrame frame, Object value);
-
-        public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB);
-
-        public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b);
-
-        @ShortCircuit("b")
-        public boolean needsB(Object a) {
-            return true;
-        }
-
-        @Specialization
-        int call(Object a, boolean hasB, Object b) {
-            return 42;
-        }
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)})
-    abstract static class TestEvaluatedShortCircuit2 extends Node {
-
-        public abstract Object execute1(VirtualFrame frame, Object value);
-
-        public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB);
-
-        public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b);
-
-        @ShortCircuit("b")
-        public boolean needsB(Object a) {
-            return true;
-        }
-
-        @Specialization
-        int call(int a, boolean hasB, int b) {
-            return 42;
-        }
-
-        @Specialization
-        int call(Object a, boolean hasB, Object b) {
-            return 42;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static org.junit.Assert.*;
-
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ExecuteGroupingTestFactory.ExecuteGrouping1NodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/*
- * This test aims to test the reuse of execute methods with evaluated parameters as much as possible.
- */
-@RunWith(Theories.class)
-public class ExecuteGroupingTest {
-
-    @DataPoints public static final Object[] parameters = new Object[]{1, 2};
-
-    static final class ExecuteGroupingChild extends Node {
-
-        int invocationCount = 0;
-
-        private final Object returnValue;
-
-        public ExecuteGroupingChild(Object returnValue) {
-            this.returnValue = returnValue;
-        }
-
-        Object execute() {
-            invocationCount++;
-            return returnValue;
-        }
-
-    }
-
-    @Theory
-    public void testExecuteGrouping1Node(Object a, Object b, Object c) throws UnexpectedResultException {
-        ExecuteGroupingChild child0 = new ExecuteGroupingChild(a);
-        ExecuteGroupingChild child1 = new ExecuteGroupingChild(b);
-        ExecuteGroupingChild child2 = new ExecuteGroupingChild(c);
-
-        int result = ((int) a) + ((int) b) + ((int) c);
-
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute());
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute((VirtualFrame) null));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).execute(a));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).executeInt(a));
-
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, b));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, b));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, (int) b));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, (int) b));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).executeInt((int) a, (int) b));
-
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute(a, b, c));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, c));
-        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, (int) c));
-
-    }
-
-    @NodeChildren({@NodeChild(type = ExecuteGroupingChild.class), @NodeChild(type = ExecuteGroupingChild.class), @NodeChild(type = ExecuteGroupingChild.class)})
-    abstract static class ExecuteGrouping1Node extends Node {
-
-        abstract Object execute();
-
-        int executeInt() throws UnexpectedResultException {
-            Object value = execute();
-            if (value instanceof Integer) {
-                return (int) value;
-            }
-            throw new UnexpectedResultException(value);
-        }
-
-        abstract double executeDouble() throws UnexpectedResultException;
-
-        abstract Object execute(VirtualFrame frame);
-
-        abstract Object execute(Object o1);
-
-        abstract int executeInt(Object o1) throws UnexpectedResultException;
-
-        abstract Object execute(Object o1, Object o2);
-
-        abstract Object execute(int o1, int o2);
-
-        abstract Object execute(int o1, int o2, Object o3);
-
-        abstract int executeInt(int o1, int o2) throws UnexpectedResultException;
-
-        abstract Object execute(Object o1, int o2);
-
-        abstract Object execute(int o1, Object o2);
-
-        abstract Object execute(Object o1, Object o2, Object o3);
-
-        abstract Object execute(int o1, int o2, int o3);
-
-        @Specialization
-        int s1(int a, int b, int c) {
-            return a + b + c;
-        }
-
-        @Specialization
-        int s2(Object a, Object b, Object c) {
-            return ((int) a) + ((int) b) + ((int) c);
-        }
-
-    }
-
-    abstract static class StrangeReturnCase extends Node {
-
-        // we don't know how to implement executeDouble
-        public abstract double executeDouble();
-
-        public int executeInt() {
-            return 42;
-        }
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        double s1() {
-            return 42;
-        }
-
-        @Specialization
-        double s2() {
-            return 42;
-        }
-
-    }
-
-    @ExpectError("Incompatible abstract execute methods found %")
-    abstract static class IncompatibleAbstract1 extends Node {
-
-        // we don't know how to implement executeDouble
-        abstract double executeDouble();
-
-        abstract int executeInt();
-
-        @Specialization
-        double s1() {
-            return 42;
-        }
-
-    }
-
-    abstract static class IncompatibleAbstract2 extends Node {
-
-        abstract double executeDouble();
-
-        // we can resolve duplicate path errors by making an execute method final
-        @SuppressWarnings("static-method")
-        public final int executeInt() {
-            return 42;
-        }
-
-        @ExpectError("The provided return type \"int\" does not match expected return type \"double\".%")
-        @Specialization(rewriteOn = RuntimeException.class)
-        int s1() {
-            return 42;
-        }
-
-        @Specialization
-        double s2() {
-            return 42;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,433 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class ExecuteMethodTest {
-
-    private static final String ERROR_NO_EXECUTE = "No accessible and overridable generic execute method found. Generic execute methods usually have the signature 'public abstract {Type} "
-                    + "execute(VirtualFrame)' and must not throw any checked exceptions.";
-
-    @TypeSystem({int.class})
-    @DSLOptions(useNewLayout = true)
-    static class ExecuteMethodTypes {
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    abstract static class ChildNoFrame extends Node {
-        abstract Object execute();
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError(ERROR_NO_EXECUTE)
-    abstract static class ExecuteThis1 extends Node {
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError(ERROR_NO_EXECUTE)
-    abstract static class ExecuteThis2 extends Node {
-
-        abstract Object execute() throws UnexpectedResultException;
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError(ERROR_NO_EXECUTE)
-    abstract static class ExecuteThis3 extends Node {
-
-        abstract int execute() throws UnexpectedResultException;
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThis4 extends Node {
-
-        protected abstract Object execute();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThis5 extends Node {
-
-        public abstract Object execute();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError(ERROR_NO_EXECUTE)
-    abstract static class ExecuteThis6 extends Node {
-
-        @SuppressWarnings({"unused", "static-method"})
-        private Object execute() {
-            return 0;
-        }
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError(ERROR_NO_EXECUTE)
-    abstract static class ExecuteThis7 extends Node {
-
-        @SuppressWarnings("static-method")
-        public final int executeInt() {
-            return 0;
-        }
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThis8 extends Node {
-
-        abstract int executeInt();
-
-        abstract Object executeObject();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThis9 extends Node {
-
-        abstract int executeInt();
-
-        // disambiguate executeObject
-        final Object executeObject() {
-            return executeInt();
-        }
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThisVoid1 extends Node {
-
-        abstract void executeVoid();
-
-        @Specialization
-        void doInt(@SuppressWarnings("unused") int a) {
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThisVoid2 extends Node {
-
-        // allow one execute void
-        abstract void executeVoid();
-
-        abstract Object executeObject();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteThisVoid3 extends Node {
-
-        // allow only one execute void
-        abstract void executeVoid1();
-
-        abstract void executeVoid2();
-
-        abstract Object executeObject();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrame1 extends Node {
-
-        // no frame in execute. no parameter in specializations
-        abstract Object executeNoFrame();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrame2 extends Node {
-
-        // frame in execute also usable in specialization
-        abstract Object executeWithFrame(VirtualFrame frame);
-
-        @Specialization
-        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrame3 extends Node {
-
-        abstract Object executeWithFrame(Frame frame);
-
-        @Specialization
-        int doInt(@SuppressWarnings("unused") Frame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ExecuteWithFrame4.class)
-    abstract static class ExecuteWithFrame4 extends Node {
-
-        abstract Object executeWithFrame(MaterializedFrame frame);
-
-        @Specialization
-        int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrameError1 extends Node {
-
-        abstract Object executeNoFrame();
-
-        @Specialization
-        @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%")
-        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrameError2 extends Node {
-
-        abstract Object executeFrame(MaterializedFrame frame);
-
-        @Specialization
-        @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%")
-        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrameError3 extends Node {
-
-        abstract Object executeFrame(VirtualFrame frame);
-
-        @Specialization
-        @ExpectError("Method signature (MaterializedFrame, int) does not match to the expected signature:%")
-        int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    @ExpectError("Invalid inconsistent frame types [MaterializedFrame, VirtualFrame] found for the declared execute methods.%")
-    abstract static class ExecuteWithFrameError4 extends Node {
-
-        abstract Object execute(VirtualFrame frame);
-
-        abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException;
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteWithFrameError5 extends Node {
-
-        abstract Object execute();
-
-        abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException;
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    abstract static class ChildVirtualFrame extends Node {
-        abstract Object execute(VirtualFrame frame);
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    abstract static class ChildMaterializedFrame extends Node {
-        abstract Object execute(MaterializedFrame frame);
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    abstract static class ChildFrame extends Node {
-        abstract Object execute(Frame frame);
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildNoFrame.class)
-    abstract static class ExecuteChildFrame1 extends Node {
-
-        abstract Object execute(VirtualFrame frame);
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildFrame.class)
-    abstract static class ExecuteChildFrame2 extends Node {
-
-        abstract Object execute(VirtualFrame frame);
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildFrame.class)
-    abstract static class ExecuteChildFrame3 extends Node {
-
-        abstract Object execute(MaterializedFrame frame);
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildFrame.class)
-    abstract static class ExecuteChildFrame4 extends Node {
-
-        abstract Object execute(Frame frame);
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [com.oracle.truffle.api.frame.Frame].")
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildVirtualFrame.class)
-    abstract static class ExecuteChildFrameError1 extends Node {
-
-        abstract Object execute(Frame frame);
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildFrame and frame types [].")
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildFrame.class)
-    abstract static class ExecuteChildFrameError2 extends Node {
-
-        abstract Object execute();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [].")
-    @TypeSystemReference(ExecuteMethodTypes.class)
-    @NodeChild(value = "a", type = ChildVirtualFrame.class)
-    abstract static class ExecuteChildFrameError3 extends Node {
-
-        abstract Object execute();
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExpectError.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import java.lang.annotation.*;
-
-/**
- * This annotation is internally known by the dsl processor and used to expect errors for testing
- * purposes. This is not part of public API.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface ExpectError {
-
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback1Factory;
-import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback2Factory;
-import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback3Factory;
-import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback4Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class FallbackTest {
-
-    private static final Object UNKNOWN_OBJECT = new Object() {
-    };
-
-    @Test
-    public void testFallback1() {
-        assertRuns(Fallback1Factory.getInstance(), //
-                        array(42, UNKNOWN_OBJECT), //
-                        array("(int)", "(fallback)"));
-    }
-
-    /**
-     * Test with fallback handler defined.
-     */
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class Fallback1 extends ValueNode {
-
-        @Override
-        public abstract String executeString(VirtualFrame frame);
-
-        @Specialization
-        String f1(int a) {
-            return "(int)";
-        }
-
-        @Fallback
-        String f2(Object a) {
-            return "(fallback)";
-        }
-    }
-
-    @Test
-    public void testFallback2() {
-        assertRuns(Fallback2Factory.getInstance(), //
-                        array(42, UNKNOWN_OBJECT), //
-                        array("(int)", UnsupportedSpecializationException.class));
-    }
-
-    /**
-     * Test without fallback handler defined.
-     */
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class Fallback2 extends ValueNode {
-
-        @Specialization
-        String f1(int a) {
-            return "(int)";
-        }
-
-    }
-
-    @Test
-    public void testFallback3() {
-        assertRuns(Fallback3Factory.getInstance(), //
-                        array(42, 43, UNKNOWN_OBJECT, "somestring"), //
-                        array("(int)", "(int)", "(object)", "(object)"));
-    }
-
-    /**
-     * Test without fallback handler and unreachable.
-     */
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class Fallback3 extends ValueNode {
-
-        @Specialization
-        String f1(int a) {
-            return "(int)";
-        }
-
-        @Specialization(guards = "notInt(a)")
-        String f2(Object a) {
-            return "(object)";
-        }
-
-        boolean notInt(Object value) {
-            return !(value instanceof Integer);
-        }
-
-    }
-
-    /**
-     * Tests the contents of the {@link UnsupportedSpecializationException} contents in polymorphic
-     * nodes.
-     */
-    @Test
-    public void testFallback4() {
-        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
-
-        Assert.assertEquals("(int)", executeWith(node, 1));
-        Assert.assertEquals("(boolean)", executeWith(node, true));
-        try {
-            executeWith(node, UNKNOWN_OBJECT);
-            Assert.fail();
-        } catch (UnsupportedSpecializationException e) {
-            Assert.assertEquals(node.getNode(), e.getNode());
-            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
-            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
-        }
-    }
-
-    /**
-     * Test without fallback handler and unreachable.
-     */
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class Fallback4 extends ValueNode {
-
-        @Specialization
-        String f1(int a) {
-            return "(int)";
-        }
-
-        @Specialization
-        String f2(boolean a) {
-            return "(boolean)";
-        }
-    }
-
-    /**
-     * Tests the contents of the {@link UnsupportedSpecializationException} contents in monomorphic
-     * nodes.
-     */
-    @Test
-    public void testFallback5() {
-        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
-
-        Assert.assertEquals("(int)", executeWith(node, 1));
-        try {
-            executeWith(node, UNKNOWN_OBJECT);
-            Assert.fail();
-        } catch (UnsupportedSpecializationException e) {
-            Assert.assertEquals(node.getNode(), e.getNode());
-            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
-            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
-        }
-    }
-
-    // test without fallback handler and unreachable
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class Fallback5 extends ValueNode {
-
-        @Specialization
-        String f1(int a) {
-            return "(int)";
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory;
-import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory;
-import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-
-public class ImplicitCastTest {
-
-    @TypeSystem({int.class, String.class, boolean.class})
-    static class ImplicitCast0Types {
-
-        @ImplicitCast
-        static boolean castInt(int intvalue) {
-            return intvalue == 1 ? true : false;
-        }
-
-        @ImplicitCast
-        static boolean castString(String strvalue) {
-            return strvalue.equals("1");
-        }
-
-    }
-
-    @TypeSystemReference(ImplicitCast0Types.class)
-    @NodeChild(value = "operand", type = ImplicitCast0Node.class)
-    abstract static class ImplicitCast0Node extends ValueNode {
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object value2);
-
-        @Specialization
-        public String op1(String value) {
-            return value;
-        }
-
-        @Specialization
-        public boolean op1(boolean value) {
-            return value;
-        }
-
-    }
-
-    @Test
-    public void testImplicitCast0() {
-        ImplicitCast0Node node = ImplicitCast0NodeFactory.create(null);
-        TestRootNode<ImplicitCast0Node> root = new TestRootNode<>(node);
-        root.adoptChildren();
-        Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
-        Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true));
-    }
-
-    @TypeSystemReference(ImplicitCast0Types.class)
-    @NodeChild(value = "operand", type = ImplicitCast1Node.class)
-    abstract static class ImplicitCast1Node extends ValueNode {
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object operand);
-
-        @Specialization
-        public String op0(String value) {
-            return value;
-        }
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "op1")
-        public boolean op2(boolean value) {
-            return value;
-        }
-
-    }
-
-    @Test
-    public void testImplicitCast1() {
-        ImplicitCast1Node node = ImplicitCast1NodeFactory.create(null);
-        TestRootNode<ImplicitCast1Node> root = new TestRootNode<>(node);
-        root.adoptChildren();
-        Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
-        Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true));
-    }
-
-    @TypeSystemReference(ImplicitCast0Types.class)
-    @NodeChildren({@NodeChild(value = "operand0", type = ImplicitCast2Node.class), @NodeChild(value = "operand1", type = ImplicitCast2Node.class, executeWith = "operand0")})
-    // TODO temporary workaround
-    abstract static class ImplicitCast2Node extends ValueNode {
-
-        @Specialization
-        public String op0(String v0, String v1) {
-            return v0 + v1;
-        }
-
-        @SuppressWarnings("unused")
-        @Specialization(rewriteOn = RuntimeException.class)
-        public boolean op1(boolean v0, boolean v1) throws RuntimeException {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "op1")
-        public boolean op2(boolean v0, boolean v1) {
-            return v0 && v1;
-        }
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object v1);
-
-        public abstract Object executeEvaluated(VirtualFrame frame, Object v1, Object v2);
-
-        public abstract Object executeEvaluated(VirtualFrame frame, boolean v1, boolean v2);
-
-    }
-
-    @Test
-    public void testImplicitCast2() {
-        ImplicitCast2Node node = ImplicitCast2NodeFactory.create(null, null);
-        TestRootNode<ImplicitCast2Node> root = new TestRootNode<>(node);
-        root.adoptChildren();
-        Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1));
-        Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1));
-        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true));
-    }
-
-    @TypeSystem({String.class, boolean.class})
-    static class ImplicitCastError1 {
-
-        @ImplicitCast
-        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
-        static String castInvalid(@SuppressWarnings("unused") String value) {
-            throw new AssertionError();
-        }
-
-    }
-
-    @TypeSystem({String.class, boolean.class})
-    static class ImplicitCastError2 {
-
-        @ImplicitCast
-        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
-        static String castInvalid(@SuppressWarnings("unused") String value) {
-            throw new AssertionError();
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ImportGuardsTestFactory.ImportGuards6Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class ImportGuardsTest {
-
-    @ImportStatic(Imports0.class)
-    @NodeChild("a")
-    static class ImportGuards0 extends ValueNode {
-
-        @Specialization(guards = "staticGuard(a)")
-        int f0(int a) {
-            return a;
-        }
-    }
-
-    @NodeChild("a")
-    @ImportStatic(Imports0.class)
-    static class ImportGuards1 extends ValueNode {
-
-        @ExpectError("Error parsing expression 'nonStaticGuard(a)': The method nonStaticGuard is undefined for the enclosing scope.")
-        @Specialization(guards = "nonStaticGuard(a)")
-        int f1(int a) {
-            return a;
-        }
-
-        @ExpectError("Error parsing expression 'protectedGuard(a)': The method protectedGuard is undefined for the enclosing scope.")
-        @Specialization(guards = "protectedGuard(a)")
-        int f2(int a) {
-            return a;
-        }
-
-        @ExpectError("Error parsing expression 'packageGuard(a)': The method packageGuard is undefined for the enclosing scope.")
-        @Specialization(guards = "packageGuard(a)")
-        int f3(int a) {
-            return a;
-        }
-
-        @ExpectError("Error parsing expression 'privateGuard(a)': The method privateGuard is undefined for the enclosing scope.")
-        @Specialization(guards = "privateGuard(a)")
-        int f4(int a) {
-            return a;
-        }
-    }
-
-    public static class Imports0 {
-        public static boolean staticGuard(int a) {
-            return a == 0;
-        }
-
-        public boolean nonStaticGuard(int a) {
-            return a == 0;
-        }
-
-        protected static boolean protectedGuard(int a) {
-            return a == 0;
-        }
-
-        static boolean packageGuard(int a) {
-            return a == 0;
-        }
-
-        @SuppressWarnings("unused")
-        private static boolean privateGuard(int a) {
-            return a == 0;
-        }
-
-    }
-
-    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports1' must be public.")
-    @NodeChild("a")
-    @ImportStatic(Imports1.class)
-    static class ImportGuards2 extends ValueNode {
-
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    static class Imports1 {
-
-    }
-
-    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports2' must be public.")
-    @NodeChild("a")
-    @ImportStatic(Imports2.class)
-    static class ImportGuards3 extends ValueNode {
-
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @ExpectError("The specified import guard class 'boolean' is not a declared type.")
-    @NodeChild("a")
-    @ImportStatic(boolean.class)
-    static class ImportGuards4 extends ValueNode {
-
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    private static class Imports2 {
-
-    }
-
-    @ExpectError("At least import guard classes must be specified.")
-    @NodeChild("a")
-    @ImportStatic({})
-    static class ImportGuards5 extends ValueNode {
-
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testImportGuards6() {
-        // should use the guar declared in the node instead of the imported one.
-        assertRuns(ImportGuards6Factory.getInstance(), //
-                        array(1, 1), //
-                        array(1, 1));
-    }
-
-    @ImportStatic(Imports0.class)
-    @NodeChild("a")
-    static class ImportGuards6 extends ValueNode {
-
-        static boolean staticGuard(int a) {
-            return a == 1;
-        }
-
-        @Specialization(guards = "staticGuard(a)")
-        int f0(int a) {
-            return a;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class InsertBeforeTest {
-
-    @NodeChild("a")
-    static class InsertBefore1Base extends ValueNode {
-
-        @Specialization(guards = "a == 1")
-        int f1(int a) {
-            return a;
-        }
-
-        @Specialization(guards = "a == 2")
-        int f3(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1T1 extends InsertBefore1Base {
-
-        @Specialization
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1T2 extends InsertBefore1Base {
-
-        @Specialization(guards = "a == 0", insertBefore = "f1")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1T3 extends InsertBefore1Base {
-
-        @Specialization(guards = "a == 0", insertBefore = "f3")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int).",
-                    "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
-    static class InsertBefore1T4 extends InsertBefore1Base {
-
-        @Specialization(insertBefore = "f1")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
-    static class InsertBefore1T5 extends InsertBefore1Base {
-
-        boolean g0(int a) {
-            return a == 0;
-        }
-
-        @Specialization(insertBefore = "f3")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1T6part1 extends InsertBefore1Base {
-
-        boolean g0(int a) {
-            return a == 0;
-        }
-
-        @Specialization(insertBefore = "f1", guards = "a == 0")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1T6part2 extends InsertBefore1T6part1 {
-
-        @Specialization(insertBefore = "f0", guards = "a == 3")
-        int f(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1Error1 extends InsertBefore1Base {
-
-        @ExpectError("Specializations can only be inserted before specializations in superclasses.")
-        @Specialization(insertBefore = "f0")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild("a")
-    static class InsertBefore1Error2 extends InsertBefore1Base {
-
-        @ExpectError("The referenced specialization 'asdf' could not be found.")
-        @Specialization(insertBefore = "asdf")
-        int f0(int a) {
-            return a;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/IntegerLiteralGuardsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.BinaryLiteralTestFactory;
-import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.DecimalLiteralTestFactory;
-import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.HexLiteralTestFactory;
-import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.OctalLiteralTestFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class IntegerLiteralGuardsTest {
-
-    @Test
-    public void testDecimalLiteral() {
-        CallTarget root = createCallTarget(DecimalLiteralTestFactory.getInstance());
-        assertEquals("do1", root.call(14));
-    }
-
-    @NodeChild
-    static class DecimalLiteralTest extends ValueNode {
-        @Specialization(guards = "value == 14")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testHexLiteral() {
-        CallTarget root = createCallTarget(HexLiteralTestFactory.getInstance());
-        assertEquals("do1", root.call(20));
-    }
-
-    @NodeChild
-    static class HexLiteralTest extends ValueNode {
-        @Specialization(guards = "value == 0x14")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testOctalLiteral() {
-        CallTarget root = createCallTarget(OctalLiteralTestFactory.getInstance());
-        assertEquals("do1", root.call(12));
-    }
-
-    @NodeChild
-    static class OctalLiteralTest extends ValueNode {
-        @Specialization(guards = "value == 014")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testBinaryLiteral() {
-        CallTarget root = createCallTarget(BinaryLiteralTestFactory.getInstance());
-        assertEquals("do1", root.call(50));
-    }
-
-    @NodeChild
-    static class BinaryLiteralTest extends ValueNode {
-        @Specialization(guards = "value == 0b110010")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.LazyClassLoadingTestFactory.TestNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class LazyClassLoadingTest {
-    @Test
-    public void test() {
-        String factoryName = TestNodeFactory.class.getName();
-        String nodeName = factoryName + "$" + TestNode.class.getSimpleName() + "Gen";
-        Assert.assertTrue(isLoaded(factoryName));
-        Assert.assertFalse(isLoaded(nodeName));
-
-        NodeFactory<TestNode> factory = TestNodeFactory.getInstance();
-        Assert.assertTrue(isLoaded(factoryName));
-        Assert.assertTrue(isLoaded(nodeName));
-
-        Assert.assertFalse(isLoaded(nodeName + "$UninitializedNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$BaseNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$IntNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
-
-        TestRootNode<TestNode> root = TestHelper.createRoot(factory);
-
-        Assert.assertTrue(isLoaded(nodeName + "$UninitializedNode_"));
-        Assert.assertTrue(isLoaded(nodeName + "$BaseNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$IntNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
-
-        Assert.assertEquals(42, TestHelper.executeWith(root, 42));
-
-        Assert.assertTrue(isLoaded(nodeName + "$IntNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
-        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
-
-        Assert.assertEquals(true, TestHelper.executeWith(root, true));
-
-        Assert.assertTrue(isLoaded(nodeName + "$IntNode_"));
-        Assert.assertTrue(isLoaded(nodeName + "$BooleanNode_"));
-        Assert.assertTrue(isLoaded(nodeName + "$PolymorphicNode_"));
-    }
-
-    private boolean isLoaded(String className) {
-        ClassLoader classLoader = getClass().getClassLoader();
-        Method m;
-        try {
-            m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
-            m.setAccessible(true);
-            return m.invoke(classLoader, className) != null;
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class TestNode extends ValueNode {
-
-        @Specialization
-        int doInt(int a) {
-            return a;
-        }
-
-        @Specialization
-        boolean doBoolean(boolean a) {
-            return a;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.LimitTestFactory.ConstantLimitTestFactory;
-import com.oracle.truffle.api.dsl.test.LimitTestFactory.DefaultLimit3TestFactory;
-import com.oracle.truffle.api.dsl.test.LimitTestFactory.LocalLimitTestFactory;
-import com.oracle.truffle.api.dsl.test.LimitTestFactory.MethodLimitTestFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class LimitTest {
-
-    @Test
-    public void testDefaultLimit3() {
-        CallTarget root = createCallTarget(DefaultLimit3TestFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        assertEquals(44, root.call(44));
-        try {
-            root.call(45);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class DefaultLimit3Test extends ValueNode {
-        @Specialization(guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-    }
-
-    @Test
-    public void testConstantLimit() {
-        CallTarget root = createCallTarget(ConstantLimitTestFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        try {
-            root.call(44);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class ConstantLimitTest extends ValueNode {
-
-        public static final int LIMIT = 2;
-
-        @Specialization(limit = "LIMIT", guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-    }
-
-    @Test
-    public void testLocalLimit() {
-        CallTarget root = createCallTarget(LocalLimitTestFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        try {
-            root.call(44);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-    }
-
-    @NodeChild
-    static class LocalLimitTest extends ValueNode {
-
-        protected int localLimit = 2;
-
-        @Specialization(limit = "localLimit", guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-    }
-
-    @Test
-    public void testMethodLimit() {
-        MethodLimitTest.invocations = 0;
-        CallTarget root = createCallTarget(MethodLimitTestFactory.getInstance());
-        assertEquals(42, root.call(42));
-        assertEquals(43, root.call(43));
-        try {
-            root.call(44);
-            fail();
-        } catch (UnsupportedSpecializationException e) {
-        }
-        assertEquals(3, MethodLimitTest.invocations);
-    }
-
-    @NodeChild
-    static class MethodLimitTest extends ValueNode {
-
-        static int invocations = 0;
-
-        @Specialization(limit = "calculateLimitFor(cachedValue, invocations)", guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return cachedValue;
-        }
-
-        int calculateLimitFor(int cachedValue, int boundField) {
-            invocations = boundField + 1;
-            return 2;
-        }
-
-    }
-
-    @NodeChild
-    static class LimitErrorTest1 extends ValueNode {
-        @ExpectError("The limit expression has no effect.%")
-        @Specialization(limit = "4")
-        static int do1(int value) {
-            return value;
-        }
-    }
-
-    @NodeChild
-    static class LimitErrorTest2 extends ValueNode {
-        public static final Object CONSTANT = new Object();
-
-        @ExpectError("Incompatible return type Object. Limit expressions must return int.")
-        @Specialization(limit = "CONSTANT", guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return value;
-        }
-    }
-
-    @NodeChild
-    static class LimitErrorTest3 extends ValueNode {
-
-        public static final Object CONSTANT = new Object();
-
-        @ExpectError("Limit expressions must not bind dynamic parameter values.")
-        @Specialization(limit = "value", guards = "value == cachedValue")
-        static int do1(int value, @Cached("value") int cachedValue) {
-            return value;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MergeSpecializationsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestCachedNodeFactory;
-import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-
-public class MergeSpecializationsTest {
-
-    private static final int THREADS = 50;
-
-    @NodeChild
-    @SuppressWarnings("unused")
-    abstract static class TestNode extends ValueNode {
-
-        @Specialization
-        int s1(int a) {
-            return 1;
-        }
-
-        @Specialization
-        int s2(long a) {
-            return 2;
-        }
-
-        @Specialization
-        int s3(double a) {
-            return 3;
-        }
-    }
-
-    @NodeChild
-    @SuppressWarnings("unused")
-    abstract static class TestCachedNode extends ValueNode {
-
-        @Specialization(guards = "a == cachedA", limit = "3")
-        int s1(int a, @Cached("a") int cachedA) {
-            return 1;
-        }
-
-        @Specialization
-        int s2(long a) {
-            return 2;
-        }
-
-        @Specialization
-        int s3(double a) {
-            return 3;
-        }
-    }
-
-    @Test
-    public void testMultithreadedMergeInOrder() {
-        for (int i = 0; i < 100; i++) {
-            multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
-        }
-    }
-
-    @Test
-    public void testMultithreadedMergeReverse() {
-        for (int i = 0; i < 100; i++) {
-            multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1.0, 1L << 32, 1), 3, 2, 1);
-        }
-    }
-
-    @Test
-    public void testMultithreadedMergeCachedInOrder() {
-        for (int i = 0; i < 100; i++) {
-            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
-        }
-    }
-
-    @Test
-    public void testMultithreadedMergeCachedTwoEntries() {
-        for (int i = 0; i < 100; i++) {
-            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 1.0), 1, 1, 3);
-        }
-    }
-
-    @Test
-    public void testMultithreadedMergeCachedThreeEntries() {
-        for (int i = 0; i < 100; i++) {
-            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 3), 1, 1, 1);
-        }
-    }
-
-    private static <T extends ValueNode> void multithreadedMerge(NodeFactory<T> factory, final Executions executions, int... order) {
-        assertEquals(3, order.length);
-        final TestRootNode<T> node = createRoot(factory);
-
-        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
-
-        final CountDownLatch beforeFirst = new CountDownLatch(1);
-        final CountDownLatch executedFirst = new CountDownLatch(THREADS);
-
-        final CountDownLatch beforeSecond = new CountDownLatch(1);
-        final CountDownLatch executedSecond = new CountDownLatch(THREADS);
-
-        final CountDownLatch beforeThird = new CountDownLatch(1);
-        final CountDownLatch executedThird = new CountDownLatch(THREADS);
-
-        Thread[] threads = new Thread[THREADS];
-        for (int i = 0; i < threads.length; i++) {
-            threads[i] = new Thread(new Runnable() {
-                public void run() {
-                    threadsStarted.countDown();
-
-                    MergeSpecializationsTest.await(beforeFirst);
-                    executeWith(node, executions.firstValue);
-                    executedFirst.countDown();
-
-                    MergeSpecializationsTest.await(beforeSecond);
-                    executeWith(node, executions.secondValue);
-                    executedSecond.countDown();
-
-                    MergeSpecializationsTest.await(beforeThird);
-                    executeWith(node, executions.thirdValue);
-                    executedThird.countDown();
-                }
-            });
-            threads[i].start();
-        }
-
-        final SpecializedNode gen = (SpecializedNode) node.getNode();
-
-        final SpecializationNode start0 = gen.getSpecializationNode();
-        assertEquals("UninitializedNode_", start0.getClass().getSimpleName());
-
-        await(threadsStarted);
-        beforeFirst.countDown();
-        await(executedFirst);
-
-        final SpecializationNode start1 = gen.getSpecializationNode();
-        assertEquals("S" + order[0] + "Node_", start1.getClass().getSimpleName());
-        assertEquals("UninitializedNode_", nthChild(1, start1).getClass().getSimpleName());
-
-        beforeSecond.countDown();
-        await(executedSecond);
-
-        final SpecializationNode start2 = gen.getSpecializationNode();
-        Arrays.sort(order, 0, 2);
-        assertEquals("PolymorphicNode_", start2.getClass().getSimpleName());
-        assertEquals("S" + order[0] + "Node_", nthChild(1, start2).getClass().getSimpleName());
-        assertEquals("S" + order[1] + "Node_", nthChild(2, start2).getClass().getSimpleName());
-        assertEquals("UninitializedNode_", nthChild(3, start2).getClass().getSimpleName());
-
-        beforeThird.countDown();
-        await(executedThird);
-
-        final SpecializationNode start3 = gen.getSpecializationNode();
-        Arrays.sort(order);
-        assertEquals("PolymorphicNode_", start3.getClass().getSimpleName());
-        assertEquals("S" + order[0] + "Node_", nthChild(1, start3).getClass().getSimpleName());
-        assertEquals("S" + order[1] + "Node_", nthChild(2, start3).getClass().getSimpleName());
-        assertEquals("S" + order[2] + "Node_", nthChild(3, start3).getClass().getSimpleName());
-        assertEquals("UninitializedNode_", nthChild(4, start3).getClass().getSimpleName());
-
-        for (Thread thread : threads) {
-            try {
-                thread.join();
-            } catch (InterruptedException e) {
-                fail("interrupted");
-            }
-        }
-    }
-
-    private static class Executions {
-        public final Object firstValue;
-        public final Object secondValue;
-        public final Object thirdValue;
-
-        public Executions(Object firstValue, Object secondValue, Object thirdValue) {
-            this.firstValue = firstValue;
-            this.secondValue = secondValue;
-            this.thirdValue = thirdValue;
-        }
-    }
-
-    private static void await(final CountDownLatch latch) {
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            fail("interrupted");
-        }
-    }
-
-    private static Node firstChild(Node node) {
-        return node.getChildren().iterator().next();
-    }
-
-    private static Node nthChild(int n, Node node) {
-        if (n == 0) {
-            return node;
-        } else {
-            return nthChild(n - 1, firstChild(node));
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,609 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardCompareWithFieldTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardComplexTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualByteIntTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualIntLongTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualLongIntTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualShortIntTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardFieldTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterEqualTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessEqualTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMethodTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleAndMethodTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleOrMethodTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardNotTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardOrTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardStaticFieldTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardStaticFinalFieldCompareTestFactory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardUnboundMethodTestFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-@SuppressWarnings("unused")
-public class MethodGuardsTest {
-
-    @Test
-    public void testGuardEqual() {
-        CallTarget root = createCallTarget(GuardEqualTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(1));
-    }
-
-    @NodeChild
-    static class GuardEqualTest extends ValueNode {
-        @Specialization(guards = "value == 1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardEqualIntLong() {
-        CallTarget root = createCallTarget(GuardEqualIntLongTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(1));
-    }
-
-    @NodeChild
-    static class GuardEqualIntLongTest extends ValueNode {
-        @Specialization(guards = "1 == value")
-        static String do1(long value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(long value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardEqualByteInt() {
-        CallTarget root = createCallTarget(GuardEqualByteIntTestFactory.getInstance());
-        assertEquals("do1", root.call((byte) 1));
-        assertEquals("do2", root.call((byte) 2));
-        assertEquals("do1", root.call((byte) 1));
-    }
-
-    @NodeChild
-    static class GuardEqualByteIntTest extends ValueNode {
-        @Specialization(guards = "value == 1")
-        static String do1(byte value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(byte value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardEqualShortInt() {
-        CallTarget root = createCallTarget(GuardEqualShortIntTestFactory.getInstance());
-        assertEquals("do1", root.call((short) 1));
-        assertEquals("do2", root.call((short) 2));
-        assertEquals("do1", root.call((short) 1));
-    }
-
-    @NodeChild
-    static class GuardEqualShortIntTest extends ValueNode {
-        @Specialization(guards = "value == 1")
-        static String do1(short value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(short value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardEqualLongInt() {
-        CallTarget root = createCallTarget(GuardEqualLongIntTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(1));
-    }
-
-    @NodeChild
-    static class GuardEqualLongIntTest extends ValueNode {
-        @Specialization(guards = "value == 1")
-        static String do1(long value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(long value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardLessEqual() {
-        CallTarget root = createCallTarget(GuardLessEqualTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(0));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardLessEqualTest extends ValueNode {
-        @Specialization(guards = "value <= 1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardLess() {
-        CallTarget root = createCallTarget(GuardLessTestFactory.getInstance());
-        assertEquals("do1", root.call(0));
-        assertEquals("do2", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(-1));
-    }
-
-    @NodeChild
-    static class GuardLessTest extends ValueNode {
-        @Specialization(guards = "value < 1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardGreaterEqual() {
-        CallTarget root = createCallTarget(GuardGreaterEqualTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(0));
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardGreaterEqualTest extends ValueNode {
-        @Specialization(guards = "value >= 1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardGreater() {
-        CallTarget root = createCallTarget(GuardGreaterTestFactory.getInstance());
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(0));
-        assertEquals("do2", root.call(1));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardGreaterTest extends ValueNode {
-        @Specialization(guards = "value > 1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardOr() {
-        CallTarget root = createCallTarget(GuardOrTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(0));
-        assertEquals("do2", root.call(2));
-        assertEquals("do2", root.call(-1));
-    }
-
-    @NodeChild
-    static class GuardOrTest extends ValueNode {
-        @Specialization(guards = "value == 1 || value == 0")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardNot() {
-        CallTarget root = createCallTarget(GuardNotTestFactory.getInstance());
-        assertEquals("do1", root.call(0));
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(1));
-        assertEquals("do1", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardNotTest extends ValueNode {
-        @Specialization(guards = "!(value == 1)")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardField() {
-        CallTarget root = createCallTarget(GuardFieldTestFactory.getInstance());
-        GuardFieldTest node = getNode(root);
-        node.field = true;
-        assertEquals("do1", root.call(0));
-        assertEquals("do1", root.call(2));
-
-        node.field = false;
-        try {
-            root.call(2);
-            fail("expected Assertion failed");
-        } catch (AssertionError e) {
-        }
-    }
-
-    @NodeChild
-    static class GuardFieldTest extends ValueNode {
-
-        boolean field;
-
-        @Specialization(guards = "field")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardCompareWithField() {
-        CallTarget root = createCallTarget(GuardCompareWithFieldTestFactory.getInstance());
-        GuardCompareWithFieldTest node = getNode(root);
-        node.field = 1;
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-
-        node.field = 2;
-        assertEquals("do2", root.call(1));
-        assertEquals("do1", root.call(2));
-    }
-
-    @NodeChild
-    static class GuardCompareWithFieldTest extends ValueNode {
-
-        int field;
-
-        @Specialization(guards = "value == field")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardStaticField() {
-        CallTarget root = createCallTarget(GuardStaticFieldTestFactory.getInstance());
-        GuardStaticFieldTest.field = true;
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(2));
-        GuardStaticFieldTest.field = false;
-        try {
-            root.call(2);
-            fail("expected Assertion failed");
-        } catch (AssertionError e) {
-        }
-    }
-
-    @NodeChild
-    static class GuardStaticFieldTest extends ValueNode {
-
-        static boolean field;
-
-        @Specialization(guards = "field")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardStaticFinalFieldCompare() {
-        CallTarget root = createCallTarget(GuardStaticFinalFieldCompareTestFactory.getInstance());
-        GuardStaticFieldTest.field = true;
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-    }
-
-    @NodeChild
-    static class GuardStaticFinalFieldCompareTest extends ValueNode {
-
-        protected static final int FIELD = 1;
-
-        @Specialization(guards = "value == FIELD")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization(guards = "value != FIELD")
-        static String do2(int value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testGuardMethod() {
-        CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardMethodTest extends ValueNode {
-
-        @Specialization(guards = "method(value)")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        boolean method(int value) {
-            return value == 1;
-        }
-    }
-
-    @Test
-    public void testGuardUnboundMethodField() {
-        CallTarget root = createCallTarget(GuardUnboundMethodTestFactory.getInstance());
-        GuardUnboundMethodTest node = getNode(root);
-        node.hiddenValue = true;
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(2));
-        node.hiddenValue = false;
-        try {
-            root.call(2);
-            fail("expected Assertion failed");
-        } catch (AssertionError e) {
-        }
-    }
-
-    @NodeChild
-    static class GuardUnboundMethodTest extends ValueNode {
-
-        private boolean hiddenValue;
-
-        @Specialization(guards = "method()")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        boolean method() {
-            return hiddenValue;
-        }
-    }
-
-    @Test
-    public void testStaticGuardMethod() {
-        CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(2));
-        assertEquals("do1", root.call(1));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class StaticGuardMethodTest extends ValueNode {
-
-        @Specialization(guards = "method(value)")
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        static boolean method(int value) {
-            return value == 1;
-        }
-    }
-
-    @Test
-    public void testMultipleGuardAndMethod() {
-        CallTarget root = createCallTarget(GuardMultipleAndMethodTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(3));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardMultipleAndMethodTest extends ValueNode {
-
-        @Specialization(guards = {"method1(value)", "method2(value)"})
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        boolean method1(int value) {
-            return value >= 1;
-        }
-
-        boolean method2(int value) {
-            return value <= 2;
-        }
-    }
-
-    @Test
-    public void testMultipleGuardOrMethod() {
-        CallTarget root = createCallTarget(GuardMultipleOrMethodTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(3));
-        assertEquals("do2", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardMultipleOrMethodTest extends ValueNode {
-
-        @Specialization(guards = {"method1(value) || method2(value)"})
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        boolean method1(int value) {
-            return value == 1;
-        }
-
-        boolean method2(int value) {
-            return value == 2;
-        }
-    }
-
-    @Test
-    public void testComplexGuard() {
-        CallTarget root = createCallTarget(GuardComplexTestFactory.getInstance());
-        assertEquals("do1", root.call(1));
-        assertEquals("do1", root.call(2));
-        assertEquals("do2", root.call(3));
-        assertEquals("do1", root.call(0));
-    }
-
-    @NodeChild
-    static class GuardComplexTest extends ValueNode {
-
-        int field1 = 1;
-        static int field2 = 2;
-
-        @Specialization(guards = {"method2(method1(field1 == 1), value <= 2)", "field2 == 2"})
-        static String do1(int value) {
-            return "do1";
-        }
-
-        @Specialization
-        static String do2(int value) {
-            return "do2";
-        }
-
-        static boolean method1(boolean value) {
-            return value;
-        }
-
-        boolean method2(boolean value1, boolean value2) {
-            return value1 && value2;
-        }
-    }
-
-    @NodeChild
-    static class ErrorGuardNotTest extends ValueNode {
-        @ExpectError("Error parsing expression '!value == 1': The operator ! is undefined for the argument type int.")
-        @Specialization(guards = "!value == 1")
-        static String do1(int value) {
-            return "do1";
-        }
-    }
-
-    @NodeChild
-    static class ErrorIncompatibleReturnTypeTest extends ValueNode {
-
-        @ExpectError("Incompatible return type int. Guards must return boolean.")
-        @Specialization(guards = "1")
-        static String do1(int value) {
-            return "do1";
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments0Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments1Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble0Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble1Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble2Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble3Factory;
-import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsSingle2Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class MethodGuardsWithArgumentsTest {
-
-    @Test
-    public void testMArguments0() {
-        TestRootNode<MArguments0> root = createRoot(MArguments0Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root));
-    }
-
-    abstract static class MArguments0 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @Specialization(guards = "guard()")
-        int do1() {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testMArguments1() {
-        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root));
-    }
-
-    abstract static class MArguments1 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @Specialization(guards = "guard()")
-        int do1() {
-            return 42;
-        }
-    }
-
-    @Test
-    public void testMArgumentsSingle0() {
-        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("a")
-    abstract static class MArgumentsSingle0 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @Specialization(guards = "guard()")
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsSingle1() {
-        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("a")
-    abstract static class MArgumentsSingle1 extends ValueNode {
-
-        static boolean guard(int a) {
-            return a == 42;
-        }
-
-        @Specialization(guards = "guard(a)")
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsSingle2() {
-        TestRootNode<MArgumentsSingle2> root = createRoot(MArgumentsSingle2Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42));
-    }
-
-    @NodeChild("a")
-    abstract static class MArgumentsSingle2 extends ValueNode {
-
-        static boolean guard(int a1, int a2) {
-            return a1 == 42 && a2 == 42;
-        }
-
-        @Specialization(guards = "guard(a,a)")
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsDouble0() {
-        TestRootNode<MArgumentsDouble0> root = createRoot(MArgumentsDouble0Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42, 0));
-    }
-
-    @NodeChild("a")
-    abstract static class MArgumentsDouble0 extends ValueNode {
-
-        static boolean guard(int a1, Object a2) {
-            return a1 == 42 && a2.equals(new Integer(42));
-        }
-
-        @Specialization(guards = "guard(a,a)")
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsDouble1() {
-        TestRootNode<MArgumentsDouble1> root = createRoot(MArgumentsDouble1Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42, 41));
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class MArgumentsDouble1 extends ValueNode {
-
-        static boolean guard(int a1, double a2) {
-            return a1 == 42 && a2 == 41;
-        }
-
-        @Specialization(guards = "guard(a,b)")
-        int do1(int a, @SuppressWarnings("unused") double b) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsDouble2() {
-        TestRootNode<MArgumentsDouble2> root = createRoot(MArgumentsDouble2Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42, 41.0));
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class MArgumentsDouble2 extends ValueNode {
-
-        static boolean guard(double a1, int a2) {
-            return a1 == 41 && a2 == 42;
-        }
-
-        @Specialization(guards = "guard(b,a)")
-        int do1(int a, @SuppressWarnings("unused") double b) {
-            return a;
-        }
-    }
-
-    @Test
-    public void testMArgumentsDouble3() {
-        TestRootNode<MArgumentsDouble3> root = createRoot(MArgumentsDouble3Factory.getInstance());
-        Assert.assertEquals(42, executeWith(root, 42, 41.0));
-    }
-
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class MArgumentsDouble3 extends ValueNode {
-
-        static boolean guard(Object a1, double a2) {
-            return new Double(41.0).equals(a1) && a2 == 41;
-        }
-
-        @Specialization(guards = "guard(b,b)")
-        int do1(int a, @SuppressWarnings("unused") double b) {
-            return a;
-        }
-    }
-
-    abstract static class MArgumentsError0 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @ExpectError("Error parsing expression 'guard(': -- line 1 col 7: \")\" expected%")
-        @Specialization(guards = "guard(")
-        int do1() {
-            return 42;
-        }
-    }
-
-    abstract static class MArgumentsError1 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @ExpectError("Error parsing expression 'guard)': -- line 1 col 6: EOF expected%")
-        @Specialization(guards = "guard)")
-        int do1() {
-            return 42;
-        }
-
-    }
-
-    abstract static class MArgumentsError2 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
-        @Specialization(guards = "guard(a)")
-        int do1() {
-            return 42;
-        }
-    }
-
-    @NodeChild("b")
-    abstract static class MArgumentsError3 extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
-        @Specialization(guards = "guard(a)")
-        int do1(int b) {
-            return b;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NameDuplicationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NameDuplicationTest {
-
-    @NodeChild
-    abstract static class Test0 extends ValueNode {
-
-        @Specialization
-        int base(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild
-    abstract static class Test1 extends ValueNode {
-
-        @Specialization
-        int generic(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild
-    abstract static class Test2 extends ValueNode {
-
-        @Specialization
-        int polymorphic(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChild
-    abstract static class Test3 extends ValueNode {
-
-        @Specialization
-        int uninitialized(int a) {
-            return a;
-        }
-
-    }
-
-    abstract static class AddNode extends ValueNode {
-
-        @Specialization
-        int add() {
-            return 0;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NegatedGuardsTestFactory.NegatedGuardNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NegatedGuardsTest {
-
-    @Test
-    public void testGuardGlobal() {
-        TestRootNode<NegatedGuardNode> root = createRoot(NegatedGuardNodeFactory.getInstance());
-        Assert.assertEquals(42, executeWith(root));
-    }
-
-    abstract static class NegatedGuardNode extends ValueNode {
-
-        static boolean guard() {
-            return true;
-        }
-
-        @Specialization(guards = "!guard()")
-        int do1() {
-            throw new AssertionError();
-        }
-
-        @Specialization
-        int do2() {
-            return 42; // the generic answer to all questions
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.JustFrameTestNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.NoParameterTestNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectInterfaceNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectPrimitiveTestNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectStringTestNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.PrimitiveTestNodeGen;
-import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.TypesNotInTypeSystemTestNodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class NoTypeSystemTest {
-
-    abstract static class DummyChild extends Node {
-        abstract Object execute();
-    }
-
-    abstract static class NoParameterTestNode extends Node {
-        abstract void execute();
-
-        @Specialization
-        void s1() {
-        }
-    }
-
-    @Test
-    public void testNoParameter() {
-        NoParameterTestNodeGen.create().execute();
-    }
-
-    abstract static class JustFrameTestNode extends Node {
-
-        abstract void execute(VirtualFrame frames);
-
-        @Specialization
-        void s1(@SuppressWarnings("unused") VirtualFrame frame) {
-        }
-    }
-
-    @Test
-    public void testJustFrame() {
-        JustFrameTestNodeGen.create().execute(null);
-    }
-
-    abstract static class PrimitiveTestNode extends Node {
-
-        abstract int execute(int primitive);
-
-        @Specialization
-        int test(int primitive) {
-            return primitive;
-        }
-
-    }
-
-    @Test
-    public void testPrimitive() {
-        Assert.assertEquals(42, PrimitiveTestNodeGen.create().execute(42));
-    }
-
-    abstract static class ObjectInterfaceNode extends Node {
-
-        abstract CharSequence execute(Object operand);
-
-        @Specialization
-        CharSequence s1(CharSequence operandSpecial) {
-            return operandSpecial;
-        }
-    }
-
-    @Test
-    public void testObjectInterface() {
-        Assert.assertEquals("42", ObjectInterfaceNodeGen.create().execute("42"));
-    }
-
-    abstract static class ObjectPrimitiveTestNode extends Node {
-
-        abstract int execute(Object primitive);
-
-        @Specialization
-        int s1(int primitive) {
-            return primitive;
-        }
-
-    }
-
-    @Test
-    public void testObjectPrimitiveTest() {
-        Assert.assertEquals(42, ObjectPrimitiveTestNodeGen.create().execute(42));
-    }
-
-    abstract static class ObjectStringTestNode extends Node {
-
-        abstract String execute(Object operand);
-
-        @Specialization
-        String s1(String operand) {
-            return operand;
-        }
-    }
-
-    @Test
-    public void testObjectStringTest() {
-        Assert.assertEquals("42", ObjectStringTestNodeGen.create().execute("42"));
-    }
-
-    abstract static class TypesNotInTypeSystemTest extends Node {
-
-        abstract Object execute(Object primitive);
-
-        abstract int executeInt(Object primitive) throws UnexpectedResultException;
-
-        abstract double executeDouble(Object primitive) throws UnexpectedResultException;
-
-        abstract String executeString(Object primitive) throws UnexpectedResultException;
-
-        abstract int[] executeIntArray(Object primitive) throws UnexpectedResultException;
-
-        abstract void executeVoid(Object primitive);
-
-        abstract void executeChar(Object primitive);
-
-        abstract int executeInt(int primitive) throws UnexpectedResultException;
-
-        abstract double executeDouble(double primitive) throws UnexpectedResultException;
-
-        abstract String executeString(String primitive) throws UnexpectedResultException;
-
-        abstract int[] executeIntArray(int[] primitive) throws UnexpectedResultException;
-
-        abstract void executeChar(char primitive);
-
-        @Specialization
-        int s1(int primitive) {
-            return primitive;
-        }
-
-        @Specialization
-        double s2(double primitive) {
-            return (int) primitive;
-        }
-
-        @Specialization
-        String s3(String object) {
-            return object;
-        }
-
-        @Specialization
-        int[] s4(int[] object) {
-            return object;
-        }
-
-        @Specialization
-        void s5(@SuppressWarnings("unused") char object) {
-        }
-
-    }
-
-    @Test
-    public void testTypesNotInTypeSystem() throws UnexpectedResultException {
-        int[] someArray = {1, 2, 3};
-        Assert.assertEquals(42, createTypesNotInTypeSystem().execute(42));
-        Assert.assertEquals(42d, createTypesNotInTypeSystem().execute(42d));
-        Assert.assertEquals(someArray, createTypesNotInTypeSystem().execute(someArray));
-        Assert.assertNull(createTypesNotInTypeSystem().execute((char) 42));
-
-        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt((Object) 42));
-        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble((Object) 42d), 0d);
-        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray((Object) someArray));
-        createTypesNotInTypeSystem().executeChar((Object) (char) 42);
-
-        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt(42));
-        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble(42d), 0d);
-        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray(someArray));
-        createTypesNotInTypeSystem().executeChar((char) 42);
-
-        try {
-            createTypesNotInTypeSystem().executeInt("a");
-            Assert.fail();
-        } catch (UnexpectedResultException e) {
-        }
-
-        try {
-            createTypesNotInTypeSystem().executeDouble("a");
-            Assert.fail();
-        } catch (UnexpectedResultException e) {
-        }
-
-        try {
-            createTypesNotInTypeSystem().executeIntArray("a");
-            Assert.fail();
-        } catch (UnexpectedResultException e) {
-        }
-
-        createTypesNotInTypeSystem().executeChar("a");
-
-    }
-
-    private static TypesNotInTypeSystemTest createTypesNotInTypeSystem() {
-        return TestHelper.createRoot(TypesNotInTypeSystemTestNodeGen.create());
-    }
-
-    abstract static class ErrorImpossibleTypes1 extends Node {
-
-        abstract int execute(int primitive);
-
-        @Specialization
-        int test(int primitive) {
-            return primitive;
-        }
-
-        @ExpectError("The provided return type \"Object\" does not match expected return type \"int\".%")
-        @Specialization
-        Object s2(int arg0) {
-            return arg0;
-        }
-    }
-
-    abstract static class ErrorImpossibleTypes2 extends Node {
-
-        abstract int execute(int primitive);
-
-        @Specialization
-        int test(int primitive) {
-            return primitive;
-        }
-
-        @ExpectError("Method signature (Object) does not match to the expected signature: %")
-        @Specialization
-        int s2(Object arg0) {
-            return (int) arg0;
-        }
-    }
-
-    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
-    abstract static class ErrorMissingNodeChild1 extends Node {
-
-        abstract int execute();
-
-        @Specialization
-        int s1(int arg0) {
-            return arg0;
-        }
-    }
-
-    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
-    @NodeChild(type = DummyChild.class)
-    abstract static class ErrorMissingNodeChild2 extends Node {
-
-        abstract int execute(int arg0);
-
-        @Specialization
-        int s1(int arg0, int arg1) {
-            return arg0 + arg1;
-        }
-    }
-
-    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
-    abstract static class ErrorMissingNodeChild3 extends Node {
-
-        abstract int execute();
-
-        abstract int execute(int arg0);
-
-        @Specialization
-        int s1(int arg0) {
-            return arg0;
-        }
-
-    }
-
-    @ExpectError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.")
-    @NodeChild(type = DummyChild.class)
-    abstract static class ErrorAdditionalNodeChild1 extends Node {
-
-        abstract int execute(int arg0);
-
-        @Specialization
-        int s1(int arg0) {
-            return arg0;
-        }
-    }
-
-    @NodeChild(type = DummyChild.class)
-    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
-    abstract static class ErrorAdditionalNodeChild2 extends Node {
-
-        abstract int execute(int arg0);
-
-        @Specialization
-        int s1(int arg0, int arg1) {
-            return arg0 + arg1;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildNoNameTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.OneArgNoNameFactory;
-import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.ThreeArgsNoNameFactory;
-import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.TwoArgsNoNameFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-
-public class NodeChildNoNameTest {
-
-    @Test
-    public void testOneArg() {
-        ValueNode node = new ConstantNode();
-        OneArgNoName arg = OneArgNoNameFactory.create(node);
-        Assert.assertEquals(node, arg.getChild0());
-        Assert.assertEquals(43, TestHelper.createCallTarget(arg).call());
-    }
-
-    @Test
-    public void testTwoArg() {
-        ValueNode node1 = new ConstantNode();
-        ValueNode node2 = new ConstantNode();
-        TwoArgsNoName arg = TwoArgsNoNameFactory.create(node1, node2);
-        Assert.assertEquals(node1, arg.getChild0());
-        Assert.assertEquals(node2, arg.getChild1());
-        Assert.assertEquals(84, TestHelper.createCallTarget(arg).call());
-    }
-
-    @Test
-    public void testThreeArg() {
-        ValueNode node1 = new ConstantNode();
-        ValueNode node2 = new ConstantNode();
-        ValueNode node3 = new ConstantNode();
-        ThreeArgsNoName arg = ThreeArgsNoNameFactory.create(node1, node2, node3);
-        Assert.assertEquals(node1, arg.getChild0());
-        Assert.assertEquals(node2, arg.getChild1());
-        Assert.assertEquals(node3, arg.getChild2());
-        Assert.assertEquals(126, TestHelper.createCallTarget(arg).call());
-    }
-
-    private static class ConstantNode extends ValueNode {
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return 42;
-        }
-    }
-
-    @NodeChild
-    abstract static class OneArgNoName extends ValueNode {
-
-        public abstract ValueNode getChild0();
-
-        @Specialization
-        int doIt(int exp) {
-            return exp + 1;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild, @NodeChild})
-    abstract static class TwoArgsNoName extends ValueNode {
-
-        public abstract ValueNode getChild0();
-
-        public abstract ValueNode getChild1();
-
-        @Specialization
-        int doIt(int exp0, int exp1) {
-            return exp0 + exp1;
-        }
-    }
-
-    @NodeChildren({@NodeChild, @NodeChild, @NodeChild})
-    abstract static class ThreeArgsNoName extends ValueNode {
-
-        public abstract ValueNode getChild0();
-
-        public abstract ValueNode getChild1();
-
-        public abstract ValueNode getChild2();
-
-        @Specialization
-        int doIt(int exp0, int exp1, int exp2) {
-            return exp0 + exp1 + exp2;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NodeChildTest {
-
-    @Test
-    public void testIntField() {
-        assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call());
-    }
-
-    @NodeChild("child0")
-    abstract static class Base0Node extends ValueNode {
-
-    }
-
-    @NodeChild(value = "child1", type = ValueNode.class)
-    abstract static class Child0Node extends Base0Node {
-
-        @Specialization
-        int intField(int child0, int child1) {
-            return child0 + child1;
-        }
-    }
-
-    @NodeChildren({@NodeChild("child0")})
-    abstract static class Base1Node extends ValueNode {
-
-    }
-
-    @NodeChildren({@NodeChild(value = "child1", type = ValueNode.class)})
-    abstract static class Child1Node extends Base1Node {
-
-        @Specialization
-        int intField(int child0, int child1) {
-            return child0 + child1;
-        }
-    }
-
-    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
-    abstract static class Base2Node extends ValueNode {
-
-    }
-
-    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                    + "The following execute methods do not provide all evaluated values for the expected signature size 3:%")
-    @NodeChildren({@NodeChild(value = "child2", type = ValueNode.class)})
-    abstract static class Child2Node extends Base1Node {
-
-        @ExpectError("Method signature (int, int, int) does not match to the expected signature:%")
-        @Specialization
-        int intField(int child0, int child1, int child2) {
-            return child0 + child1 + child2;
-        }
-    }
-
-    @NodeChildren({@NodeChild(value = "receiver", type = ValueNode.class), @NodeChild(value = "arguments", type = ValueNode[].class)})
-    abstract static class BaseNode extends ValueNode {
-        public abstract ValueNode getReceiver();
-
-        public abstract ValueNode[] getArguments();
-    }
-
-    abstract static class UnaryNode extends BaseNode {
-        @Specialization
-        public int doIt(int value) {
-            return value;
-        }
-    }
-
-    abstract static class BinaryNode extends BaseNode {
-        @Specialization
-        public int doIt(int value0, int value1) {
-            return value0 + value1;
-        }
-    }
-
-    abstract static class TernaryNode extends BaseNode {
-        @Specialization
-        public int doIt(int value0, int value1, int value2) {
-            return value0 + value1 + value2;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory;
-import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NodeFieldTest {
-
-    @Test
-    public void testIntField() {
-        assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call());
-    }
-
-    @NodeField(name = "field", type = int.class)
-    abstract static class IntFieldTestNode extends ValueNode {
-
-        public abstract int getField();
-
-        @Specialization
-        int intField() {
-            return getField();
-        }
-
-    }
-
-    @Test
-    public void testIntFieldNoGetter() {
-        assertEquals(42, createCallTarget(IntFieldNoGetterTestNodeFactory.create(42)).call());
-    }
-
-    @NodeField(name = "field", type = int.class)
-    abstract static class IntFieldNoGetterTestNode extends ValueNode {
-
-        @Specialization
-        int intField(int field) {
-            return field;
-        }
-
-    }
-
-    @Test
-    public void testMultipleFields() {
-        assertEquals(42, createCallTarget(MultipleFieldsTestNodeFactory.create(21, 21)).call());
-    }
-
-    @NodeFields({@NodeField(name = "field0", type = int.class), @NodeField(name = "field1", type = int.class)})
-    abstract static class MultipleFieldsTestNode extends ValueNode {
-
-        public abstract int getField0();
-
-        public abstract int getField1();
-
-        @Specialization
-        int intField() {
-            return getField0() + getField1();
-        }
-
-    }
-
-    @Test
-    public void testStringField() {
-        assertEquals("42", createCallTarget(StringFieldTestNodeFactory.create("42")).call());
-    }
-
-    @NodeField(name = "field", type = String.class)
-    abstract static class StringFieldTestNode extends ValueNode {
-
-        public abstract String getField();
-
-        @Specialization
-        String stringField() {
-            return getField();
-        }
-
-    }
-
-    @Test
-    public void testRewrite() {
-        assertEquals("42", createCallTarget(RewriteTestNodeFactory.create("42")).call());
-    }
-
-    @NodeField(name = "field", type = String.class)
-    abstract static class RewriteTestNode extends ValueNode {
-
-        public abstract String getField();
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        String alwaysRewrite() {
-            throw new RuntimeException();
-        }
-
-        @Specialization(contains = "alwaysRewrite")
-        Object returnField() {
-            return getField();
-        }
-    }
-
-    @Test
-    public void testStringContainer() {
-        assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call());
-    }
-
-    @NodeField(name = "field", type = int.class)
-    abstract static class IntContainerNode extends ValueNode {
-
-        public abstract int getField();
-
-    }
-
-    @NodeField(name = "anotherField", type = String.class)
-    abstract static class TestContainer extends ValueNode {
-
-        @Specialization
-        int containerField(String field) {
-            return field.equals("42") ? 42 : -1;
-        }
-
-    }
-
-    @Test
-    public void testObjectContainer() {
-        assertEquals("42", createCallTarget(ObjectContainerNodeFactory.create("42")).call());
-    }
-
-    @NodeField(name = "object", type = Object.class)
-    abstract static class ObjectContainerNode extends ValueNode {
-
-        public abstract Object getObject();
-
-        @Specialization
-        Object containerField() {
-            return getObject();
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullLiteralGuardsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareNotNullNodeFactory;
-import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareObjectsNullNodeFactory;
-import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareStringNullNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
-
-@SuppressWarnings("unused")
-public class NullLiteralGuardsTest {
-
-    @Test
-    public void testCompareObjectsNull() {
-        CallTarget root = createCallTarget(CompareObjectsNullNodeFactory.getInstance());
-        assertEquals("do1", root.call((Object) null));
-        assertEquals("do2", root.call("42"));
-    }
-
-    abstract static class CompareObjectsNullNode extends ChildrenNode {
-        @Specialization(guards = "value == null")
-        String do1(Object value) {
-            return "do1";
-        }
-
-        @Specialization
-        String do2(Object value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testCompareStringNull() {
-        CallTarget root = createCallTarget(CompareStringNullNodeFactory.getInstance());
-        assertEquals("do1", root.call("42"));
-        assertEquals("do2", root.call((Object) null));
-    }
-
-    abstract static class CompareStringNullNode extends ChildrenNode {
-        @Specialization(guards = "value != null")
-        String do1(String value) {
-            return "do1";
-        }
-
-        @Specialization
-        String do2(Object value) {
-            return "do2";
-        }
-    }
-
-    @Test
-    public void testCompareNotNull() {
-        CallTarget root = createCallTarget(CompareNotNullNodeFactory.getInstance());
-        assertEquals("do1", root.call("42"));
-        assertEquals("do2", root.call((Object) null));
-    }
-
-    abstract static class CompareNotNullNode extends ChildrenNode {
-        @Specialization(guards = "value != null")
-        String do1(Object value) {
-            return "do1";
-        }
-
-        @Specialization
-        String do2(Object value) {
-            return "do2";
-        }
-    }
-
-    abstract static class ErrorNullIntComparison1 extends ChildrenNode {
-        @ExpectError("Error parsing expression 'value == null': Incompatible operand types int and null.")
-        @Specialization(guards = "value == null")
-        String do1(int value) {
-            return "do1";
-        }
-    }
-
-    abstract static class ErrorNullIntComparison2 extends ChildrenNode {
-        @ExpectError("Error parsing expression '1 == null': Incompatible operand types int and null.")
-        @Specialization(guards = "1 == null")
-        String do1(int value) {
-            return "do1";
-        }
-    }
-
-    abstract static class ErrorNullNullComparison extends ChildrenNode {
-        @ExpectError("Error parsing expression 'null == null': The operator == is undefined for the argument type(s) null null.")
-        @Specialization(guards = "null == null")
-        String do1(int value) {
-            return "do1";
-        }
-    }
-
-    abstract static class ErrorObjectVoidComparison extends ChildrenNode {
-        protected static void returnVoid() {
-        }
-
-        @ExpectError("Error parsing expression 'value == returnVoid()': Incompatible operand types Object and void.")
-        @Specialization(guards = "value == returnVoid()")
-        String do1(Object value) {
-            return "do1";
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.NullTestFactory.NullTest1Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class NullTest {
-
-    @Test
-    public void testGuardInvocations() {
-        TestRootNode<NullTest1> root = createRoot(NullTest1Factory.getInstance());
-
-        assertEquals("fallback", executeWith(root, (Object) null));
-        assertEquals(true, executeWith(root, true));
-        assertEquals(42L, executeWith(root, 42));
-        assertEquals("string", executeWith(root, "s"));
-        assertEquals("fallback", executeWith(root, (Object) null));
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChild("a")
-    abstract static class NullTest1 extends ValueNode {
-
-        @Specialization
-        long s(long a) {
-            return a;
-        }
-
-        @Specialization
-        boolean s(boolean a) {
-            return a;
-        }
-
-        @Specialization
-        String s(String a) {
-            return "string";
-        }
-
-        @Fallback
-        Object s(Object a) {
-            return "fallback";
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic1Factory;
-import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic2Factory;
-import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic3Factory;
-import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-
-public class PolymorphicTest {
-
-    private static void assertParent(Node expectedParent, Node child) {
-        Node parent = child.getParent();
-        while (parent != null && parent != expectedParent) {
-            parent = parent.getParent();
-        }
-
-        if (parent != expectedParent) {
-            assertEquals(expectedParent, parent);
-        }
-    }
-
-    public static void assertNoDuplicates(Node node, Node... ignored) {
-        assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet<Class<?>>(), node);
-    }
-
-    private static void assertNoDuplicatesRec(Set<Node> ignored, Set<Class<?>> seenClasses, Node current) {
-        if (!ignored.contains(current)) {
-            if (seenClasses.contains(current.getClass())) {
-                Assert.fail(String.format("Multiple occurences of the same class %s. %nTree: %s", current.getClass().getSimpleName(), NodeUtil.printCompactTreeToString(current.getRootNode())));
-            } else {
-                seenClasses.add(current.getClass());
-            }
-        }
-
-        for (Node child : current.getChildren()) {
-            if (child != null) {
-                assertNoDuplicatesRec(ignored, seenClasses, child);
-            }
-        }
-    }
-
-    @Test
-    public void testPolymorphic1() {
-        assertRuns(Polymorphic1Factory.getInstance(), //
-                        array(42, 43, true, false, "a", "b"), //
-                        array(42, 43, true, false, "a", "b"), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                Polymorphic1 polymorphic = ((Polymorphic1) node.getNode());
-                                assertParent(node.getNode(), polymorphic.getA());
-                                assertNoDuplicates(polymorphic, polymorphic.getA());
-                                if (index == 0) {
-                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-                                }
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Polymorphic1 extends ValueNode {
-
-        public abstract ValueNode getA();
-
-        @Specialization
-        int add(int a) {
-            return a;
-        }
-
-        @Specialization
-        boolean add(boolean a) {
-            return a;
-        }
-
-        @Specialization
-        String add(String a) {
-            return a;
-        }
-
-        @Fallback
-        String add(Object left) {
-            throw new AssertionError(left.toString());
-        }
-
-    }
-
-    @Test
-    public void testPolymorphic2() {
-        assertRuns(Polymorphic2Factory.getInstance(), //
-                        array(0, 1, 1, "1", "2", 2, 3), //
-                        array(0, 1, 1, "1", "2", 2, 3), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                Polymorphic2 polymorphic = ((Polymorphic2) node.getNode());
-                                assertParent(node.getNode(), polymorphic.getA());
-                                assertNoDuplicates(polymorphic, polymorphic.getA());
-                                if (index == 0) {
-                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
-                                }
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Polymorphic2 extends ValueNode {
-
-        public abstract ValueNode getA();
-
-        @Specialization
-        String s2(String a) {
-            return a;
-        }
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        int s0(int a) {
-            if (a == 1) {
-                throw new RuntimeException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int s1(int a) {
-            return a;
-        }
-
-    }
-
-    @Test
-    public void testPolymorphic3() {
-        assertRuns(Polymorphic3Factory.getInstance(), //
-                        array("0", "1", 1, 1, 2, 2, 3, 3), //
-                        array("0", "1", 1, 1, 2, 2, 3, 3), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                Polymorphic3 polymorphic = ((Polymorphic3) node.getNode());
-                                assertParent(node.getNode(), polymorphic.getA());
-                                assertNoDuplicates(polymorphic, polymorphic.getA());
-                            }
-                        });
-    }
-
-    @NodeChild("a")
-    abstract static class Polymorphic3 extends ValueNode {
-
-        public abstract ValueNode getA();
-
-        @Specialization
-        String s2(String a) {
-            return a;
-        }
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        int s0(int a) {
-            if (a == 1) {
-                throw new RuntimeException();
-            }
-            return a;
-        }
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        int s1(int a) {
-            if (a == 1) {
-                throw new RuntimeException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int s2(int a) {
-            return a;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
-import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Polymorphic1Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.nodes.*;
-
-public class PolymorphicTest2 {
-
-    @Test
-    public void testMultipleTypes() {
-        /* Tests the unexpected polymorphic case. */
-        TestRootNode<Polymorphic1> node = TestHelper.createRoot(Polymorphic1Factory.getInstance());
-        assertEquals(21, executeWith(node, false, false));
-        assertEquals(42, executeWith(node, 21, 21));
-        assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-    }
-
-    @SuppressWarnings("unused")
-    abstract static class Polymorphic1 extends BinaryNode {
-
-        @Specialization
-        int add(int left, int right) {
-            return 42;
-        }
-
-        @Specialization
-        int add(boolean left, boolean right) {
-            return 21;
-        }
-
-        @Specialization
-        String add(boolean left, int right) {
-            return "(boolean,int)";
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class ReachabilityTest {
-
-    static class Reachability1 extends ValueNode {
-        @Specialization
-        int do2() {
-            return 2;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization
-        int do1() {
-            return 2;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType1 extends ValueNode {
-        @Specialization
-        int do2(int a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(int).")
-        @Specialization
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType2 extends ValueNode {
-        @Specialization
-        BExtendsAbstract do2(BExtendsAbstract a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(BExtendsAbstract).")
-        @Specialization
-        BExtendsAbstract do1(BExtendsAbstract a) {
-            return a;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType3 extends ValueNode {
-        @Specialization
-        Abstract do2(Abstract a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(Abstract).")
-        @Specialization
-        BExtendsAbstract do1(BExtendsAbstract a) {
-            return a;
-        }
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType4 extends ValueNode {
-
-        @Specialization
-        BExtendsAbstract do2(BExtendsAbstract a) {
-            return a;
-        }
-
-        @Specialization
-        Abstract do1(Abstract a) {
-            return a;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType5 extends ValueNode {
-
-        @Specialization
-        double do2(double a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(double).")
-        @Specialization
-        int do1(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType6 extends ValueNode {
-
-        @Specialization
-        BigInteger do2(BigInteger a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(BigInteger).")
-        @Specialization
-        int do1(int a) {
-            return a;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType7 extends ValueNode {
-
-        @Specialization
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization
-        BigInteger do1(BigInteger a) {
-            return a;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType8 extends ValueNode {
-
-        @Specialization
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization
-        Object do1(Object a) {
-            return a;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class ReachabilityType9 extends ValueNode {
-
-        @Specialization
-        Object do2(Object a) {
-            return a;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2(Object).")
-        @Specialization
-        int do1(int a) {
-            return a;
-        }
-    }
-
-    static class ReachabilityGuard1 extends ValueNode {
-
-        boolean foo() {
-            return false;
-        }
-
-        @Specialization(guards = "foo()")
-        int do2() {
-            return 1;
-        }
-
-        @Specialization
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    static class ReachabilityGuard2 extends ValueNode {
-
-        boolean foo() {
-            return false;
-        }
-
-        @Specialization
-        int do2() {
-            return 2;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(guards = "foo()")
-        int do1() {
-            return 1;
-        }
-
-    }
-
-    static class ReachabilityGuard3 extends ValueNode {
-
-        boolean foo() {
-            return false;
-        }
-
-        @Specialization(guards = "foo()")
-        int do2() {
-            return 1;
-        }
-
-        @Specialization
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    static class ReachabilityGuard4 extends ValueNode {
-
-        boolean foo() {
-            return false;
-        }
-
-        @Specialization(guards = "foo()")
-        int do2() {
-            return 1;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(guards = "foo()")
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    static class ReachabilityThrowable1 extends ValueNode {
-
-        @Specialization(rewriteOn = RuntimeException.class)
-        int do2() throws RuntimeException {
-            return 1;
-        }
-
-        @Specialization
-        int do1() {
-            return 2;
-        }
-
-    }
-
-    static class ReachabilityThrowable2 extends ValueNode {
-
-        @Specialization
-        int do2() {
-            return 1;
-        }
-
-        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
-        @Specialization(rewriteOn = RuntimeException.class)
-        int do1() throws RuntimeException {
-            return 2;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory;
-import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.ShortCircuitWithImplicitCastNodeFactory;
-import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory;
-import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class ShortCircuitTest {
-
-    @Test
-    public void testSingleChild1() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
-        SingleChildNode.needsChild = true;
-        assertEquals(42, callTarget.call(new Object[]{42}));
-        assertEquals(1, arg0.getInvocationCount());
-    }
-
-    @Test
-    public void testSingleChild2() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
-        SingleChildNode.needsChild = false;
-        assertEquals(0, callTarget.call(new Object[]{42}));
-        assertEquals(0, arg0.getInvocationCount());
-    }
-
-    @NodeChild("child0")
-    abstract static class SingleChildNode extends ValueNode {
-
-        static boolean needsChild;
-
-        @ShortCircuit("child0")
-        boolean needsChild0() {
-            return needsChild;
-        }
-
-        @Specialization
-        int doIt(boolean hasChild0, int child0) {
-            assert hasChild0 == needsChild0();
-            return child0;
-        }
-
-    }
-
-    @Test
-    public void testDoubleChild1() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
-        assertEquals(42, callTarget.call(new Object[]{41, 42}));
-        assertEquals(1, arg1.getInvocationCount());
-    }
-
-    @Test
-    public void testDoubleChild2() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
-        assertEquals(0, callTarget.call(new Object[]{42, 42}));
-        assertEquals(0, arg1.getInvocationCount());
-    }
-
-    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
-    @SuppressWarnings("unused")
-    abstract static class DoubleChildNode extends ValueNode {
-
-        @ShortCircuit("child1")
-        boolean needsChild1(Object leftValue) {
-            return leftValue.equals(41);
-        }
-
-        @Specialization
-        int doIt(int child0, boolean hasChild1, int child1) {
-            return child1;
-        }
-
-    }
-
-    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
-    @SuppressWarnings("unused")
-    abstract static class GuardChildNode extends ValueNode {
-
-        @ShortCircuit("child1")
-        boolean needsChild1(Object a) {
-            return a.equals(new Integer(42));
-        }
-
-        static boolean guard(int a, boolean hasB, int b) {
-            return false;
-        }
-
-        @Specialization(guards = "guard(a, hasB, b)")
-        int doIt(int a, boolean hasB, int b) {
-            return a + b;
-        }
-
-    }
-
-    @Test
-    public void testVarArgs1() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
-        assertEquals(42, callTarget.call(new Object[]{41, 42}));
-        assertEquals(1, arg1.getInvocationCount());
-    }
-
-    @Test
-    public void testVarArgs2() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
-        assertEquals(0, callTarget.call(new Object[]{42, 42}));
-        assertEquals(0, arg1.getInvocationCount());
-    }
-
-    @NodeChild(value = "children", type = ValueNode[].class)
-    abstract static class VarArgsNode extends ValueNode {
-
-        @ShortCircuit("children[1]")
-        boolean needsChild1(Object leftValue) {
-            return leftValue.equals(41);
-        }
-
-        @Specialization
-        @SuppressWarnings("unused")
-        int doIt(int child0, boolean hasChild1, int child1) {
-            return child1;
-        }
-
-    }
-
-    @Test
-    public void testShortCircuitWithImplicitCastNode() {
-        ArgumentNode arg0 = new ArgumentNode(0);
-        ArgumentNode arg1 = new ArgumentNode(1);
-        CallTarget callTarget = TestHelper.createCallTarget(ShortCircuitWithImplicitCastNodeFactory.create(new ValueNode[]{arg0, arg1}));
-        assertEquals(42, callTarget.call(new Object[]{42, 41}));
-    }
-
-    @TypeSystem(int.class)
-    abstract static class ShortCircuitWithImplicitCastTypes {
-
-        @ImplicitCast
-        public static int doAnImplicitCast(String foo) {
-            return Integer.parseInt(foo);
-        }
-
-    }
-
-    @NodeChild(value = "children", type = ValueNode[].class)
-    @TypeSystemReference(ShortCircuitWithImplicitCastTypes.class)
-    abstract static class ShortCircuitWithImplicitCastNode extends ValueNode {
-
-        @ShortCircuit("children[1]")
-        public boolean needsRightNode(Object left) {
-            return (int) left == 41;
-        }
-
-        @Specialization
-        public int doInteger(int left, boolean needsRight, int right) {
-            return needsRight ? right : left;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection0Factory;
-import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection1Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-@RunWith(Theories.class)
-public class SourceSectionTest {
-
-    @DataPoints public static final int[] data = new int[]{1, 2, 3, 4};
-
-    @Theory
-    public void testSourceSections(int value0, int value1, int value2) {
-        TestRootNode<SourceSection0> root = createRoot(SourceSection0Factory.getInstance());
-        SourceSection section = new NullSourceSection("a", "b");
-        root.getNode().assignSourceSection(section);
-        expectSourceSection(root.getNode(), section);
-        assertThat((int) executeWith(root, value0), is(value0));
-        expectSourceSection(root.getNode(), section);
-        assertThat((int) executeWith(root, value1), is(value1));
-        expectSourceSection(root.getNode(), section);
-        assertThat((int) executeWith(root, value2), is(value2));
-        expectSourceSection(root.getNode(), section);
-    }
-
-    private static void expectSourceSection(Node root, SourceSection section) {
-        assertThat(root.getSourceSection(), is(sameInstance(section)));
-        for (Node child : root.getChildren()) {
-            if (child instanceof ArgumentNode || child instanceof SpecializationNode) {
-                continue;
-            }
-            if (child != null) {
-                expectSourceSection(child, section);
-            }
-        }
-    }
-
-    @NodeChild("a")
-    static class SourceSection0 extends ValueNode {
-
-        @Specialization(guards = "a == 1")
-        int do1(int a) {
-            return a;
-        }
-
-        @Specialization(guards = "a == 2")
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization(guards = "a == 3")
-        int do3(int a) {
-            return a;
-        }
-
-        @Fallback
-        Object do4(Object a) {
-            return a; // the generic answer to all questions
-        }
-    }
-
-    @Test
-    public void testCreateCast() {
-        SourceSection section = new NullSourceSection("a", "b");
-        TestRootNode<SourceSection1> root = createRootPrefix(SourceSection1Factory.getInstance(), true, section);
-        expectSourceSection(root.getNode(), section);
-        assertThat((int) executeWith(root, 1), is(1));
-        expectSourceSection(root.getNode(), section);
-    }
-
-    @NodeChild("a")
-    static class SourceSection1 extends ValueNode {
-
-        public SourceSection1(SourceSection section) {
-            super(section);
-        }
-
-        @CreateCast("a")
-        public ValueNode cast(ValueNode node) {
-            assert getSourceSection() != null;
-            return node;
-        }
-
-        @Specialization
-        int do0(int a) {
-            return a;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest0Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest1Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest2Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest3Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest4Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest5Factory;
-import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class SpecializationFallthroughTest {
-
-    @Test
-    public void testFallthrough0() {
-        assertRuns(FallthroughTest0Factory.getInstance(), //
-                        array(0, 0, 1, 2), //
-                        array(0, 0, 1, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest0.fallthroughCount > 1) {
-                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
-                                }
-                            }
-                        });
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest0 extends ValueNode {
-
-        static int fallthroughCount = 0;
-
-        public FallthroughTest0() {
-            fallthroughCount = 0;
-        }
-
-        @Specialization(rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthroughCount++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Fallback
-        Object doFallback(Object a) {
-            return a;
-        }
-    }
-
-    /*
-     * Tests that the fall through is never triggered twice for monomorphic cases.
-     */
-    @Test
-    public void testFallthrough1() {
-        assertRuns(FallthroughTest1Factory.getInstance(), //
-                        array(0, 0, 0, 1, 2), //
-                        array(0, 0, 0, 1, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest1.fallthroughCount > 1) {
-                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
-                                }
-                            }
-                        });
-    }
-
-    /* TODO assert falltrough do1 before do2 */
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest1 extends ValueNode {
-
-        static int fallthroughCount;
-
-        public FallthroughTest1() {
-            fallthroughCount = 0;
-        }
-
-        @Specialization(rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthroughCount++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int do2(int a) {
-            return a;
-        }
-
-    }
-
-    /*
-     * Tests that the fall through is never triggered twice with two falltrhoughs in one operation.
-     */
-    @Test
-    public void testFallthrough2() {
-        assertRuns(FallthroughTest2Factory.getInstance(), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest2.fallthrough1 > 1) {
-                                    Assert.fail();
-                                }
-                                if (FallthroughTest2.fallthrough2 > 1) {
-                                    Assert.fail();
-                                }
-                                FallthroughTest2.fallthrough1 = 0;
-                                FallthroughTest2.fallthrough2 = 0;
-                            }
-                        });
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest2 extends ValueNode {
-
-        static int fallthrough1;
-        static int fallthrough2;
-
-        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthrough1++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
-        int do2(int a) throws ArithmeticException {
-            if (a == 1) {
-                fallthrough2++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int do3(int a) {
-            return a;
-        }
-    }
-
-    /*
-     * Tests that the fall through is never triggered twice. In this case mixed fallthrough with
-     * normal specializations.
-     */
-    @Test
-    public void testFallthrough3() {
-        assertRuns(FallthroughTest3Factory.getInstance(), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest3.fallthrough1 > 1) {
-                                    Assert.fail(String.valueOf(FallthroughTest3.fallthrough1));
-                                }
-                                FallthroughTest3.fallthrough1 = 0;
-                            }
-                        });
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest3 extends ValueNode {
-
-        static int fallthrough1;
-
-        boolean guard0(int a) {
-            return a == 1;
-        }
-
-        @Specialization(guards = "guard0(a)")
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization(rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthrough1++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int do3(int a) {
-            return a;
-        }
-
-    }
-
-    @Test
-    public void testFallthrough4() {
-        assertRuns(FallthroughTest4Factory.getInstance(), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest4.fallthrough1 > 1) {
-                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
-                                }
-                                if (FallthroughTest4.fallthrough2 > 1) {
-                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
-                                }
-                                FallthroughTest4.fallthrough1 = 0;
-                                FallthroughTest4.fallthrough2 = 0;
-                            }
-                        });
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest4 extends ValueNode {
-
-        static int fallthrough1;
-        static int fallthrough2;
-
-        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthrough1++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
-        int do2(int a) throws ArithmeticException {
-            if (a == 1) {
-                fallthrough2++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        @Specialization
-        int do3(int a) {
-            return a;
-        }
-
-    }
-
-    @Test
-    public void testFallthrough5() {
-        assertRuns(FallthroughTest5Factory.getInstance(), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        array(0, 0, 1, 1, 2, 2), //
-                        new ExecutionListener() {
-                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-                                if (!last) {
-                                    return;
-                                }
-                                if (FallthroughTest5.fallthrough1 > 1) {
-                                    Assert.fail(String.valueOf(FallthroughTest5.fallthrough1));
-                                }
-                                FallthroughTest5.fallthrough1 = 0;
-                            }
-                        });
-    }
-
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughTest5 extends ValueNode {
-
-        static int fallthrough1;
-
-        @Specialization(guards = "isDo1(a)", rewriteOn = ArithmeticException.class)
-        int do1(int a) throws ArithmeticException {
-            if (a == 0) {
-                fallthrough1++;
-                throw new ArithmeticException();
-            }
-            return a;
-        }
-
-        protected static boolean isDo1(int a) {
-            return a == 0 || a == 1;
-        }
-
-        @Specialization(guards = "isDo1(a)")
-        int do2(int a) {
-            return a;
-        }
-
-        @Specialization
-        int do3(int a) {
-            return a;
-        }
-
-    }
-
-    /* Throwing RuntimeExceptions without rewriteOn is allowed. */
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughExceptionType0 extends ValueNode {
-
-        @Specialization
-        int do4(int a) throws RuntimeException {
-            return a;
-        }
-
-    }
-
-    /* Non runtime exceptions must be verified. */
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughExceptionType1 extends ValueNode {
-
-        @ExpectError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @Specialization method must specify a throws clause with the exception type 'java.lang.Throwable'.")
-        @Specialization(rewriteOn = Throwable.class)
-        int do4(int a) {
-            return a;
-        }
-
-    }
-
-    /* Checked exception must be verified. */
-    @NodeChildren({@NodeChild("a")})
-    static class FallthroughExceptionType2 extends ValueNode {
-
-        @ExpectError("A checked exception 'java.lang.Throwable' is thrown but is not specified using the rewriteOn property. "
-                        + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.")
-        @Specialization
-        int do4(int a) throws Throwable {
-            return a;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory;
-import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug2Factory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Tests execution counts of guards. While we do not make guarantees for guard invocation except for
- * their execution order our implementation reduces the calls to guards as much as possible for the
- * generic case.
- */
-public class SpecializationGroupingTest {
-
-    @Test
-    public void testElseConnectionBug1() {
-        CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt()));
-        Assert.assertEquals(42, target.call());
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChild(value = "genericChild", type = GenericInt.class)
-    public abstract static class TestElseConnectionBug1 extends ValueNode {
-
-        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized(value)")
-        public int do1(int value) throws SlowPathException {
-            throw new SlowPathException();
-        }
-
-        @Specialization(contains = "do1", guards = "isInitialized(value)")
-        public int do2(int value) {
-            return value == 42 ? value : 0;
-        }
-
-        @Specialization(guards = "!isInitialized(value)")
-        public Object do3(int value) {
-            throw new AssertionError();
-        }
-
-        boolean isInitialized(int value) {
-            return true;
-        }
-    }
-
-    public static final class GenericInt extends ValueNode {
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return executeInt(frame);
-        }
-
-        @Override
-        public int executeInt(VirtualFrame frame) {
-            return 42;
-        }
-
-    }
-
-    @Test
-    public void testElseConnectionBug2() {
-        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), new Object[]{42}, new Object[]{42});
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChild
-    public abstract static class TestElseConnectionBug2 extends ValueNode {
-
-        @Specialization(guards = "guard0(value)")
-        public int do1(int value) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = "guard1(value)")
-        public int do2(int value) {
-            throw new AssertionError();
-        }
-
-        @Specialization(guards = "!guard0(value)")
-        public int do3(int value) {
-            return value;
-        }
-
-        boolean guard0(int value) {
-            return false;
-        }
-
-        boolean guard1(int value) {
-            return false;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Utility class to provide some test helper functions.
- */
-class TestHelper {
-
-    // make nodes replacable
-    public static <T extends Node> T createRoot(final T node) {
-        new RootNode() {
-            @Child T child = node;
-
-            @Override
-            public Object execute(VirtualFrame frame) {
-                return null;
-            }
-        }.adoptChildren();
-        return node;
-    }
-
-    private static ArgumentNode[] arguments(int count) {
-        ArgumentNode[] nodes = new ArgumentNode[count];
-        for (int i = 0; i < nodes.length; i++) {
-            nodes[i] = new ArgumentNode(i);
-        }
-        return nodes;
-    }
-
-    static <E extends ValueNode> E createNode(NodeFactory<E> factory, boolean prefixConstants, Object... constants) {
-        ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size());
-
-        List<Object> argumentList = new ArrayList<>();
-        if (prefixConstants) {
-            argumentList.addAll(Arrays.asList(constants));
-        }
-        if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) {
-            argumentList.add(argumentNodes);
-        } else {
-            argumentList.addAll(Arrays.asList(argumentNodes));
-        }
-        if (!prefixConstants) {
-            argumentList.addAll(Arrays.asList(constants));
-        }
-        return factory.createNode(argumentList.toArray(new Object[argumentList.size()]));
-    }
-
-    static <E extends ValueNode> TestRootNode<E> createRoot(NodeFactory<E> factory, Object... constants) {
-        TestRootNode<E> rootNode = new TestRootNode<>(createNode(factory, false, constants));
-        rootNode.adoptChildren();
-        return rootNode;
-    }
-
-    static <E extends ValueNode> TestRootNode<E> createRootPrefix(NodeFactory<E> factory, boolean prefixConstants, Object... constants) {
-        TestRootNode<E> rootNode = new TestRootNode<>(createNode(factory, prefixConstants, constants));
-        rootNode.adoptChildren();
-        return rootNode;
-    }
-
-    static CallTarget createCallTarget(ValueNode node) {
-        return createCallTarget(new TestRootNode<>(node));
-    }
-
-    static CallTarget createCallTarget(TestRootNode<? extends ValueNode> node) {
-        return Truffle.getRuntime().createCallTarget(node);
-    }
-
-    static RootCallTarget createCallTarget(NodeFactory<? extends ValueNode> factory, Object... constants) {
-        return Truffle.getRuntime().createCallTarget(createRoot(factory, constants));
-    }
-
-    static boolean assertionsEnabled() {
-        boolean assertOn = false;
-        // *assigns* true if assertions are on.
-        assert (assertOn = true) == true;
-        return assertOn;
-    }
-
-    @SuppressWarnings("unchecked")
-    static <T extends ValueNode> T getNode(CallTarget target) {
-        return ((TestRootNode<T>) ((RootCallTarget) target).getRootNode()).getNode();
-    }
-
-    static <E> Object executeWith(TestRootNode<? extends ValueNode> node, Object... values) {
-        return createCallTarget(node).call(values);
-    }
-
-    static Object[] array(Object... val) {
-        return val;
-    }
-
-    static <E> List<List<E>> permutations(List<E> list) {
-        return permutations(new ArrayList<E>(), list, new ArrayList<List<E>>());
-    }
-
-    static Object[][] permutations(Object... list) {
-        List<List<Object>> permutations = permutations(Arrays.asList(list));
-
-        Object[][] a = new Object[permutations.size()][];
-        int index = 0;
-        for (List<Object> p : permutations) {
-            a[index] = p.toArray(new Object[p.size()]);
-            index++;
-        }
-
-        return a;
-    }
-
-    static <E> List<List<E>> permutations(List<E> prefix, List<E> suffix, List<List<E>> output) {
-        if (suffix.size() == 1) {
-            ArrayList<E> newElement = new ArrayList<>(prefix);
-            newElement.addAll(suffix);
-            output.add(newElement);
-            return output;
-        }
-
-        for (int i = 0; i < suffix.size(); i++) {
-            List<E> newPrefix = new ArrayList<>(prefix);
-            newPrefix.add(suffix.get(i));
-            List<E> newSuffix = new ArrayList<>(suffix);
-            newSuffix.remove(i);
-            permutations(newPrefix, newSuffix, output);
-        }
-
-        return output;
-    }
-
-    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result) {
-        assertRuns(factory, testValues, result, null);
-    }
-
-    /* Methods tests all test values in combinational order. */
-    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result, ExecutionListener listener) {
-        // test each run by its own.
-        for (int i = 0; i < testValues.length; i++) {
-            assertValue(createRoot(factory), 0, testValues[i], result[i], listener, true);
-        }
-
-        // test all combinations of the test values
-        List<Object> testValuesList = Arrays.asList(testValues);
-        List<List<Object>> permuts = permutations(testValuesList);
-        for (List<Object> list : permuts) {
-            TestRootNode<?> root = createRoot(factory);
-            int index = 0;
-            for (Object object : list) {
-                assertValue(root, index, object, result[testValuesList.indexOf(object)], listener, index == list.size() - 1);
-                index++;
-            }
-        }
-    }
-
-    static void assertValue(TestRootNode<? extends ValueNode> root, int index, Object value, Object result, ExecutionListener listener, boolean last) {
-        Object actualResult = null;
-        if (result instanceof Class && Throwable.class.isAssignableFrom((Class<?>) result)) {
-            try {
-                if (value instanceof Object[]) {
-                    actualResult = executeWith(root, (Object[]) value);
-                } else {
-                    actualResult = executeWith(root, value);
-                }
-                fail(String.format("Exception %s  expected but not occured.", result.getClass()));
-            } catch (Throwable e) {
-                actualResult = e;
-                if (!e.getClass().isAssignableFrom(((Class<?>) result))) {
-                    e.printStackTrace();
-                    fail(String.format("Incompatible exception class thrown. Expected %s but was %s.", result.toString(), e.getClass()));
-                }
-            }
-        } else if (value instanceof Object[]) {
-            actualResult = executeWith(root, (Object[]) value);
-            assertEquals(result, actualResult);
-        } else {
-            actualResult = executeWith(root, value);
-            assertEquals(result, actualResult);
-        }
-        if (listener != null) {
-            listener.afterExecution(root, index, value, result, actualResult, last);
-        }
-    }
-
-    public static final class LogListener implements ExecutionListener {
-
-        public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
-            System.out.printf("Run %3d Node:%-20s Parameters: %10s Expected: %10s Result %10s%n", index, node.getNode().getClass().getSimpleName(), value, expectedResult, actualResult);
-        }
-
-    }
-
-    interface ExecutionListener {
-
-        void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last);
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestSerialization.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import static com.oracle.truffle.api.dsl.test.TestHelper.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TestSerializationFactory.SerializedNodeFactory;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.nodes.*;
-
-public class TestSerialization {
-
-    @Test
-    public void testUpdateRoot() {
-        /* Tests the unexpected polymorphic case. */
-        TestRootNode<SerializedNode> node = TestHelper.createRoot(SerializedNodeFactory.getInstance());
-        assertEquals(true, executeWith(node, true));
-        assertEquals(21, executeWith(node, 21));
-        assertEquals("s", executeWith(node, "s"));
-        assertEquals(3, node.getNode().invocations);
-        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
-
-        @SuppressWarnings("unchecked")
-        TestRootNode<SerializedNode> copiedNode = (TestRootNode<SerializedNode>) node.deepCopy();
-        copiedNode.adoptChildren();
-        assertTrue(copiedNode != node);
-        assertEquals(true, executeWith(copiedNode, true));
-        assertEquals(21, executeWith(copiedNode, 21));
-        assertEquals("s", executeWith(copiedNode, "s"));
-        assertEquals(6, copiedNode.getNode().invocations);
-    }
-
-    @NodeChild
-    abstract static class SerializedNode extends ValueNode {
-
-        int invocations;
-
-        @Specialization
-        int add(int left) {
-            invocations++;
-            return left;
-        }
-
-        @Specialization
-        boolean add(boolean left) {
-            invocations++;
-            return left;
-        }
-
-        @Specialization
-        String add(String left) {
-            invocations++;
-            return left;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types1.Type1;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-
-public class TypeSystemErrorsTest {
-
-    @TypeSystem({int.class, boolean.class})
-    public static class ErrorTypes0 {
-
-    }
-
-    @ExpectError("Invalid type order. The type(s) [java.lang.String] are inherited from a earlier defined type java.lang.CharSequence.")
-    @TypeSystem({CharSequence.class, String.class})
-    public static class ErrorTypes1 {
-
-    }
-
-    public static class Types1 {
-        public static class Type1 {
-        }
-    }
-
-    public static class Types2 {
-        public static class Type1 {
-        }
-    }
-
-    // verify boxed type overlay
-    @ExpectError("Two types result in the same boxed name: Type1.")
-    @TypeSystem({Type1.class, com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types2.Type1.class})
-    public static class ErrorTypes2 {
-
-    }
-
-    public static class Types3 {
-        public static class Object {
-        }
-    }
-
-    // verify Object name cannot appear
-    @ExpectError("Two types result in the same boxed name: Object.")
-    @TypeSystem({com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types3.Object.class})
-    public static class ErrorTypes3 {
-    }
-
-    public static class Types4 {
-        public static class Integer {
-        }
-    }
-
-    // verify int boxed name
-    @ExpectError("Two types result in the same boxed name: Integer.")
-    @TypeSystem({int.class, com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types4.Integer.class})
-    public static class ErrorTypes4 {
-    }
-
-    @TypeSystemReference(ErrorTypes0.class)
-    @NodeChild
-    @ExpectError("The @TypeSystem of the node and the @TypeSystem of the @NodeChild does not match. Types0 != SimpleTypes. ")
-    abstract static class ErrorNode1 extends ValueNode {
-    }
-
-    @TypeSystem({int.class})
-    public static class CastError1 {
-        @TypeCast(int.class)
-        @ExpectError("The provided return type \"String\" does not match expected return type \"int\".%")
-        public static String asInteger(Object value) {
-            return (String) value;
-        }
-    }
-
-    @TypeSystem({int.class})
-    public static class CastError2 {
-        @TypeCast(int.class)
-        @ExpectError("The provided return type \"boolean\" does not match expected return type \"int\".%")
-        public static boolean asInteger(Object value) {
-            return (boolean) value;
-        }
-    }
-
-    @TypeSystem({int.class})
-    public static class CastError4 {
-        @ExpectError("@TypeCast annotated method asInt must be public and static.")
-        @TypeCast(int.class)
-        public int asInt(Object value) {
-            return (int) value;
-        }
-    }
-
-    @TypeSystem({int.class})
-    public static class CastError5 {
-        @ExpectError("@TypeCast annotated method asInt must be public and static.")
-        @TypeCast(int.class)
-        static int asInt(Object value) {
-            return (int) value;
-        }
-    }
-
-    @TypeSystem({int.class})
-    public static class CheckError2 {
-        @ExpectError("@TypeCheck annotated method isInt must be public and static.")
-        @TypeCheck(int.class)
-        public boolean isInt(Object value) {
-            return value instanceof Integer;
-        }
-    }
-
-    @TypeSystem({int.class})
-    public static class CheckError3 {
-        @ExpectError("@TypeCheck annotated method isInt must be public and static.")
-        @TypeCheck(int.class)
-        static boolean isInt(Object value) {
-            return value instanceof Integer;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import java.math.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-public class TypeSystemTest {
-
-    @TypeSystem({byte.class, short.class, int.class, long.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class,
-                    Abstract.class, Interface.class, Object[].class})
-    @DSLOptions(useNewLayout = true)
-    static class SimpleTypes {
-
-        static int intCheck;
-        static int intCast;
-
-        @TypeCheck(int.class)
-        public static boolean isInteger(Object value) {
-            intCheck++;
-            return value instanceof Integer;
-        }
-
-        @TypeCast(int.class)
-        public static int asInteger(Object value) {
-            intCast++;
-            return (int) value;
-        }
-
-        @ImplicitCast
-        public static double castDouble(int value) {
-            return value;
-        }
-
-        @ImplicitCast
-        public static long castLong(int value) {
-            return value;
-        }
-
-        @ImplicitCast
-        public static BigInteger castBigInteger(int value) {
-            return BigInteger.valueOf(value);
-        }
-
-    }
-
-    @TypeSystemReference(SimpleTypes.class)
-    @GenerateNodeFactory
-    public static class ValueNode extends Node {
-
-        public ValueNode() {
-            super(null);
-        }
-
-        public ValueNode(SourceSection sourceSection) {
-            super(sourceSection);
-        }
-
-        public int executeInt(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectInteger(execute(frame));
-        }
-
-        public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectLong(execute(frame));
-        }
-
-        public String executeString(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectString(execute(frame));
-        }
-
-        public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectBoolean(execute(frame));
-        }
-
-        public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectObjectArray(execute(frame));
-        }
-
-        public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectBigInteger(execute(frame));
-        }
-
-        public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectBExtendsAbstract(execute(frame));
-        }
-
-        public CExtendsAbstract executeCExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectCExtendsAbstract(execute(frame));
-        }
-
-        public Abstract executeAbstract(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectAbstract(execute(frame));
-        }
-
-        public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectDouble(execute(frame));
-        }
-
-        public Interface executeInterface(VirtualFrame frame) throws UnexpectedResultException {
-            return SimpleTypesGen.expectInterface(execute(frame));
-        }
-
-        public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public ValueNode copy() {
-            return (ValueNode) super.copy();
-        }
-    }
-
-    @NodeChild(value = "children", type = ValueNode[].class)
-    @GenerateNodeFactory
-    public abstract static class ChildrenNode extends ValueNode {
-
-    }
-
-    @TypeSystemReference(SimpleTypes.class)
-    public static class TestRootNode<E extends ValueNode> extends RootNode {
-
-        @Child private E node;
-
-        public TestRootNode(E node) {
-            super(null);
-            this.node = node;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return node.execute(frame);
-        }
-
-        public E getNode() {
-            return node;
-        }
-    }
-
-    public static class ArgumentNode extends ValueNode {
-
-        private int invocationCount;
-        final int index;
-
-        public ArgumentNode(int index) {
-            this.index = index;
-        }
-
-        public int getInvocationCount() {
-            return invocationCount;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            invocationCount++;
-            return frame.getArguments()[index];
-        }
-
-        @Override
-        public int executeInt(VirtualFrame frame) throws UnexpectedResultException {
-            invocationCount++;
-            // avoid casts for some tests
-            Object o = frame.getArguments()[index];
-            if (o instanceof Integer) {
-                return (int) o;
-            }
-            throw new UnexpectedResultException(o);
-        }
-
-    }
-
-    abstract static class Abstract {
-    }
-
-    static final class BExtendsAbstract extends Abstract {
-
-        static final BExtendsAbstract INSTANCE = new BExtendsAbstract();
-
-    }
-
-    static final class CExtendsAbstract extends Abstract {
-
-        static final CExtendsAbstract INSTANCE = new CExtendsAbstract();
-    }
-
-    interface Interface {
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
-import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
-import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported1Factory;
-import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported2Factory;
-import com.oracle.truffle.api.nodes.*;
-
-public class UnsupportedSpecializationTest {
-
-    @Test
-    public void testUnsupported1() {
-        TestRootNode<Unsupported1> root = TestHelper.createRoot(Unsupported1Factory.getInstance());
-        try {
-            TestHelper.executeWith(root, "");
-            Assert.fail();
-        } catch (UnsupportedSpecializationException e) {
-            Assert.assertNotNull(e.getSuppliedValues());
-            Assert.assertEquals(1, e.getSuppliedValues().length);
-            Assert.assertEquals("", e.getSuppliedValues()[0]);
-            Assert.assertSame(root.getNode().getChildren().iterator().next(), e.getSuppliedNodes()[0]);
-            Assert.assertEquals(root.getNode(), e.getNode());
-        }
-    }
-
-    @NodeChild("a")
-    abstract static class Unsupported1 extends ValueNode {
-
-        @Specialization
-        public int doInteger(@SuppressWarnings("unused") int a) {
-            throw new AssertionError();
-        }
-    }
-
-    @Test
-    public void testUnsupported2() {
-        TestRootNode<Unsupported2> root = TestHelper.createRoot(Unsupported2Factory.getInstance());
-        try {
-            TestHelper.executeWith(root, "", 1);
-            Assert.fail();
-        } catch (UnsupportedSpecializationException e) {
-            Assert.assertNotNull(e.getSuppliedValues());
-            Assert.assertNotNull(e.getSuppliedNodes());
-            Assert.assertEquals(3, e.getSuppliedValues().length);
-            Assert.assertEquals(3, e.getSuppliedNodes().length);
-            Assert.assertEquals("", e.getSuppliedValues()[0]);
-            Assert.assertEquals(false, e.getSuppliedValues()[1]);
-            Assert.assertEquals(null, e.getSuppliedValues()[2]);
-            List<Node> children = NodeUtil.findNodeChildren(root.getNode());
-            Assert.assertSame(children.get(0), e.getSuppliedNodes()[0]);
-            Assert.assertNull(e.getSuppliedNodes()[1]);
-            Assert.assertSame(children.get(1), e.getSuppliedNodes()[2]);
-            Assert.assertEquals(root.getNode(), e.getNode());
-        }
-    }
-
-    @SuppressWarnings("unused")
-    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
-    abstract static class Unsupported2 extends ValueNode {
-
-        @ShortCircuit("b")
-        public boolean needsB(Object a) {
-            return false;
-        }
-
-        @Specialization
-        public int doInteger(int a, boolean hasB, int b) {
-            throw new AssertionError();
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-@TypeSystemReference(ExampleTypes.class)
-@NodeChild(value = "args", type = ExampleNode[].class)
-public abstract class ExampleNode extends Node {
-
-    public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
-        // will get implemented by the DSL.
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public String toString() {
-        if (this instanceof SpecializedNode) {
-            return ((SpecializedNode) this).getSpecializationNode().toString();
-        } else {
-            return super.toString();
-        }
-    }
-
-    public static CallTarget createTarget(ExampleNode node) {
-        return Truffle.getRuntime().createCallTarget(new ExampleRootNode(node));
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> T getNode(CallTarget target) {
-        return (T) ((ExampleRootNode) ((RootCallTarget) target).getRootNode()).child;
-    }
-
-    public static ExampleNode[] createArguments(int count) {
-        ExampleNode[] nodes = new ExampleNode[count];
-        for (int i = 0; i < count; i++) {
-            nodes[i] = new ExampleArgumentNode(i);
-        }
-        return nodes;
-    }
-
-    private static class ExampleRootNode extends RootNode {
-
-        @Child ExampleNode child;
-
-        public ExampleRootNode(ExampleNode child) {
-            this.child = child;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return child.execute(frame);
-        }
-
-    }
-
-    private static class ExampleArgumentNode extends ExampleNode {
-
-        private final int index;
-
-        public ExampleArgumentNode(int index) {
-            this.index = index;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            Object[] arguments = frame.getArguments();
-            if (index < arguments.length) {
-                return arguments[index];
-            }
-            return null;
-        }
-    }
-
-    public static CallTarget createDummyTarget(int argumentIndex) {
-        return Truffle.getRuntime().createCallTarget(new DummyCallRootNode(argumentIndex));
-    }
-
-    private static class DummyCallRootNode extends RootNode {
-
-        private final int argumentIndex;
-
-        public DummyCallRootNode(int argumentIndex) {
-            this.argumentIndex = argumentIndex;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return frame.getArguments()[argumentIndex];
-        }
-
-        @Override
-        public String toString() {
-            return "DummyRootNode[arg = " + argumentIndex + "]";
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.examples.FunctionCall.Function;
-import com.oracle.truffle.api.dsl.test.examples.Interop.TruffleObject;
-import com.oracle.truffle.api.dsl.test.examples.RubyCall.InternalMethod;
-import com.oracle.truffle.api.dsl.test.examples.RubyCall.RubyObject;
-import com.oracle.truffle.api.dsl.test.examples.StableDispatch.SLFunction;
-
-@TypeSystem({int.class, double.class, boolean.class, TruffleObject.class, SLFunction.class, RubyObject.class, Function.class, InternalMethod.class, int[].class, double[].class, Object[].class})
-public class ExampleTypes {
-
-    @ImplicitCast
-    public static double castInt(int intValue) {
-        return intValue;
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.examples.FunctionCallFactory.FunctionCallNodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This example illustrates how {@link Cached} can be used to implement function calls that use
- * local state for its guards. If there are always distinct Function objects with distinct
- * CallTargets then we can use the directCallFunctionGuard specialization. If there are two Function
- * instances cached with the same CallTarget then we use the directCall cache. We do this because
- * the directCallFunctionGuard specialization can use a faster guard.
- */
-@SuppressWarnings("unused")
-public class FunctionCall {
-
-    @Test
-    public void testFunctionCall() {
-        assertEquals(2, FunctionCallNode.CACHE_SIZE);
-
-        CallTarget dummyTarget1 = createDummyTarget(0);
-        CallTarget dummyTarget2 = createDummyTarget(0);
-        CallTarget dummyTarget3 = createDummyTarget(0);
-
-        Function dummyFunction1 = new Function(dummyTarget1);
-        Function dummyFunction2 = new Function(dummyTarget2);
-        Function dummyFunction3 = new Function(dummyTarget2); // same target as dummyFunction2
-        Function dummyFunction4 = new Function(dummyTarget3);
-
-        FunctionCallNode node = FunctionCallNodeGen.create(createArguments(2));
-        CallTarget target = createTarget(node);
-        assertEquals(42, target.call(dummyFunction1, 42));
-        assertEquals(43, target.call(dummyFunction2, 43));
-        assertEquals(44, target.call(dummyFunction3, 44)); // transition to directCall
-        assertEquals(2, node.directCallFunctionGuard);
-        assertEquals(1, node.directCall);
-
-        assertEquals(42, target.call(dummyFunction1, 42));
-        assertEquals(43, target.call(dummyFunction2, 43));
-        assertEquals(2, node.directCallFunctionGuard);
-        assertEquals(3, node.directCall);
-
-        assertEquals(44, target.call(dummyFunction4, 44)); // transition to indirectCall
-        assertEquals(2, node.directCallFunctionGuard);
-        assertEquals(3, node.directCall);
-        assertEquals(1, node.indirectCall);
-
-        assertEquals(42, target.call(dummyFunction1, 42));
-        assertEquals(43, target.call(dummyFunction2, 43));
-        assertEquals(44, target.call(dummyFunction3, 44));
-        assertEquals(2, node.directCallFunctionGuard);
-        assertEquals(3, node.directCall);
-        assertEquals(4, node.indirectCall);
-    }
-
-    public static class FunctionCallNode extends ExampleNode {
-
-        public static final int CACHE_SIZE = 2;
-
-        private Function[] cachedFunctions = new Function[CACHE_SIZE];
-
-        private int directCallFunctionGuard;
-        private int directCall;
-        private int indirectCall;
-
-        @Specialization(limit = "CACHE_SIZE", guards = {"function == cachedFunction", "cacheFunctionTarget(cachedFunction)"})
-        public Object directCallFunctionGuard(VirtualFrame frame, Function function, Object argument,  //
-                        @Cached("function") Function cachedFunction, //
-                        @Cached("create(cachedFunction.getTarget())") DirectCallNode callNode) {
-            directCallFunctionGuard++;
-            return callNode.call(frame, new Object[]{argument});
-        }
-
-        protected final boolean cacheFunctionTarget(Function function) {
-            CompilerAsserts.neverPartOfCompilation();
-            if (cachedFunctions != null) {
-                for (int i = 0; i < cachedFunctions.length; i++) {
-                    Function cachedFunction = cachedFunctions[i];
-                    if (cachedFunction == null) {
-                        cachedFunctions[i] = function;
-                        return true;
-                    } else if (cachedFunction == function) {
-                        return true;
-                    } else if (cachedFunction.getTarget() == function.getTarget()) {
-                        cachedFunctions = null;
-                        return false;
-                    }
-                }
-            }
-            return false;
-        }
-
-        @Specialization(limit = "CACHE_SIZE", contains = "directCallFunctionGuard", guards = {"function.getTarget() == cachedTarget"})
-        protected Object directCall(VirtualFrame frame, Function function, Object argument,  //
-                        @Cached("function.getTarget()") CallTarget cachedTarget, //
-                        @Cached("create(cachedTarget)") DirectCallNode callNode) {
-            directCall++;
-            return callNode.call(frame, new Object[]{argument});
-        }
-
-        @Specialization(contains = "directCall")
-        protected Object indirectCall(VirtualFrame frame, Function function, Object argument, //
-                        @Cached("create()") IndirectCallNode callNode) {
-            indirectCall++;
-            return callNode.call(frame, function.getTarget(), new Object[]{argument});
-        }
-    }
-
-    public static class Function {
-
-        private final CallTarget target;
-
-        public Function(CallTarget target) {
-            this.target = target;
-        }
-
-        public CallTarget getTarget() {
-            return target;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.examples.InteropFactory.UseInteropNodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This example aims to illustrate how the {@link Cached} annotation can be used to implement a
- * cache for a simplified language interoperability pattern.
- */
-public class Interop {
-
-    @Test
-    public void testInterop() {
-        UseInterop node = UseInteropNodeGen.create(createArguments(2));
-        CallTarget target = createTarget(node);
-        TruffleObject o1 = new TruffleObject();
-        TruffleObject o2 = new TruffleObject();
-        TruffleObject o3 = new TruffleObject();
-        TruffleObject o4 = new TruffleObject();
-        assertEquals(42, target.call(o1, 42));
-        assertEquals(43, target.call(o2, 43));
-        assertEquals(44, target.call(o3, 44));
-        assertEquals(3, node.cached);
-        assertEquals(0, node.generic);
-        assertEquals(45, target.call(o4, 45)); // operation gets generic
-        assertEquals(42, target.call(o1, 42));
-        assertEquals(43, target.call(o2, 43));
-        assertEquals(44, target.call(o3, 44));
-        assertEquals(3, node.cached);
-        assertEquals(4, node.generic);
-    }
-
-    public static class UseInterop extends ExampleNode {
-
-        int cached = 0;
-        int generic = 0;
-
-        @Specialization(guards = "operation.accept(target)")
-        protected Object interopCached(VirtualFrame frame, TruffleObject target, Object value, //
-                        @Cached("target.createOperation()") TruffleObjectOperation operation) {
-            cached++;
-            return operation.execute(frame, target, value);
-        }
-
-        @Specialization(contains = "interopCached")
-        protected Object interopGeneric(VirtualFrame frame, TruffleObject target, Object value) {
-            generic++;
-            return target.createOperation().execute(frame, target, value);
-        }
-    }
-
-    public abstract static class TruffleObjectOperation extends Node {
-
-        public abstract boolean accept(TruffleObject object);
-
-        public abstract Object execute(VirtualFrame frame, Object target, Object value);
-
-    }
-
-    public static class TruffleObject {
-
-        @TruffleBoundary
-        public TruffleObjectOperation createOperation() {
-            return new TruffleObjectOperation() {
-                @Override
-                public Object execute(VirtualFrame frame, Object target, Object value) {
-                    return value;
-                }
-
-                @Override
-                public boolean accept(TruffleObject object) {
-                    return TruffleObject.this == object;
-                }
-            };
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.test.examples.MathPowFactory.MathPowNodeGen;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This example shows possible specializations for a simplified math pow node. It demonstrates how
- * multiple caches can coexist within in the same node. This example does not show the best possible
- * specializations for math.pow.
- *
- * Note: int values are implicitly casted to double values.
- */
-@SuppressWarnings("unused")
-public class MathPow extends Node {
-
-    @Test
-    public void testPow() {
-        MathPowNode node = MathPowNodeGen.create(createArguments(2));
-        CallTarget target = createTarget(node);
-
-        // start with doPowCached
-        assertEquals(1D, target.call(1D, 1));
-        assertEquals(2D, target.call(2D, 1));
-        assertEquals(3D, target.call(3D, 1));
-        assertEquals(3, node.doPowCached);
-        assertEquals(0, node.doPowCachedExponent);
-
-        // transition to doPowCachedExponent
-        assertEquals(4D, target.call(4D, 1));
-        assertEquals(5D, target.call(5D, 1));
-        assertEquals(6D, target.call(6D, 1));
-        assertEquals(16D, target.call(4D, 2));
-        assertEquals(125D, target.call(5D, 3));
-        assertEquals(5, node.doPowCachedExponent);
-        assertEquals(0, node.doPowDoubleInt);
-
-        // transition to doPowDoubleInt
-        assertEquals(4D * 4D * 4D * 4D, target.call(4D, 4));
-        assertEquals(5D * 5D * 5D * 5D * 5D, target.call(5D, 5));
-        assertEquals(5, node.doPowCachedExponent);
-        assertEquals(2, node.doPowDoubleInt);
-
-        // transition to doPow
-        assertEquals(5D, target.call(5D, 1D));
-        assertEquals(2D, target.call(2D, 1D));
-
-        assertEquals(3, node.doPowCached);
-        assertEquals(5, node.doPowCachedExponent);
-        assertEquals(2, node.doPowDoubleInt);
-        assertEquals(2, node.doPow);
-    }
-
-    public static class MathPowNode extends ExampleNode {
-
-        // test flags
-        int doPowCached;
-        int doPowCachedExponent;
-        int doPowDoubleInt;
-        int doPow;
-
-        @Specialization(guards = {"base == cachedBase", "exponent == cachedExponent"})
-        double doPowCached(double base, int exponent, //
-                        @Cached("base") double cachedBase, //
-                        @Cached("exponent") int cachedExponent, //
-                        @Cached("cachePow(cachedBase, cachedExponent)") double cachedResult) {
-            doPowCached++;
-            return cachedResult;
-        }
-
-        /*
-         * We could just use the doPow specialization instead. But this makes the number of doPow
-         * calls more difficult to assert.
-         */
-        protected static double cachePow(double base, int exponent) {
-            return Math.pow(base, exponent);
-        }
-
-        @Specialization(contains = "doPowCached", guards = {"exponent == cachedExponent", "cachedExponent <= 10"})
-        double doPowCachedExponent(double base, int exponent, @Cached("exponent") int cachedExponent) {
-            doPowCachedExponent++;
-            double result = 1.0;
-            for (int i = 0; i < cachedExponent; i++) {
-                result *= base;
-            }
-            return result;
-        }
-
-        @Specialization(contains = "doPowCachedExponent", guards = "exponent >= 0")
-        double doPowDoubleInt(double base, int exponent) {
-            doPowDoubleInt++;
-            // Uses binary decomposition to limit the number of
-            // multiplications; see the discussion in "Hacker's Delight" by Henry
-            // S. Warren, Jr., figure 11-6, page 213.
-            double b = base;
-            int e = exponent;
-            double result = 1;
-            while (e > 0) {
-                if ((e & 1) == 1) {
-                    result *= b;
-                }
-                e >>= 1;
-                b *= b;
-            }
-            return result;
-        }
-
-        @Specialization(contains = {"doPowCached", "doPowDoubleInt"})
-        double doPow(double base, double exponent) {
-            doPow++;
-            return Math.pow(base, exponent);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyDispatchNodeGen;
-import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyHeadNodeGen;
-import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyLookupNodeGen;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-/**
- * This example illustrates a simplified version of a Ruby function call semantics (RubyHeadNode).
- * The example usage shows how methods can be redefined in this implementation.
- */
-@SuppressWarnings("unused")
-public class RubyCall {
-
-    @Test
-    public void testCall() {
-        RubyHeadNode node = RubyHeadNodeGen.create(createArguments(4));
-        CallTarget nodeTarget = createTarget(node);
-        final Object firstArgument = "someArgument";
-
-        // dummyMethod is just going to return the some argument of the function
-        final Object testMethodName = "getSomeArgument";
-        // implementation returns first argument
-        InternalMethod aClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(3));
-        // implementation returns second argument
-        InternalMethod bClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(4));
-        // implementation returns third argument
-        InternalMethod cClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(5));
-
-        // defines hierarchy C extends B extends A
-        RubyClass aClass = new RubyClass("A", null);
-        RubyClass bClass = new RubyClass("B", aClass);
-        RubyClass cClass = new RubyClass("C", bClass);
-
-        RubyObject aInstance = new RubyObject(aClass);
-        RubyObject bInstance = new RubyObject(bClass);
-        RubyObject cInstance = new RubyObject(cClass);
-
-        // undefined method call
-        assertEquals(RubyObject.NIL, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument}));
-
-        // method defined in a
-        aClass.addMethod(testMethodName, aClassTestMethod);
-        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument}));
-
-        // method redefined in b
-        bClass.addMethod(testMethodName, bClassTestMethod);
-        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, firstArgument}));
-
-        // method redefined in c
-        cClass.addMethod(testMethodName, cClassTestMethod);
-        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument}));
-        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, null, firstArgument}));
-
-    }
-
-    public static class RubyHeadNode extends ExampleNode {
-
-        @Child private RubyLookupNode lookup = RubyLookupNodeGen.create();
-        @Child private RubyDispatchNode dispatch = RubyDispatchNodeGen.create();
-
-        @Specialization
-        public Object doCall(VirtualFrame frame, RubyObject receiverObject, Object methodName, Object blockObject, Object... argumentsObjects) {
-            InternalMethod method = lookup.executeLookup(receiverObject, methodName);
-
-            Object[] packedArguments = new Object[argumentsObjects.length + 3];
-            packedArguments[0] = method;
-            packedArguments[1] = receiverObject;
-            packedArguments[2] = blockObject;
-            System.arraycopy(argumentsObjects, 0, packedArguments, 3, argumentsObjects.length);
-
-            return dispatch.executeDispatch(frame, method, packedArguments);
-        }
-    }
-
-    public abstract static class RubyLookupNode extends Node {
-
-        public abstract InternalMethod executeLookup(RubyObject receiver, Object method);
-
-        @Specialization(guards = "receiver.getRubyClass() == cachedClass", assumptions = "cachedClass.getDependentAssumptions()")
-        protected static InternalMethod cachedLookup(RubyObject receiver, Object name, //
-                        @Cached("receiver.getRubyClass()") RubyClass cachedClass, //
-                        @Cached("genericLookup(receiver, name)") InternalMethod cachedLookup) {
-            return cachedLookup;
-        }
-
-        @Specialization(contains = "cachedLookup")
-        protected static InternalMethod genericLookup(RubyObject receiver, Object name) {
-            return receiver.getRubyClass().lookup(name);
-        }
-
-    }
-
-    @ImportStatic(InternalMethod.class)
-    public abstract static class RubyDispatchNode extends Node {
-
-        public abstract Object executeDispatch(VirtualFrame frame, InternalMethod function, Object[] packedArguments);
-
-        /*
-         * Please note that cachedMethod != METHOD_MISSING is invoked once at specialization
-         * instantiation. It is never executed on the fast path.
-         */
-        @Specialization(guards = {"method == cachedMethod", "cachedMethod != METHOD_MISSING"})
-        protected static Object directCall(VirtualFrame frame, InternalMethod method, Object[] arguments, //
-                        @Cached("method") InternalMethod cachedMethod, //
-                        @Cached("create(cachedMethod.getTarget())") DirectCallNode callNode) {
-            return callNode.call(frame, arguments);
-        }
-
-        /*
-         * The method == METHOD_MISSING can fold if the RubyLookup results just in a single entry
-         * returning the constant METHOD_MISSING.
-         */
-        @Specialization(guards = "method == METHOD_MISSING")
-        protected static Object methodMissing(VirtualFrame frame, InternalMethod method, Object[] arguments) {
-            // a real implementation would do a call to a method named method_missing here
-            return RubyObject.NIL;
-        }
-
-        @Specialization(contains = "directCall", guards = "method != METHOD_MISSING")
-        protected static Object indirectCall(VirtualFrame frame, InternalMethod method, Object[] arguments, //
-                        @Cached("create()") IndirectCallNode callNode) {
-            return callNode.call(frame, method.getTarget(), arguments);
-        }
-
-        @Override
-        public String toString() {
-            return ((SpecializedNode) this).getSpecializationNode().toString();
-        }
-    }
-
-    public static final class RubyObject {
-
-        public static final RubyObject NIL = new RubyObject(null);
-
-        private final RubyClass rubyClass;
-
-        public RubyObject(RubyClass rubyClass) {
-            this.rubyClass = rubyClass;
-        }
-
-        public RubyClass getRubyClass() {
-            return rubyClass;
-        }
-
-        @Override
-        public String toString() {
-            return "RubyObject[class=" + rubyClass + "]";
-        }
-
-    }
-
-    public static final class RubyClass /* this would extend RubyModule */{
-
-        private final String name;
-        private final RubyClass parent; // this would be a RubyModule
-        private final CyclicAssumption unmodified;
-        private final Map<Object, InternalMethod> methods = new HashMap<>();
-        private Assumption[] cachedDependentAssumptions;
-        private final int depth;
-
-        public RubyClass(String name, RubyClass parent) {
-            this.name = name;
-            this.parent = parent;
-            this.unmodified = new CyclicAssumption("unmodified class " + name);
-
-            // lookup depth for array allocation
-            RubyClass clazz = parent;
-            int currentDepth = 1;
-            while (clazz != null) {
-                currentDepth++;
-                clazz = clazz.parent;
-            }
-            this.depth = currentDepth;
-        }
-
-        @TruffleBoundary
-        public InternalMethod lookup(Object methodName) {
-            InternalMethod method = methods.get(methodName);
-            if (method == null) {
-                if (parent != null) {
-                    return parent.lookup(methodName);
-                } else {
-                    return InternalMethod.METHOD_MISSING;
-                }
-            } else {
-                return method;
-            }
-        }
-
-        @TruffleBoundary
-        public void addMethod(Object methodName, InternalMethod method) {
-            // check for existing method omitted for simplicity
-            this.methods.put(methodName, method);
-            this.unmodified.invalidate();
-        }
-
-        /*
-         * Method collects all unmodified assumptions in the class hierarchy. The result is cached
-         * per class to void recreation per call site.
-         */
-        @TruffleBoundary
-        public Assumption[] getDependentAssumptions() {
-            Assumption[] dependentAssumptions = cachedDependentAssumptions;
-            if (dependentAssumptions != null) {
-                // we can use the cached dependent assumptions only if they are still valid
-                for (Assumption assumption : cachedDependentAssumptions) {
-                    if (!assumption.isValid()) {
-                        dependentAssumptions = null;
-                        break;
-                    }
-                }
-            }
-            if (dependentAssumptions == null) {
-                cachedDependentAssumptions = dependentAssumptions = createDependentAssumptions();
-            }
-            return dependentAssumptions;
-        }
-
-        @Override
-        public String toString() {
-            return "RubyClass[name=" + name + "]";
-        }
-
-        private Assumption[] createDependentAssumptions() {
-            Assumption[] dependentAssumptions;
-            RubyClass clazz = this;
-            dependentAssumptions = new Assumption[depth];
-
-            // populate array
-            int index = 0;
-            do {
-                dependentAssumptions[index] = clazz.unmodified.getAssumption();
-                index++;
-                clazz = clazz.parent;
-            } while (clazz != null);
-            return dependentAssumptions;
-        }
-    }
-
-    public static final class InternalMethod {
-
-        public static final InternalMethod METHOD_MISSING = new InternalMethod(null);
-
-        private final CallTarget target;
-
-        public InternalMethod(CallTarget target) {
-            this.target = target;
-        }
-
-        public CallTarget getTarget() {
-            return target;
-        }
-
-        @Override
-        public String toString() {
-            return "InternalMethod[target=" + getTarget() + "]";
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.examples;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-/**
- * This example is based on the SLDispatchNode of SimpleLanguage. It shows how to implement a simple
- * inline cache with an assumption that needs to be checked.
- *
- * Note that if an assumption is invalidated the specialization instantiation is removed.
- */
-@SuppressWarnings("unused")
-@NodeChildren({@NodeChild("function"), @NodeChild("arguments")})
-public class StableDispatch {
-
-    public static class StableDispatchNode extends ExampleNode {
-
-        @Specialization(guards = "function == cachedFunction", assumptions = "cachedFunction.getCallTargetStable()")
-        protected static Object directDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, //
-                        @Cached("function") SLFunction cachedFunction, //
-                        @Cached("create(cachedFunction.getCallTarget())") DirectCallNode callNode) {
-            return callNode.call(frame, arguments);
-        }
-
-        @Specialization(contains = "directDispatch")
-        protected static Object indirectDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, //
-                        @Cached("create()") IndirectCallNode callNode) {
-            return callNode.call(frame, function.getCallTarget(), arguments);
-        }
-    }
-
-    public static final class SLFunction {
-
-        private CallTarget callTarget;
-        private final CyclicAssumption callTargetStable;
-
-        protected SLFunction(String name) {
-            this.callTargetStable = new CyclicAssumption(name);
-        }
-
-        protected void setCallTarget(CallTarget callTarget) {
-            this.callTarget = callTarget;
-            this.callTargetStable.invalidate();
-        }
-
-        public CallTarget getCallTarget() {
-            return callTarget;
-        }
-
-        public Assumption getCallTargetStable() {
-            return callTargetStable.getAssumption();
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/Compile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.processor;
-
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import javax.tools.*;
-import javax.tools.JavaFileObject.Kind;
-
-final class Compile implements DiagnosticListener<JavaFileObject> {
-    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
-    private final Map<String, byte[]> classes;
-    private final String sourceLevel;
-
-    private Compile(Class<?> processor, String code, String sl) {
-        this.sourceLevel = sl;
-        classes = compile(processor, code);
-    }
-
-    /**
-     * Performs compilation of given HTML page and associated Java code.
-     */
-    public static Compile create(Class<?> processor, String code) {
-        return new Compile(processor, code, "1.7");
-    }
-
-    /** Checks for given class among compiled resources. */
-    public byte[] get(String res) {
-        return classes.get(res);
-    }
-
-    /**
-     * Obtains errors created during compilation.
-     */
-    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
-        List<Diagnostic<? extends JavaFileObject>> err;
-        err = new ArrayList<>();
-        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
-            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
-                err.add(diagnostic);
-            }
-        }
-        return err;
-    }
-
-    private Map<String, byte[]> compile(Class<?> processor, final String code) {
-        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
-
-        final Map<String, ByteArrayOutputStream> class2BAOS;
-        class2BAOS = new HashMap<>();
-
-        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
-            @Override
-            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
-                return code;
-            }
-        };
-
-        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
-            @Override
-            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
-                if (kind == Kind.CLASS) {
-                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-
-                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
-                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
-                        @Override
-                        public OutputStream openOutputStream() {
-                            return buffer;
-                        }
-                    };
-                }
-
-                if (kind == Kind.SOURCE) {
-                    final String n = className.replace('.', '/') + ".java";
-                    final URI un;
-                    try {
-                        un = new URI("mem://" + n);
-                    } catch (URISyntaxException ex) {
-                        throw new IOException(ex);
-                    }
-                    return new VirtFO(un/* sibling.toUri() */, kind, n);
-                }
-
-                throw new IllegalStateException();
-            }
-
-            @Override
-            public boolean isSameFile(FileObject a, FileObject b) {
-                if (a instanceof VirtFO && b instanceof VirtFO) {
-                    return ((VirtFO) a).getName().equals(((VirtFO) b).getName());
-                }
-
-                return super.isSameFile(a, b);
-            }
-
-            class VirtFO extends SimpleJavaFileObject {
-
-                private final String n;
-
-                public VirtFO(URI uri, Kind kind, String n) {
-                    super(uri, kind);
-                    this.n = n;
-                }
-
-                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
-
-                @Override
-                public OutputStream openOutputStream() {
-                    return data;
-                }
-
-                @Override
-                public String getName() {
-                    return n;
-                }
-
-                @Override
-                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
-                    data.close();
-                    return new String(data.toByteArray());
-                }
-            }
-        };
-        List<String> args = Arrays.asList("-source", sourceLevel, "-target", "1.7", //
-                        "-processor", processor.getName());
-
-        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, args, null, Arrays.asList(file)).call();
-
-        Map<String, byte[]> result = new HashMap<>();
-
-        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
-            result.put(e.getKey(), e.getValue().toByteArray());
-        }
-
-        return result;
-    }
-
-    @Override
-    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
-        errors.add(diagnostic);
-    }
-
-    void assertErrors() {
-        assertFalse("There are supposed to be some errors", getErrors().isEmpty());
-    }
-
-    void assertNoErrors() {
-        assertTrue("There are supposed to be no errors: " + getErrors(), getErrors().isEmpty());
-    }
-
-    void assertError(String expMsg) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Can't find ").append(expMsg).append(" among:");
-        for (Diagnostic<? extends JavaFileObject> e : errors) {
-            String msg = e.getMessage(Locale.US);
-            if (msg.contains(expMsg)) {
-                return;
-            }
-            sb.append("\n");
-            sb.append(msg);
-        }
-        fail(sb.toString());
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.processor;
-
-import java.io.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.dsl.test.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-
-public class LanguageRegistrationTest {
-
-    @ExpectError("Registered language class must be public")
-    @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my")
-    private static final class MyLang {
-    }
-
-    @ExpectError("Registered language inner-class must be static")
-    @TruffleLanguage.Registration(name = "myLangNonStatic", version = "0", mimeType = "text/x-my")
-    public final class MyLangNonStatic {
-    }
-
-    @ExpectError("Registered language class must subclass TruffleLanguage")
-    @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my")
-    public static final class MyLangNoSubclass {
-    }
-
-    @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter")
-    @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my")
-    public static final class MyLangWrongConstr extends TruffleLanguage {
-        private MyLangWrongConstr() {
-            super(null);
-        }
-
-        @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
-        }
-
-        @Override
-        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-            return null;
-        }
-
-        @Override
-        protected Object getLanguageGlobal() {
-            return null;
-        }
-
-        @Override
-        protected boolean isObjectOfLanguage(Object object) {
-            return false;
-        }
-
-        @Override
-        protected ToolSupportProvider getToolSupport() {
-            return null;
-        }
-
-        @Override
-        protected DebugSupportProvider getDebugSupport() {
-            return null;
-        }
-
-    }
-
-    @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter")
-    @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my")
-    public static final class MyLangNoConstr extends TruffleLanguage {
-        public MyLangNoConstr() {
-            super(null);
-        }
-
-        @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
-        }
-
-        @Override
-        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-            return null;
-        }
-
-        @Override
-        protected Object getLanguageGlobal() {
-            return null;
-        }
-
-        @Override
-        protected boolean isObjectOfLanguage(Object object) {
-            return false;
-        }
-
-        @Override
-        protected ToolSupportProvider getToolSupport() {
-            return null;
-        }
-
-        @Override
-        protected DebugSupportProvider getDebugSupport() {
-            return null;
-        }
-
-    }
-
-    @TruffleLanguage.Registration(name = "myLangGood", version = "0", mimeType = "text/x-my")
-    public static final class MyLangGood extends TruffleLanguage {
-        public MyLangGood(TruffleLanguage.Env env) {
-            super(env);
-        }
-
-        @Override
-        protected Object eval(Source code) throws IOException {
-            return null;
-        }
-
-        @Override
-        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-            return null;
-        }
-
-        @Override
-        protected Object getLanguageGlobal() {
-            return null;
-        }
-
-        @Override
-        protected boolean isObjectOfLanguage(Object object) {
-            return false;
-        }
-
-        @Override
-        protected ToolSupportProvider getToolSupport() {
-            return null;
-        }
-
-        @Override
-        protected DebugSupportProvider getDebugSupport() {
-            return null;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/TruffleProcessorTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.test.processor;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.tools.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.dsl.test.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.verify.*;
-
-/**
- * Verify errors emitted by the processor.
- */
-public class TruffleProcessorTest {
-    //
-    // AnnotationProcessor test using the NetBeans style
-    //
-
-    @Test
-    public void childCannotBeFinal() throws Exception {
-        // @formatter:off
-        String code = "package x.y.z;\n" +
-            "import com.oracle.truffle.api.nodes.Node;\n" +
-            "abstract class MyNode extends Node {\n" +
-            "  @Child final MyNode first;\n" +
-            "  MyNode(MyNode n) {\n" +
-            "    this.first = n;\n" +
-            "  };\n" +
-            "}\n";
-        // @formatter:on
-
-        Compile c = Compile.create(VerifyTruffleProcessor.class, code);
-        c.assertErrors();
-        boolean ok = false;
-        StringBuilder msgs = new StringBuilder();
-        for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
-            String msg = e.getMessage(Locale.ENGLISH);
-            if (msg.contains("cannot be final")) {
-                ok = true;
-            }
-            msgs.append("\n").append(msg);
-        }
-        if (!ok) {
-            fail("Should contain warning about final:" + msgs);
-        }
-    }
-
-    @Test
-    public void workAroundCannonicalDependency() throws Exception {
-        Class<?> myProc = VerifyTruffleProcessor.class;
-        assertNotNull(myProc);
-        StringBuilder sb = new StringBuilder();
-        sb.append("Cannot find ").append(myProc);
-        for (Processor load : ServiceLoader.load(Processor.class)) {
-            sb.append("Found ").append(load);
-            if (myProc.isInstance(load)) {
-                return;
-            }
-        }
-        fail(sb.toString());
-    }
-
-    //
-    // and now the Truffle traditional way
-    //
-
-    abstract class MyNode extends Node {
-        @ExpectError("@Child field cannot be final") @Child final MyNode first;
-
-        MyNode(MyNode n) {
-            this.first = n;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-/**
- * <p>
- * A parameter annotated with {@link Cached} in a {@link Specialization} refers to a <b>cached</b>
- * value of a specialization instance. A cached parameter value is initialized once using the
- * initializer expression at specialization instantiation. For each call of the specialization
- * method the cached value is provided by using the annotated parameter from the method body. Cache
- * initializers are potentially executed before guard expressions declared in
- * {@link Specialization#guards()}.
- * </p>
- * <p>
- * A typical specialization may define multiple dynamic and multiple cached parameters. Dynamic
- * parameter values are typically provided by executing child nodes of the operation. Cached
- * parameters are initialized and stored once per specialization instantiation. Cached parameters
- * are always constant at compile time. You may verify this by invoking
- * {@link CompilerAsserts#compilationConstant(Object)} on any cached parameter. For consistency
- * between specialization declarations cached parameters must be declared last in a specialization
- * method.
- * </p>
- * <p>
- * The initializer expression of a cached parameter is defined using a subset of Java. This subset
- * includes field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=,
- * >, >=) and integer literals. The return type of the initializer expression must be assignable to
- * the parameter type. If the annotated parameter type is derived from {@link Node} then the
- * {@link Node} instance is allowed to use the {@link Node#replace(Node)} method to replace itself.
- * Bound elements without receivers are resolved using the following order:
- * <ol>
- * <li>Dynamic and cached parameters of the enclosing specialization.</li>
- * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
- * <li>Public constructors of the type of the annotated parameter using the <code>new</code> keyword
- * as method name.</li>
- * <li>Public and static methods or fields of the type of the annotated parameter.</li>
- * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
- * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
- * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
- * </ol>
- *
- * The following examples explain the intended use of the {@link Cached} annotation. All of the
- * examples have to be enclosed in the following node declaration:
- * </p>
- *
- * <pre>
- * @NodeChild("operand")
- * abstract TestNode extends Node {
- *   abstract void execute(Object operandValue);
- *   // ... example here ...
- * }
- * </pre>
- *
- * <ol>
- * <li>
- * This example defines one dynamic and one cached parameter. The operand parameter is representing
- * the dynamic value of the operand while the cachedOperand is initialized once at first execution
- * of the specialization (specialization instantiation time).
- *
- * <pre>
- *  &#064;Specialization
- *  void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
- *      CompilerAsserts.compilationConstant(cachedOperand);
- *      ...
- *  }
- *
- *  Example executions:
- *  execute(1) => doCached(1, 1) // new instantiation, localOperand is bound to 1
- *  execute(0) => doCached(0, 1)
- *  execute(2) => doCached(2, 1)
- *
- * </pre>
- *
- * </li>
- * <li>
- * We extend the previous example by a guard for the cachedOperand value to be equal to the dynamic
- * operand value. This specifies that the specialization is instantiated for each individual operand
- * value that is provided. There are a lot of individual <code>int</code> values and for each
- * individual <code>int</code> value a new specialization would get instantiated. The
- * {@link Specialization#limit()} property defines a limit for the number of specializations that
- * can get instantiated. If the specialization instantiation limit is reached then no further
- * specializations are instantiated. Like for other specializations if there are no more
- * specializations defined an {@link UnsupportedSpecializationException} is thrown. The default
- * specialization instantiation limit is <code>3</code>.
- *
- * <pre>
- * &#064;Specialization(guards = &quot;operand == cachedOperand&quot;)
- * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
- *    CompilerAsserts.compilationConstant(cachedOperand);
- *    ...
- * }
- *
- * Example executions:
- * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
- * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
- * execute(1) => doCached(1, 1)
- * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
- * execute(3) => throws UnsupportedSpecializationException // instantiation limit overflows
- *
- * </pre>
- *
- * </li>
- * <li>
- * To handle the limit overflow we extend our example by an additional specialization named
- * <code>doNormal</code>. This specialization has the same type restrictions but does not have local
- * state nor the operand identity guard. It is also declared after <code>doCached</code> therefore
- * it is only instantiated if the limit of the <code>doCached</code> specialization has been
- * reached. In other words <code>doNormal</code> is more generic than <code>doCached</code> . The
- * <code>doNormal</code> specialization uses <code>contains=&quot;doCached&quot;</code> to specify
- * that all instantiations of <code>doCached</code> get removed if <code>doNormal</code> is
- * instantiated. Alternatively if the <code>contains</code> relation is omitted then all
- * <code>doCached</code> instances remain but no new instances are created.
- *
- * <code>
- * &#064;Specialization(guards = &quot;operand == cachedOperand&quot;)
- * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
- *    CompilerAsserts.compilationConstant(cachedOperand);
- *    ...
- * }
- *
- * &#064;Specialization(contains = &quot;doCached&quot;)
- * void doNormal(int operand) {...}
- *
- * Example executions with contains = &quot;doCached&quot;:
- * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
- * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
- * execute(1) => doCached(1, 1)
- * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
- * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow; doCached gets removed.
- * execute(1) => doNormal(1)
- *
- * Example executions without contains = &quot;doCached&quot;:
- * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
- * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
- * execute(1) => doCached(1, 1)
- * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
- * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow
- * execute(1) => doCached(1, 1)
- *
- * </code>
- *
- * </li>
- * <li>
- * This next example shows how methods from the enclosing node can be used to initialize cached
- * parameters. Please note that the visibility of transformLocal must not be <code>private</code>.
- *
- * <pre>
- * &#064;Specialization
- * void s(int operand, @Cached(&quot;transformLocal(operand)&quot;) int cachedOperand) {
- * }
- *
- * int transformLocal(int operand) {
- *     return operand & 0x42;
- * }
- *
- * </li>
- * </pre>
- * <li>
- * The <code>new</code> keyword can be used to initialize a cached parameter using a constructor of
- * the parameter type.
- *
- * <pre>
- * &#064;Specialization
- * void s(Object operand, @Cached(&quot;new()&quot;) OtherNode someNode) {
- *     someNode.execute(operand);
- * }
- *
- * static class OtherNode extends Node {
- *
- *     public String execute(Object value) {
- *         throw new UnsupportedOperationException();
- *     }
- * }
- *
- * </pre>
- *
- * </li>
- * <li>
- * Java types without public constructor but with a static factory methods can be initialized by
- * just referencing its static factory method and its parameters. In this case
- * {@link BranchProfile#create()} is used to instantiate the {@link BranchProfile} instance.
- *
- * <pre>
- * &#064;Specialization
- * void s(int operand, @Cached(&quot;create()&quot;) BranchProfile profile) {
- * }
- * </pre>
- *
- * </li>
- * </ol>
- *
- * @see Specialization#guards()
- * @see Specialization#contains()
- * @see Specialization#limit()
- * @see ImportStatic
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.PARAMETER})
-public @interface Cached {
-
-    /**
-     * Defines the initializer expression of the cached parameter value.
-     *
-     * @see Cached
-     */
-    String value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Specifies a factory method that creates a {@link Node} which is used to cast this child.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface CreateCast {
-
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <p>
- * A method annotated with {@link Fallback} is treated as a {@link Specialization} that implicitly
- * links all the guards of all other declared {@link Specialization} annotated methods of the
- * operation in a negated form. As a consequence it cannot declare any other guards. The expected
- * signature of the method must match to the signature of a {@link Specialization} with the
- * additional limitation that only generically executable argument types are allowed. A generically
- * executable argument is a an argument hat can be executed from the child {@link Node} using an
- * execute method without {@link UnsupportedOperationException}. In many cases the generically
- * executable type is {@link Object}. An operation is limited to just one {@link Fallback}
- * specialization which is always ordered at the end of the specialization chain.
- * </p>
- *
- * <p>
- * A simple example showing the use of the {@link Fallback} annotation in a DSL operation:
- * </p>
- *
- * <pre>
- * &#064;Specialization int doInt(int a) {..}
- * &#064;Specialization int doDouble(double a) {..}
- * &#064;Fallback int orElse(Object a) {..}
- * </pre>
- *
- * <p>
- * The previous example could be redeclared just using {@link Specialization} annotated methods as
- * follows:
- * </p>
- *
- * <pre>
- * &#064;Specialization int doInt(int a) {..}
- * &#064;Specialization int doDouble(double a) {..}
- * &#064;Specialization(guard={"!isInt(a)", "!isDouble(a)"})
- * int orElse(Object a) {..}
- * </pre>
- *
- * <p>
- * <b>Performance note:</b> For operations with a lot of {@link Specialization} annotated methods
- * the use of {@link Fallback} might generate a guard that is very big. Try to avoid the use of
- * {@link Fallback} for specializations that are significantly important for peak performance.
- * </p>
- *
- * @see Specialization
- * @see NodeChild
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface Fallback {
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GenerateNodeFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Annotate nodes or base classes of nodes to generate factory handlers implementing the
- * {@link NodeFactory} interface. The generated factory handlers class name starts with the source
- * original class and ends with 'Factory'.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface GenerateNodeFactory {
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Marks a type as being generated based on another class or method of a class.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-public @interface GeneratedBy {
-
-    Class<?> value();
-
-    String methodName() default "";
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface ImplicitCast {
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Experimental API.
- *
- * @deprecated annotation has no effect anymore.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-@Deprecated
-public @interface Implies {
-
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Imports all <code>public</code> and <code>static</code> methods and fields of the provided
- * classes for the use in DSL expressions of the annotated class or its subclasses.
- *
- * @see Specialization#guards()
- * @see Specialization#assumptions()
- * @see Specialization#limit()
- * @see Cached
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-public @interface ImportStatic {
-
-    Class<?>[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.*;
-
-/**
- * @deprecated use {@link NodeField} with type {@link Assumption} instead.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-@Deprecated
-public @interface NodeAssumptions {
-
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A
- * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeChild {
-
-    String value() default "";
-
-    Class<?> type() default Node.class;
-
-    /**
-     * The {@link #executeWith()} property allows a node to pass the result of one child's
-     * executable as an input to another child's executable. These referenced children must be
-     * defined before the current node in the execution order. The current node {@link #type()}
-     * attribute must be set to a {@link Node} which supports the evaluated execution with the
-     * number of {@link #executeWith()} arguments that are defined. For example if this child is
-     * executed with one argument, the {@link #type()} attribute must define a node which publicly
-     * declares a method with the signature <code>Object execute*(VirtualFrame, Object)</code>.
-     */
-    String[] executeWith() default {};
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeChildren {
-
-    NodeChild[] value() default {};
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate
- * generated node classes without using reflection.
- */
-public interface NodeFactory<T> {
-
-    /**
-     * Instantiates the node using the arguments array. The arguments length and types must suffice
-     * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does
-     * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown.
-     *
-     * @param arguments the argument values
-     * @return the instantiated node
-     * @throws IllegalArgumentException
-     */
-    T createNode(Object... arguments);
-
-    /**
-     * Returns the node class that will get created by {@link #createNode(Object...)}. The node
-     * class does not match exactly to the instantiated object but they are guaranteed to be
-     * assignable.
-     */
-    Class<T> getNodeClass();
-
-    /**
-     * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}.
-     */
-    List<List<Class<?>>> getNodeSignatures();
-
-    /**
-     * Returns a list of children that will be executed by the created node. This is useful for base
-     * nodes that can execute a variable amount of nodes.
-     */
-    List<Class<? extends Node>> getExecutionSignature();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeField.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A {@link NodeField} element defines a field for the generated {@link Node}. A {@link Node}
- * contains multiple {@link NodeFields} specified in linear declaration order. The field can be
- * accessed by declaring an abstract getter named
- * <code>"get" + firstLetterUpperCase({@link #name()})()</code>.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeField {
-
-    String name();
-
-    Class<?> type();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFields.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A {@link NodeFields} element defines a field for the generated {@link Node}. A {@link Node}
- * contains multiple {@link NodeFields} specified in linear declaration order. The field can be
- * accessed by declaring an abstract getter named
- * <code>"get" + firstLetterUpperCase({@link #value()})()</code>.
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface NodeFields {
-
-    NodeField[] value() default {};
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface ShortCircuit {
-
-    String value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <p>
- * Defines a method of a node subclass to represent one specialization of an operation. Multiple
- * specializations can be defined in a node representing an operation. A specialization defines
- * which kind of input is expected using the method signature and the annotation attributes. The
- * specialized semantics of the operation are defined using the body of the annotated Java method. A
- * specialization method must be declared in a class that is derived from {@link Node} that
- * references a {@link TypeSystem}. At least one specialization must be defined per operation. If no
- * specialization is valid for the given set of input values then an
- * {@link UnsupportedSpecializationException} is thrown instead of invoking any specialization
- * method.
- * </p>
- * <p>
- * A specialization must have at least as many parameters as there are {@link NodeChild} annotations
- * declared for the enclosing operation node. These parameters are declared in the same order as the
- * {@link NodeChild} annotations (linear execution order). We call such parameters dynamic input
- * parameters. Every specialization that is declared within an operation must have an equal number
- * of dynamic input parameters.
- * </p>
- * <p>
- * The supported kind of input values for a specialization are declared using guards. A
- * specialization may provide declarative specifications for four kinds of guards:
- * <ul>
- * <li><b>Type guards</b> optimistically assume the type of an input value. A value that matches the
- * type is cast to its expected type automatically. Type guards are modeled using the parameter type
- * of the specialization method. Types used for type guards must be defined in the
- * {@link TypeSystem}. If the type of the parameter is {@link Object} then no type guard is used for
- * the dynamic input parameter.</li>
- *
- * <li><b>Expression guards</b> optimistically assume the return value of a user-defined expression
- * to be <code>true</code>. Expression guards are modeled using Java expressions that return a
- * <code>boolean</code> value. If the guard expression returns <code>false</code>, the
- * specialization is no longer applicable and the operation is re-specialized. Guard expressions are
- * declared using the {@link #guards()} attribute.</li>
- *
- * <li><b>Event guards</b> trigger re-specialization in case an exception is thrown in the
- * specialization body. The {@link #rewriteOn()} attribute can be used to declare a list of such
- * exceptions. Guards of this kind are useful to avoid calculating a value twice when it is used in
- * the guard and its specialization.</li>
- *
- * <li><b>Assumption guards</b> optimistically assume that the state of an {@link Assumption}
- * remains <code>true</code>. Assumptions can be assigned to specializations using the
- * {@link #assumptions()} attribute.</li>
- * </ul>
- * </p>
- * <p>
- * The enclosing {@link Node} of a specialization method must have at least one <code>public</code>
- * and non-<code>final</code> execute method. An execute method is a method that starts with
- * 'execute'. If all execute methods declare the first parameter type as {@link Frame},
- * {@link VirtualFrame} or {@link MaterializedFrame} then the same frame type can be used as
- * optional first parameter of the specialization. This parameter does not count to the number of
- * dynamic parameters.
- * </p>
- * <p>
- * A specialization method may declare multiple parameters annotated with {@link Cached}. Cached
- * parameters are initialized and stored once per specialization instantiation. For consistency
- * between specialization declarations cached parameters must be declared last in a specialization
- * method.
- * </p>
- * <p>
- * If the operation is re-specialized or if it is executed for the first time then all declared
- * specializations of the operation are tried in declaration order until the guards of the first
- * specialization accepts the current input values. The new specialization is then added to the
- * chain of current specialization instances which might consist of one (monomorph) or multiple
- * instances (polymorph). If an assumption of an instantiated specialization is violated then
- * re-specialization is triggered again.
- * </p>
- * <p>
- * With guards in combination with cached parameters it is possible that multiple instances of the
- * same specialization are created. The {@link #limit()} attribute can be used to limit the number
- * of instantiations per specialization.
- * </p>
- *
- * @see NodeChild
- * @see ShortCircuit
- * @see Fallback
- * @see Cached
- * @see TypeSystem
- * @see TypeSystemReference
- * @see UnsupportedSpecializationException
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
-public @interface Specialization {
-
-    /**
-     * @deprecated do not use anymore. Will get removed in the next release.
-     */
-    @Deprecated int DEFAULT_ORDER = -1;
-
-    /**
-     * @deprecated use declaration order instead. Will get removed in the next release.
-     */
-    @Deprecated
-    int order() default DEFAULT_ORDER;
-
-    /**
-     * References a specialization of a super class by its method name where this specialization is
-     * inserted before. The declaration order of a specialization is not usable for nodes where
-     * specializations are partly declared in the super class and partly declared in a derived
-     * class. By default all specializations declared in the derived class are appended to those in
-     * the super class. This attribute can be used to override the default behavior.
-     */
-    String insertBefore() default "";
-
-    /**
-     * <p>
-     * Declares an event guards that trigger re-specialization in case an exception is thrown in the
-     * specialization body. This attribute can be used to declare a list of such exceptions. Guards
-     * of this kind are useful to avoid calculating a value twice when it is used in the guard and
-     * its specialization.
-     * </p>
-     *
-     * <p>
-     * If an event guard exception is triggered then all instantiations of this specialization are
-     * removed. If one of theses exceptions is thrown once then no further instantiations of this
-     * specialization are going to be created for this node. A specialization that rewrites on an
-     * exception must ensure that no non-repeatable side-effect is caused until the rewrite is
-     * triggered.
-     * </p>
-     *
-     * <b>Example usage:</b>
-     *
-     * <pre>
-     * &#064;Specialization(rewriteOn = ArithmeticException.class)
-     * int doAddNoOverflow(int a, int b) {
-     *     return ExactMath.addExact(a, b);
-     * }
-     * &#064;Specialization
-     * long doAddWithOverflow(int a, int b) {
-     *     return a + b;
-     * }
-     * ...
-     * Example executions:
-     *   execute(Integer.MAX_VALUE - 1, 1) => doAddNoOverflow(Integer.MAX_VALUE - 1, 1)
-     *   execute(Integer.MAX_VALUE, 1)     => doAddNoOverflow(Integer.MAX_VALUE, 1)
-     *                                     => throws ArithmeticException
-     *                                     => doAddWithOverflow(Integer.MAX_VALUE, 1)
-     *   execute(Integer.MAX_VALUE - 1, 1) => doAddWithOverflow(Integer.MAX_VALUE - 1, 1)
-     * </pre>
-     *
-     * </p>
-     *
-     * @see ExactMath#addExact(int, int)
-     */
-    Class<? extends Throwable>[] rewriteOn() default {};
-
-    /**
-     * <p>
-     * Declares other specializations of the same node to be contained by this specialization. Other
-     * specializations are references using their unique method name. If this specialization is
-     * instantiated then all contained specialization instances are removed and never instantiated
-     * again for this node instance. Therefore this specialization should handle strictly more
-     * inputs than which were handled by the contained specialization, otherwise the removal of the
-     * contained specialization will lead to unspecialized types of input values. The contains
-     * declaration is transitive for multiple involved specializations.
-     * </p>
-     * <b>Example usage:</b>
-     *
-     * <pre>
-     * &#064;Specialization(guards = "b == 2")
-     * void doDivPowerTwo(int a, int b) {
-     *     return a >> 1;
-     * }
-     * &#064;Specialization(contains ="doDivPowerTwo", guards = "b > 0")
-     * void doDivPositive(int a, int b) {
-     *     return a / b;
-     * }
-     * ...
-     * Example executions with contains="doDivPowerTwo":
-     *   execute(4, 2) => doDivPowerTwo(4, 2)
-     *   execute(9, 3) => doDivPositive(9, 3) // doDivPowerTwo instances get removed
-     *   execute(4, 2) => doDivPositive(4, 2)
-     * Same executions without contains="doDivPowerTwo"
-     *   execute(4, 2) => doDivPowerTwo(4, 2)
-     *   execute(9, 3) => doDivPositive(9, 3)
-     *   execute(4, 2) => doDivPowerTwo(4, 2)
-     * </pre>
-     *
-     * </p>
-     *
-     * @see #guards()
-     */
-    String[] contains() default {};
-
-    /**
-     * <p>
-     * Declares <code>boolean</code> expressions that define whether or not input values are
-     * applicable to this specialization instance. Guard expressions must always return the same
-     * result for each combination of the enclosing node instance and the bound input values.
-     * </p>
-     * <p>
-     * If a guard expression does not bind any dynamic input parameters then the DSL assumes that
-     * the result will not change for this node after specialization instantiation. The DSL asserts
-     * this assumption if assertions are enabled (-ea).
-     * </p>
-     * <p>
-     * Guard expressions are defined using a subset of Java. This subset includes field/parameter
-     * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
-     * negation (!), logical disjunction (||) and integer literals. The return type of guard
-     * expressions must be <code>boolean</code>. Bound elements without receivers are resolved using
-     * the following order:
-     * <ol>
-     * <li>Dynamic and cached parameters of the enclosing specialization.</li>
-     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
-     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
-     * </ol>
-     * </p>
-     * <p>
-     * <b>Example usage:</b>
-     *
-     * <pre>
-     * static boolean acceptOperand(int operand) {
-     *     assert operand <= 42;
-     *     return operand & 1 == 1;
-     * }
-     * &#064;Specialization(guards = {"operand <= 42", "acceptOperand(operand)"})
-     * void doSpecialization(int operand) {...}
-     * </pre>
-     *
-     * </p>
-     *
-     * @see Cached
-     * @see ImportStatic
-     */
-    String[] guards() default {};
-
-    /**
-     * <p>
-     * Declares assumption guards that optimistically assume that the state of an {@link Assumption}
-     * remains valid. Assumption expressions are cached once per specialization instantiation. If
-     * one of the returned assumptions gets invalidated then the specialization instance is removed.
-     * If the assumption expression returns an array of assumptions then all assumptions of the
-     * array are checked. This is limited to one-dimensional arrays.
-     * </p>
-     * <p>
-     * Assumption expressions are defined using a subset of Java. This subset includes
-     * field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=, >,
-     * >=), logical negation (!), logical disjunction (||) and integer literals. The return type of
-     * the expression must be {@link Assumption} or an array of {@link Assumption} instances.
-     * Assumption expressions are not allowed to bind to dynamic parameter values of the
-     * specialization. Bound elements without receivers are resolved using the following order:
-     * <ol>
-     * <li>Cached parameters of the enclosing specialization.</li>
-     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
-     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
-     * </ol>
-     * </p>
-     *
-     * <p>
-     * <b>Example usage:</b>
-     *
-     * <pre>
-     * static abstract class DynamicObject() {
-     *      abstract Shape getShape();
-     *      ...
-     * }
-     * static abstract class Shape() {
-     *      abstract Assumption getUnmodifiedAssuption();
-     *      ...
-     * }
-     * &#064;Specialization(guards = "operand.getShape() == cachedShape", assumptions = "cachedShape.getUnmodifiedAssumption()")
-     * void doAssumeUnmodifiedShape(DynamicObject operand, @Cached("operand.getShape()") Shape cachedShape) {...}
-     * </pre>
-     *
-     * </p>
-     *
-     * @see Cached
-     * @see ImportStatic
-     */
-    String[] assumptions() default {};
-
-    /**
-     * <p>
-     * Declares the expression that limits the number of specialization instantiations. The default
-     * limit for specialization instantiations is defined as <code>"3"</code>. If the limit is
-     * exceeded no more instantiations of the enclosing specialization method are created. Please
-     * note that the existing specialization instantiations are <b>not</b> removed from the
-     * specialization chain. You can use {@link #contains()} to remove unnecessary specializations
-     * instances.
-     * </p>
-     * <p>
-     * The limit expression is defined using a subset of Java. This subset includes field/parameter
-     * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
-     * negation (!), logical disjunction (||) and integer literals. The return type of the limit
-     * expression must be <code>int</code>. Limit expressions are not allowed to bind to dynamic
-     * parameter values of the specialization. Bound elements without receivers are resolved using
-     * the following order:
-     * <ol>
-     * <li>Cached parameters of the enclosing specialization.</li>
-     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
-     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
-     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
-     * </ol>
-     * </p>
-     *
-     * <p>
-     * <b>Example usage:</b>
-     *
-     * <pre>
-     * static int getCacheLimit() {
-     *     return Integer.parseInt(System.getProperty("language.cacheLimit"));
-     * }
-     * &#064;Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()")
-     * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...}
-     * </pre>
-     *
-     * </p>
-     *
-     * @see #guards()
-     * @see #contains()
-     * @see Cached
-     * @see ImportStatic
-     */
-    String limit() default "";
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Overrides the standard way of casting a certain type in a {@link TypeSystem}. This is useful for
- * types where the guest language specific type cast can be implemented more efficiently than an
- * instanceof check. The annotated method must be contained in a {@link TypeSystem} annotated class.
- * Type checks must conform to the following signature: <code>public static Type as{TypeName}(Object
- * value)</code>. The casted type must be a type declared in the {@link TypeSystem}.
- *
- * <p>
- * If no {@link TypeCast} is declared then the type system implicitly uses a type cast that can be
- * declared as follows:
- *
- * <pre>
- * {@literal @}TypeCast(Type.class)
- * public static Type asType(Object value) {
- *         return (Type) value;
- * }
- * </pre>
- *
- * @see TypeCheck
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface TypeCast {
-
-    Class<?> value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-/**
- * Overrides the standard way of checking for a certain type in a {@link TypeSystem}. This is useful
- * for types where the guest language specific type check can be implemented more efficiently than a
- * direct cast. The annotated method must be contained in a {@link TypeSystem} annotated class. Type
- * checks must conform to the following signature: <code>public static boolean is{TypeName}(Object
- * value)</code>. The checked type must be a type declared in the {@link TypeSystem}.
- *
- * <p>
- * If no {@link TypeCheck} is declared then the type system implicitly uses a type check that can be
- * declared as follows:
- *
- * <pre>
- * {@literal @}TypeCheck(Type.class)
- * public static boolean isType(Object value) {
- *         return value instanceof Type;
- * }
- * </pre>
- *
- * @see TypeCast
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD})
-public @interface TypeCheck {
-
-    Class<?> value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <p>
- * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used
- * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside
- * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child
- * elements, in which every type precedes its super types.The latter condition ensures that the most
- * concrete type is found first when searching the list sequentially for the type of a given generic
- * value.
- * </p>
- *
- * <p>
- * Each {@link #value()} is represented as a java type. A type can specify two annotations:
- * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic
- * value matches to the current type. The {@link TypeCast} casts a generic type value to the current
- * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the
- * {@link TypeSystem} the a default implementation is provided. The default implementation of
- * {@link TypeCheck} returns <code>true</code> only on an exact type match and {@link TypeCast} is
- * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be
- * used to extend the definition of a type in the language. In our example, the
- * <code>isInteger</code> and <code>asInteger</code> methods are defined in a way so that they
- * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example
- * points out how we express implicit type conversions.
- * </p>
- *
- * <p>
- * <b>Example:</b> The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and
- * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent
- * all values.
- *
- * <pre>
- *
- * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
- * public abstract class ExampleTypeSystem {
- *
- *     {@literal @}TypeCheck
- *     public boolean isInteger(Object value) {
- *         return value instanceof Integer || value instanceof Double;
- *     }
- *
- *     {@literal @}TypeCast
- *     public double asInteger(Object value) {
- *         return ((Number)value).doubleValue();
- *     }
- * }
- * </pre>
- *
- *
- * @see TypeCast
- * @see TypeCheck
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface TypeSystem {
-
-    /**
-     * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type.
-     */
-    Class<?>[] value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one
- * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy.
- *
- * @see TypeSystem
- * @see Node
- */
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.TYPE})
-public @interface TypeSystemReference {
-
-    /** The {@link TypeSystem} java type. */
-    Class<?> value();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl;
-
-import java.util.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Thrown by the generated code of Truffle-DSL if no compatible Specialization could be found for
- * the provided values.
- */
-public final class UnsupportedSpecializationException extends RuntimeException {
-
-    private static final long serialVersionUID = -2122892028296836269L;
-
-    private final Node node;
-    private final Node[] suppliedNodes;
-    private final Object[] suppliedValues;
-
-    @TruffleBoundary
-    public UnsupportedSpecializationException(Node node, Node[] suppliedNodes, Object... suppliedValues) {
-        Objects.requireNonNull(suppliedNodes, "The suppliedNodes parameter must not be null.");
-        if (suppliedNodes.length != suppliedValues.length) {
-            throw new IllegalArgumentException("The length of suppliedNodes must match the length of suppliedValues.");
-        }
-        this.node = node;
-        this.suppliedNodes = suppliedNodes;
-        this.suppliedValues = suppliedValues;
-    }
-
-    @Override
-    public String getMessage() {
-        return String.format("Unexpected values provided for %s: %s", node, Arrays.toString(suppliedValues));
-    }
-
-    /**
-     * Returns the {@link Node} that caused the this {@link UnsupportedSpecializationException}.
-     */
-    public Node getNode() {
-        return node;
-    }
-
-    /**
-     * Returns the children of the {@link Node} returned by {@link #getNode()} which produced the
-     * values returned by {@link #getSuppliedValues()}. The array returned by
-     * {@link #getSuppliedNodes()} has the same length as the array returned by
-     * {@link #getSuppliedValues()}. Never returns null.
-     */
-    public Node[] getSuppliedNodes() {
-        return suppliedNodes;
-    }
-
-    /**
-     * Returns the dynamic values that were supplied to the node.The array returned by
-     * {@link #getSuppliedNodes()} has the same length as the array returned by
-     * {@link #getSuppliedValues()}. Never returns null.
-     */
-    public Object[] getSuppliedValues() {
-        return suppliedValues;
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-/**
- * This is NOT public API. Do not use directly. This code may change without notice.
- */
-public final class DSLMetadata {
-
-    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[]{};
-    public static final DSLMetadata NONE = new DSLMetadata(null, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, 0, 0);
-
-    private final Class<?> specializationClass;
-    private final Class<?>[] includes;
-    private final Class<?>[] excludedBy;
-    private final Class<?>[] specializedTypes;
-
-    private final int costs;
-    private final int order;
-
-    public DSLMetadata(Class<?> specializationClass, Class<?>[] includes, Class<?>[] excludes, Class<?>[] specializedTypes, int costs, int order) {
-        this.specializationClass = specializationClass;
-        this.includes = includes;
-        this.excludedBy = excludes;
-        this.specializedTypes = specializedTypes;
-        this.costs = costs;
-        this.order = order;
-    }
-
-    public Class<?> getSpecializationClass() {
-        return specializationClass;
-    }
-
-    public Class<?>[] getSpecializedTypes() {
-        return specializedTypes;
-    }
-
-    Class<?>[] getIncludes() {
-        return includes;
-    }
-
-    Class<?>[] getExcludedBy() {
-        return excludedBy;
-    }
-
-    int getCosts() {
-        return costs;
-    }
-
-    int getOrder() {
-        return order;
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is NOT public API. Do not use directly. This code may change without notice.
- */
-public interface DSLNode {
-
-    DSLMetadata getMetadata0();
-
-    void adoptChildren0(Node other, Node next);
-
-    void updateTypes0(Class<?>[] types);
-
-    Node getNext0();
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import java.lang.annotation.*;
-
-/**
- * Internal DSL options to tune the generated code. These are expert options and not intended to be
- * changed used for guest language implementations.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-public @interface DSLOptions {
-
-    /** Flag has no effect anymore. Is going to be removed soon. */
-    @Deprecated
-    boolean useNewLayout() default true;
-
-    /**
-     * Lazy class loading ensures that all generated specialization classes are loaded lazily.
-     * Disabling this feature will eagerly load all classes but will also reduce the generated code
-     * size.
-     */
-    boolean useLazyClassLoading() default true;
-
-    /**
-     * Sets the optimization strategy for implicit casts.
-     */
-    ImplicitCastOptimization implicitCastOptimization() default ImplicitCastOptimization.DUPLICATE_TAIL;
-
-    /** Not yet implemented. */
-    boolean useDisjunctiveMethodGuardOptimization() default true;
-
-    public enum ImplicitCastOptimization {
-
-        /** Perform no informed optimization for implicit casts. */
-        NONE,
-
-        /** Duplicate specializations for each used implicit cast combination. */
-        DUPLICATE_TAIL,
-
-        /**
-         * Use the same specialization for multiple combinations of implicit casts and specialize
-         * them independently. Not yet fully implemented.
-         */
-        MERGE_CASTS;
-
-        public boolean isNone() {
-            return this == NONE;
-        }
-
-        public boolean isDuplicateTail() {
-            return this == DUPLICATE_TAIL;
-        }
-
-        public boolean isMergeCasts() {
-            return this == MERGE_CASTS;
-        }
-    }
-
-    public enum TypeBoxingOptimization {
-        /** Perform the optimization for all types. */
-        ALWAYS,
-        /** Perform the optimization just for primitive types. */
-        PRIMITIVE,
-        /** Perform the optimization for no types. */
-        NONE;
-    }
-
-    /**
-     * Defines the range of the generation of type specialized execute methods for return types and
-     * for specialized parameter types. A type specialized execute method is generated as soon as
-     * one declared type is either returned or used a specialized parameter.
-     */
-    TypeBoxingOptimization monomorphicTypeBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
-
-    /**
-     * Defines the range of types for which type specialized execute methods should be used for
-     * polymorphic operations.
-     */
-    TypeBoxingOptimization polymorphicTypeBoxingElimination() default TypeBoxingOptimization.PRIMITIVE;
-
-    /**
-     * Defines the range of types for which type specialized execute methods for implicit cast
-     * optimizations are used. This option only has an effect if
-     * {@link ImplicitCastOptimization#DUPLICATE_TAIL} or
-     * {@link ImplicitCastOptimization#MERGE_CASTS} is set in {@link #implicitCastOptimization()}.
-     */
-    TypeBoxingOptimization implicitTypeBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
-
-    /**
-     * Defines range of specialization return types in which the void boxing optimization is used.
-     * Void boxing generates an extra execute method with {@link Void} return type in order to avoid
-     * boxing and type checking of the return type in case the return type is not needed. For this
-     * to work the operation class needs to provide an overridable execute method returning
-     * {@link Void}.
-     */
-    TypeBoxingOptimization voidBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
-
-    public enum FallbackOptimization {
-        /** Always generate an optimized fallback specialization. */
-        ALWAYS,
-
-        /**
-         * Only generate an optimized fallback specialization if a method annotated with @Fallback
-         * is used in the operation.
-         */
-        DECLARED,
-
-        /**
-         * Never generate an optimized fallback specialization. Please be aware that triggering a @Fallback
-         * case without optimization will also invalidate your compiled code.
-         */
-        NEVER;
-    }
-
-    /** Defines the optimization strategy that is used to optimize @Fallback annotated methods. */
-    FallbackOptimization optimizeFallback() default FallbackOptimization.DECLARED;
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/** Contains utility classes shared across generated DSLNode implementations. */
-public class DSLShare {
-
-    public static boolean isExcluded(Node currentNode, DSLMetadata otherMetadata) {
-        assert otherMetadata.getExcludedBy().length > 0 : "At least one exclude must be defined for isIncluded.";
-        Node cur = findRoot(currentNode);
-        while (cur != null) {
-            Class<?> curClass = cur.getClass();
-            if (curClass == otherMetadata.getSpecializationClass()) {
-                return true;
-            } else if (containsClass(otherMetadata.getExcludedBy(), cur)) {
-                return true;
-            }
-            cur = getNext(cur);
-        }
-        return false;
-    }
-
-    private static boolean includes(Node oldNode, DSLNode newNode) {
-        return containsClass(newNode.getMetadata0().getIncludes(), oldNode);
-    }
-
-    public static <T extends Node & DSLNode> T rewrite(final Node thisNode, final T newNode, final String message) {
-        return thisNode.atomic(new Callable<T>() {
-            public T call() {
-                assert newNode != null;
-                if (getNext(thisNode) != null || getPrevious(thisNode) != null) {
-                    // already polymorphic -> append
-                    return appendPolymorphic(findUninitialized(thisNode), newNode);
-                } else if (includes(thisNode, newNode)) {
-                    // included -> remains monomorphic
-                    newNode.adoptChildren0(thisNode, null);
-                    return thisNode.replace(newNode, message);
-                } else {
-                    // goto polymorphic
-                    return null;
-                }
-            }
-        });
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T extends Node> T findRoot(T node) {
-        Node prev = node;
-        Node cur;
-        do {
-            cur = prev;
-            prev = getPrevious(cur);
-        } while (prev != null);
-        return (T) cur;
-    }
-
-    private static Node findUninitialized(Node node) {
-        Node next = node;
-        Node cur;
-        do {
-            cur = next;
-            next = getNext(cur);
-        } while (next != null);
-        return cur;
-    }
-
-    public static <T extends Node & DSLNode> T rewriteUninitialized(final Node uninitialized, final T newNode) {
-        return uninitialized.atomic(new Callable<T>() {
-            public T call() {
-                Node prev = getPrevious(uninitialized);
-                if (prev == null) {
-                    newNode.adoptChildren0(uninitialized, null);
-                    return uninitialized.replace(newNode, "Uninitialized monomorphic");
-                } else {
-                    return appendPolymorphic(uninitialized, newNode);
-                }
-            }
-        });
-
-    }
-
-    public static <T extends Node & DSLNode> T rewriteToPolymorphic(final Node oldNode, final DSLNode uninitializedDSL, final T polymorphic, final DSLNode currentCopy, final DSLNode newNodeDSL,
-                    final String message) {
-        return oldNode.atomic(new Callable<T>() {
-            public T call() {
-                assert getNext(oldNode) == null;
-                assert getPrevious(oldNode) == null;
-                assert newNodeDSL != null;
-
-                Node uninitialized = (Node) uninitializedDSL;
-                Node newNode = (Node) newNodeDSL;
-                polymorphic.adoptChildren0(oldNode, (Node) currentCopy);
-
-                updateSourceSection(oldNode, uninitialized);
-                // new specialization
-                updateSourceSection(oldNode, newNode);
-                newNodeDSL.adoptChildren0(null, uninitialized);
-                currentCopy.adoptChildren0(null, newNode);
-
-                oldNode.replace(polymorphic, message);
-
-                assert newNode != null ? currentCopy.getNext0() == newNode : currentCopy.getNext0() == uninitialized;
-                assert uninitializedDSL.getNext0() == null;
-                return polymorphic;
-            }
-        });
-    }
-
-    private static void updateSourceSection(Node oldNode, Node newNode) {
-        if (newNode.getSourceSection() == null) {
-            newNode.assignSourceSection(oldNode.getSourceSection());
-        }
-    }
-
-    private static Class<?>[] mergeTypes(DSLNode node, Class<?>[] types) {
-        Class<?>[] specializedTypes = node.getMetadata0().getSpecializedTypes();
-        if (specializedTypes.length == 0) {
-            return null;
-        } else if (types == null) {
-            return Arrays.copyOf(specializedTypes, specializedTypes.length);
-        } else {
-            for (int i = 0; i < specializedTypes.length; i++) {
-                if (specializedTypes[i] != types[i]) {
-                    types[i] = Object.class;
-                }
-            }
-            return types;
-        }
-    }
-
-    private static <T extends Node & DSLNode> T appendPolymorphic(Node uninitialized, T newNode) {
-        Class<?>[] includes = newNode.getMetadata0().getIncludes();
-        Node cur = getPrevious(uninitialized);
-        Node prev = uninitialized;
-        int depth = 0;
-        Class<?>[] types = null;
-        while (cur != null) {
-            if (containsClass(includes, cur)) {
-                cur.replace(prev, "Included in other specialization");
-                cur = prev;
-            } else {
-                depth++;
-                types = mergeTypes((DSLNode) cur, types);
-            }
-            prev = cur;
-            cur = getPrevious(cur);
-        }
-        assert prev.getCost() == NodeCost.POLYMORPHIC;
-
-        updateSourceSection(prev, newNode);
-        if (depth <= 1) {
-            newNode.adoptChildren0(prev, null);
-            return prev.replace(newNode, "Polymorphic to monomorphic.");
-        } else {
-            newNode.adoptChildren0(null, uninitialized);
-            ((DSLNode) prev).updateTypes0(mergeTypes(newNode, types));
-            return uninitialized.replace(newNode, "Appended polymorphic");
-        }
-    }
-
-    private static boolean containsClass(Class<?>[] classList, Node node) {
-        Class<?> nodeClass = node.getClass();
-        for (Class<?> toCheck : classList) {
-            if (nodeClass == toCheck) {
-                if (node.getCost() == NodeCost.UNINITIALIZED) {
-                    /*
-                     * In case a specialization is excluded by the fallback specialization the
-                     * uninitialized class is used as exclusion class. Because the fallback field in
-                     * the uninitialized specialization is not accessible we use the costs to check
-                     * if the fallback was reached or not. In case the fallback was reached in the
-                     * uninitialized version the cost is MONOMORPHIC, otherwise it is UNINITIALIZED.
-                     */
-                    continue;
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static Node getNext(Node node) {
-        return ((DSLNode) node).getNext0();
-    }
-
-    private static Node getPrevious(Node node) {
-        Node parent = node.getParent();
-        if (parent instanceof DSLNode && getNext(parent) == node) {
-            return parent;
-        } else {
-            return null;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import java.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is NOT public API. Do not use directly. This code may change without notice.
- */
-public abstract class NodeFactoryBase<T> implements NodeFactory<T> {
-
-    private final Class<T> nodeClass;
-    private final Class<?>[][] nodeSignatures;
-    private final Class<? extends Node>[] executionSignatures;
-
-    @SuppressWarnings("unchecked")
-    public NodeFactoryBase(Class<T> nodeClass, Class<?>[] executionSignatures, Class<?>[][] nodeSignatures) {
-        this.nodeClass = nodeClass;
-        this.nodeSignatures = nodeSignatures;
-        this.executionSignatures = (Class<? extends Node>[]) executionSignatures;
-    }
-
-    public abstract T createNode(Object... arguments);
-
-    public final Class<T> getNodeClass() {
-        return nodeClass;
-    }
-
-    public final List<List<Class<?>>> getNodeSignatures() {
-        List<List<Class<?>>> signatures = new ArrayList<>();
-        for (int i = 0; i < nodeSignatures.length; i++) {
-            signatures.add(Arrays.asList(nodeSignatures[i]));
-        }
-        return signatures;
-    }
-
-    public final List<Class<? extends Node>> getExecutionSignature() {
-        return Arrays.asList(executionSignatures);
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SlowPathEvent.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Lazy rewrite event that implements {@link CharSequence} to be provided as message in
- * {@link Node#replace(Node, CharSequence)}.
- */
-abstract class SlowPathEvent implements CharSequence {
-
-    protected final SpecializationNode source;
-    protected final String reason;
-    protected final Frame frame;
-    private String message;
-
-    SlowPathEvent(SpecializationNode source, String reason, Frame frame) {
-        this.source = source;
-        this.reason = reason;
-        this.frame = frame;
-    }
-
-    public int length() {
-        return getMessage().length();
-    }
-
-    public char charAt(int index) {
-        return getMessage().charAt(index);
-    }
-
-    public CharSequence subSequence(int start, int end) {
-        return getMessage().subSequence(start, end);
-    }
-
-    @Override
-    public String toString() {
-        return getMessage();
-    }
-
-    private String getMessage() {
-        if (message == null) {
-            message = createMessage();
-        }
-        return message;
-    }
-
-    private String createMessage() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(source);
-        builder.append(" ");
-        builder.append(reason);
-        Object[] values = getValues();
-        if (values.length > 0) {
-            builder.append(" with parameters (");
-            String sep = "";
-            for (Object value : values) {
-                builder.append(sep);
-                if (value == null) {
-                    builder.append("null");
-                } else {
-                    builder.append(value).append(" (").append(value.getClass().getSimpleName()).append(")");
-                }
-
-                sep = ", ";
-            }
-            builder.append(")");
-        }
-        return builder.toString();
-    }
-
-    public abstract Object[] getValues();
-
-    static class SlowPathEvent0 extends SlowPathEvent {
-
-        private static final Object[] EMPTY = new Object[0];
-
-        public SlowPathEvent0(SpecializationNode source, String reason, Frame frame) {
-            super(source, reason, frame);
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return EMPTY;
-        }
-
-    }
-
-    static class SlowPathEvent1 extends SlowPathEvent {
-
-        protected final Object o1;
-
-        public SlowPathEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
-            super(source, reason, frame);
-            this.o1 = o1;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return new Object[]{o1};
-        }
-
-    }
-
-    static class SlowPathEvent2 extends SlowPathEvent {
-
-        protected final Object o1;
-        protected final Object o2;
-
-        public SlowPathEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
-            super(source, reason, frame);
-            this.o1 = o1;
-            this.o2 = o2;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return new Object[]{o1, o2};
-        }
-
-    }
-
-    static class SlowPathEvent3 extends SlowPathEvent {
-
-        protected final Object o1;
-        protected final Object o2;
-        protected final Object o3;
-
-        public SlowPathEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
-            super(source, reason, frame);
-            this.o1 = o1;
-            this.o2 = o2;
-            this.o3 = o3;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return new Object[]{o1, o2, o3};
-        }
-
-    }
-
-    static class SlowPathEvent4 extends SlowPathEvent {
-
-        protected final Object o1;
-        protected final Object o2;
-        protected final Object o3;
-        protected final Object o4;
-
-        public SlowPathEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-            super(source, reason, frame);
-            this.o1 = o1;
-            this.o2 = o2;
-            this.o3 = o3;
-            this.o4 = o4;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return new Object[]{o1, o2, o3, o4};
-        }
-
-    }
-
-    static class SlowPathEvent5 extends SlowPathEvent {
-
-        protected final Object o1;
-        protected final Object o2;
-        protected final Object o3;
-        protected final Object o4;
-        protected final Object o5;
-
-        public SlowPathEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-            super(source, reason, frame);
-            this.o1 = o1;
-            this.o2 = o2;
-            this.o3 = o3;
-            this.o4 = o4;
-            this.o5 = o5;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return new Object[]{o1, o2, o3, o4, o5};
-        }
-
-    }
-
-    static class SlowPathEventN extends SlowPathEvent {
-
-        protected final Object[] args;
-
-        public SlowPathEventN(SpecializationNode source, String reason, Frame frame, Object... args) {
-            super(source, reason, frame);
-            this.args = args;
-        }
-
-        @Override
-        public final Object[] getValues() {
-            return args;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,866 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent0;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent1;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent2;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent3;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent4;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent5;
-import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEventN;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Internal implementation dependent base class for generated specialized nodes.
- */
-@NodeInfo(cost = NodeCost.NONE)
-@SuppressWarnings("unused")
-public abstract class SpecializationNode extends Node {
-
-    @Child protected SpecializationNode next;
-
-    final int index;
-
-    public SpecializationNode() {
-        this(-1);
-    }
-
-    public SpecializationNode(int index) {
-        this.index = index;
-    }
-
-    @Override
-    public final NodeCost getCost() {
-        return NodeCost.NONE;
-    }
-
-    public void reset() {
-        SpecializationNode start = findStart();
-        SpecializationNode end = findEnd();
-        if (start != end) {
-            start.replace(end, "reset specialization");
-        }
-    }
-
-    public static Node updateRoot(Node node) {
-        updateRootImpl(((SpecializedNode) node).getSpecializationNode(), node);
-        return node;
-    }
-
-    private static void updateRootImpl(SpecializationNode start, Node node) {
-        NodeFieldAccessor[] fields = NodeClass.get(start).getFields();
-        for (int i = fields.length - 1; i >= 0; i--) {
-            NodeFieldAccessor f = fields[i];
-            if (f.getName().equals("root")) {
-                f.putObject(start, node);
-                break;
-            }
-        }
-        if (start.next != null) {
-            updateRootImpl(start.next, node);
-        }
-    }
-
-    protected final SpecializationNode polymorphicMerge(SpecializationNode newNode, SpecializationNode merged) {
-        if (merged == newNode && count() <= 2) {
-            return removeSame(new SlowPathEvent0(this, "merged polymorphic to monomorphic", null));
-        }
-        return merged;
-    }
-
-    public final NodeCost getNodeCost() {
-        switch (count()) {
-            case 0:
-            case 1:
-                return NodeCost.UNINITIALIZED;
-            case 2:
-                return NodeCost.MONOMORPHIC;
-            default:
-                return NodeCost.POLYMORPHIC;
-        }
-    }
-
-    protected abstract Node[] getSuppliedChildren();
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame) {
-        if (isIdentical(newNode, frame)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1) {
-        if (isIdentical(newNode, frame, o1)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, o1) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2) {
-        if (isIdentical(newNode, frame, o1, o2)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, o1, o2) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3) {
-        if (isIdentical(newNode, frame, o1, o2, o3)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, o1, o2, o3) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        if (isIdentical(newNode, frame, o1, o2, o3, o4)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, o1, o2, o3, o4) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        if (isIdentical(newNode, frame, o1, o2, o3, o4, o5)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, o1, o2, o3, o4, o5) : newNode;
-    }
-
-    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object... args) {
-        if (isIdentical(newNode, frame, args)) {
-            return this;
-        }
-        return next != null ? next.merge(newNode, frame, args) : newNode;
-    }
-
-    protected boolean isSame(SpecializationNode other) {
-        return getClass() == other.getClass();
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        return isSame(newNode);
-    }
-
-    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object... args) {
-        return isSame(newNode);
-    }
-
-    protected final int countSame(SpecializationNode node) {
-        return findStart().countSameImpl(node);
-    }
-
-    private int countSameImpl(SpecializationNode node) {
-        if (next != null) {
-            return next.countSameImpl(node) + (isSame(node) ? 1 : 0);
-        } else {
-            return 0;
-        }
-    }
-
-    @Override
-    public final boolean equals(Object obj) {
-        if (obj instanceof SpecializationNode) {
-            return ((SpecializationNode) obj).isSame(this);
-        }
-        return super.equals(obj);
-    }
-
-    @Override
-    public final int hashCode() {
-        return index;
-    }
-
-    private int count() {
-        return next != null ? next.count() + 1 : 1;
-    }
-
-    private SpecializationNode findEnd() {
-        SpecializationNode node = this;
-        while (node.next != null) {
-            node = node.next;
-        }
-        return node;
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame) {
-        return removeThisImpl(reason).acceptAndExecute(frame);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1) {
-        return removeThisImpl(reason).acceptAndExecute(frame, o1);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2) {
-        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3) {
-        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4, o5);
-    }
-
-    protected final Object removeThis(final CharSequence reason, Frame frame, Object... args) {
-        return removeThisImpl(reason).acceptAndExecute(frame, args);
-    }
-
-    private SpecializationNode removeThisImpl(final CharSequence reason) {
-        this.replace(this.next, reason);
-        return findEnd().findStart();
-    }
-
-    protected final SpecializationNode removeSame(final CharSequence reason) {
-        SpecializationNode start = SpecializationNode.this.findStart();
-        SpecializationNode current = start;
-        while (current != null) {
-            if (current.isSame(SpecializationNode.this)) {
-                NodeUtil.nonAtomicReplace(current, current.next, reason);
-                if (current == start) {
-                    start = start.next;
-                }
-            }
-            current = current.next;
-        }
-        return SpecializationNode.this.findEnd().findStart();
-    }
-
-    /** Find the topmost of the specialization chain. */
-    private SpecializationNode findStart() {
-        SpecializationNode node = this;
-        Node parent = this.getParent();
-        while (parent instanceof SpecializationNode) {
-            SpecializationNode parentCast = ((SpecializationNode) parent);
-            if (parentCast.next != node) {
-                break;
-            }
-            node = parentCast;
-            parent = node.getParent();
-        }
-        return node;
-    }
-
-    private Node findRoot() {
-        return findStart().getParent();
-    }
-
-    private SpecializedNode findSpecializedNode() {
-        return (SpecializedNode) findEnd().findStart().getParent();
-    }
-
-    private static SpecializationNode removeSameImpl(SpecializationNode toRemove, CharSequence reason) {
-        SpecializationNode start = toRemove.findStart();
-        SpecializationNode current = start;
-        while (current != null) {
-            if (current.isSame(toRemove)) {
-                NodeUtil.nonAtomicReplace(current, current.next, reason);
-                if (current == start) {
-                    start = start.next;
-                }
-            }
-            current = current.next;
-        }
-        return toRemove.findEnd().findStart();
-    }
-
-    public Object acceptAndExecute(Frame frame) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object o1) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object o1, Object o2) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object acceptAndExecute(Frame frame, Object... args) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createFallback() {
-        return null;
-    }
-
-    protected SpecializationNode createPolymorphic() {
-        return null;
-    }
-
-    protected SpecializationNode createNext(Frame frame) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object o1) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object o1, Object o2) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected SpecializationNode createNext(Frame frame, Object... args) {
-        throw new UnsupportedOperationException();
-    }
-
-    protected final Object uninitialized(Frame frame) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent0(this, "insert new specialization", frame));
-        if (newNode == null) {
-            return unsupported(frame);
-        }
-        return newNode.acceptAndExecute(frame);
-    }
-
-    protected final Object uninitialized(Frame frame, Object o1) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent1(this, "insert new specialization", frame, o1));
-        if (newNode == null) {
-            return unsupported(frame, o1);
-        }
-        return newNode.acceptAndExecute(frame, o1);
-    }
-
-    protected final Object uninitialized(Frame frame, Object o1, Object o2) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent2(this, "insert new specialization", frame, o1, o2));
-        if (newNode == null) {
-            return unsupported(frame, o1, o2);
-        }
-        return newNode.acceptAndExecute(frame, o1, o2);
-    }
-
-    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent3(this, "insert new specialization", frame, o1, o2, o3));
-        if (newNode == null) {
-            return unsupported(frame, o1, o2, o3);
-        }
-        return newNode.acceptAndExecute(frame, o1, o2, o3);
-    }
-
-    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent4(this, "insert new specialization", frame, o1, o2, o3, o4));
-        if (newNode == null) {
-            return unsupported(frame, o1, o2, o3, o4);
-        }
-        return newNode.acceptAndExecute(frame, o1, o2, o3, o4);
-    }
-
-    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEvent5(this, "insert new specialization", frame, o1, o2, o3, o4, o5));
-        if (newNode == null) {
-            return unsupported(frame, o1, o2, o3, o4, o5);
-        }
-        return newNode.acceptAndExecute(frame, o1, o2, o3, o4, o5);
-    }
-
-    protected final Object uninitialized(Frame frame, Object... args) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        SpecializationNode newNode = atomic(new InsertionEventN(this, "insert new specialization", frame, args));
-        if (newNode == null) {
-            return unsupported(frame, args);
-        }
-        return newNode.acceptAndExecute(frame, args);
-    }
-
-    protected final Object remove(String reason, Frame frame) {
-        return atomic(new RemoveEvent0(this, reason, frame)).acceptAndExecute(frame);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object o1) {
-        return atomic(new RemoveEvent1(this, reason, frame, o1)).acceptAndExecute(frame, o1);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object o1, Object o2) {
-        return atomic(new RemoveEvent2(this, reason, frame, o1, o2)).acceptAndExecute(frame, o1, o2);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3) {
-        return atomic(new RemoveEvent3(this, reason, frame, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        return atomic(new RemoveEvent4(this, reason, frame, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        return atomic(new RemoveEvent5(this, reason, frame, o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5);
-    }
-
-    protected final Object remove(String reason, Frame frame, Object... args) {
-        return atomic(new RemoveEventN(this, reason, frame, args)).acceptAndExecute(frame, args);
-    }
-
-    protected Object unsupported(Frame frame) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren());
-    }
-
-    protected Object unsupported(Frame frame, Object o1) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1);
-    }
-
-    protected Object unsupported(Frame frame, Object o1, Object o2) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2);
-    }
-
-    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3);
-    }
-
-    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4);
-    }
-
-    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4, o5);
-    }
-
-    protected Object unsupported(Frame frame, Object... args) {
-        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), args);
-    }
-
-    static SpecializationNode insertSorted(SpecializationNode start, final SpecializationNode generated, final CharSequence message, final SpecializationNode merged) {
-        if (merged == generated) {
-            // new node
-            if (start.count() == 2) {
-                SpecializationNode polymorphic = start.createPolymorphic();
-                /*
-                 * For nodes with all parameters evaluated in the execute method we do not need a
-                 * polymorphic node. the generated code returns null in createPolymorphic in this
-                 * case.
-                 */
-                if (polymorphic != null) {
-                    insertAt(start, polymorphic, "insert polymorphic");
-                }
-            }
-            SpecializationNode current = start;
-            while (current != null && current.index < generated.index) {
-                current = current.next;
-            }
-            return insertAt(current, generated, message);
-        } else {
-            // existing node
-            return start;
-        }
-    }
-
-    static <T> SpecializationNode insertAt(SpecializationNode node, SpecializationNode insertBefore, CharSequence reason) {
-        insertBefore.next = node;
-        // always guaranteed to be executed inside of an atomic block
-        return NodeUtil.nonAtomicReplace(node, insertBefore, reason);
-    }
-
-    @Override
-    public final String toString() {
-        Class<?> clazz = getClass();
-        StringBuilder b = new StringBuilder();
-        b.append(clazz.getSimpleName());
-
-        appendFields(b, clazz);
-        if (next != null) {
-            b.append("\n -> ").append(next.toString());
-        }
-        return b.toString();
-    }
-
-    private void appendFields(StringBuilder b, Class<?> clazz) {
-        Field[] fields = clazz.getDeclaredFields();
-        if (fields.length == 0) {
-            return;
-        }
-        b.append("(");
-        String sep = "";
-        for (Field field : fields) {
-            if (Modifier.isStatic(field.getModifiers())) {
-                continue;
-            }
-            b.append(sep);
-            String name = field.getName();
-            if (name.equals("root")) {
-                continue;
-            }
-            b.append(field.getName());
-            b.append(" = ");
-            try {
-                field.setAccessible(true);
-                Object value = field.get(this);
-                if (value instanceof Object[]) {
-                    b.append(Arrays.toString((Object[]) field.get(this)));
-                } else {
-                    b.append(field.get(this));
-                }
-            } catch (IllegalArgumentException e) {
-                b.append(e.toString());
-            } catch (IllegalAccessException e) {
-                b.append(e.toString());
-            }
-            sep = ", ";
-        }
-        b.append(")");
-    }
-
-    protected static void check(Assumption assumption) throws InvalidAssumptionException {
-        if (assumption != null) {
-            assumption.check();
-        }
-    }
-
-    @ExplodeLoop
-    protected static void check(Assumption[] assumptions) throws InvalidAssumptionException {
-        if (assumptions != null) {
-            CompilerAsserts.compilationConstant(assumptions.length);
-            for (Assumption assumption : assumptions) {
-                check(assumption);
-            }
-        }
-    }
-
-    protected static boolean isValid(Assumption assumption) {
-        if (assumption != null) {
-            return assumption.isValid();
-        }
-        return true;
-    }
-
-    protected static boolean isValid(Assumption[] assumptions) {
-        if (assumptions != null) {
-            for (Assumption assumption : assumptions) {
-                if (!isValid(assumption)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private static final class InsertionEvent0 extends SlowPathEvent0 implements Callable<SpecializationNode> {
-
-        public InsertionEvent0(SpecializationNode source, String reason, Frame frame) {
-            super(source, reason, frame);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame));
-            }
-        }
-
-    }
-
-    private static final class InsertionEvent1 extends SlowPathEvent1 implements Callable<SpecializationNode> {
-
-        public InsertionEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
-            super(source, reason, frame, o1);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, o1);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, o1));
-            }
-        }
-
-    }
-
-    private static final class InsertionEvent2 extends SlowPathEvent2 implements Callable<SpecializationNode> {
-
-        public InsertionEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
-            super(source, reason, frame, o1, o2);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, o1, o2);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, o1, o2));
-            }
-        }
-
-    }
-
-    private static final class InsertionEvent3 extends SlowPathEvent3 implements Callable<SpecializationNode> {
-
-        public InsertionEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
-            super(source, reason, frame, o1, o2, o3);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, o1, o2, o3);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3));
-            }
-        }
-
-    }
-
-    private static final class InsertionEvent4 extends SlowPathEvent4 implements Callable<SpecializationNode> {
-
-        public InsertionEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-            super(source, reason, frame, o1, o2, o3, o4);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, o1, o2, o3, o4);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3, o4));
-            }
-        }
-
-    }
-
-    private static final class InsertionEvent5 extends SlowPathEvent5 implements Callable<SpecializationNode> {
-
-        public InsertionEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-            super(source, reason, frame, o1, o2, o3, o4, o5);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, o1, o2, o3, o4, o5);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3, o4, o5));
-            }
-        }
-
-    }
-
-    private static final class InsertionEventN extends SlowPathEventN implements Callable<SpecializationNode> {
-
-        public InsertionEventN(SpecializationNode source, String reason, Frame frame, Object[] args) {
-            super(source, reason, frame, args);
-        }
-
-        public SpecializationNode call() throws Exception {
-            SpecializationNode next = source.createNext(frame, args);
-            if (next == null) {
-                next = source.createFallback();
-            }
-            if (next == null) {
-                return null;
-            }
-            SpecializationNode start = source.findStart();
-            if (start.index == Integer.MAX_VALUE) {
-                return insertAt(start, next, this);
-            } else {
-                return insertSorted(start, next, this, start.merge(next, frame, args));
-            }
-        }
-    }
-
-    private static final class RemoveEvent0 extends SlowPathEvent0 implements Callable<SpecializationNode> {
-
-        public RemoveEvent0(SpecializationNode source, String reason, Frame frame) {
-            super(source, reason, frame);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEvent1 extends SlowPathEvent1 implements Callable<SpecializationNode> {
-
-        public RemoveEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
-            super(source, reason, frame, o1);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEvent2 extends SlowPathEvent2 implements Callable<SpecializationNode> {
-
-        public RemoveEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
-            super(source, reason, frame, o1, o2);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEvent3 extends SlowPathEvent3 implements Callable<SpecializationNode> {
-
-        public RemoveEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
-            super(source, reason, frame, o1, o2, o3);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEvent4 extends SlowPathEvent4 implements Callable<SpecializationNode> {
-
-        public RemoveEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
-            super(source, reason, frame, o1, o2, o3, o4);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEvent5 extends SlowPathEvent5 implements Callable<SpecializationNode> {
-
-        public RemoveEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
-            super(source, reason, frame, o1, o2, o3, o4, o5);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-
-    }
-
-    private static final class RemoveEventN extends SlowPathEventN implements Callable<SpecializationNode> {
-
-        public RemoveEventN(SpecializationNode source, String reason, Frame frame, Object[] args) {
-            super(source, reason, frame, args);
-        }
-
-        public SpecializationNode call() throws Exception {
-            return source.removeSame(this);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializedNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.dsl.internal;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Implemented by DSL generated operation classes. This is internal implementation dependent API.
- */
-public interface SpecializedNode extends NodeInterface {
-
-    /** Returns the root {@link SpecializationNode} of the DSL operation. */
-    SpecializationNode getSpecializationNode();
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.oracle.truffle.api.interop.impl.SymbolInvokerImpl
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Execute.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class Execute extends KnownMessage {
-    public static final int HASH1 = 423430;
-    public static final int HASH2 = 423429;
-
-    private final int arity;
-    private final boolean invoke;
-
-    public static Execute create(boolean invoke, int arity) {
-        return new Execute(invoke, arity);
-    }
-
-    private Execute(boolean invoke, int arity) {
-        this.invoke = invoke;
-        this.arity = arity;
-    }
-
-    public int getArity() {
-        return arity;
-    }
-
-    @Override
-    public boolean equals(Object message) {
-        if (!(message instanceof Execute)) {
-            return false;
-        }
-        Execute m1 = this;
-        Execute m2 = (Execute) message;
-        return m1.invoke == m2.invoke;
-    }
-
-    @Override
-    public int hashCode() {
-        return invoke ? HASH1 : HASH2;
-    }
-
-    @Override
-    public String toString() {
-        return invoke ? "msgInvoke" : "msgExecute";
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-import com.oracle.truffle.api.CallTarget;
-import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.interop.impl.ReadOnlyArrayList;
-import com.oracle.truffle.api.nodes.Node;
-import java.util.List;
-
-/**
- * Encapsulates types of access to {@link TruffleObject}. If you want to expose your own objects to
- * foreign language implementations, you need to implement {@link TruffleObject} and its
- * {@link TruffleObject#getForeignAccess()} method. To create instance of <code>ForeignAccess</code>
- * , use one of the factory methods available in this class.
- */
-public final class ForeignAccess {
-    private final Factory factory;
-
-    private ForeignAccess(Factory faf) {
-        this.factory = faf;
-    }
-
-    /**
-     * Creates new instance of {@link ForeignAccess} that delegates to provided factory.
-     *
-     * @param baseClass the super class of all {@link TruffleObject}s handled by this factory (if
-     *            <code>null</code> than the second interface also needs to implement
-     *            {@link Factory})
-     * @param factory the factory that handles access requests to {@link Message}s known as of
-     *            version 1.0
-     * @return new instance wrapping <code>factory</code>
-     */
-    public static ForeignAccess create(final Class<? extends TruffleObject> baseClass, final Factory10 factory) {
-        if (baseClass == null) {
-            Factory f = (Factory) factory;
-            assert f != null;
-        }
-        class DelegatingFactory implements Factory {
-            @Override
-            public boolean canHandle(TruffleObject obj) {
-                if (baseClass == null) {
-                    return ((Factory) factory).canHandle(obj);
-                }
-                return baseClass.isInstance(obj);
-            }
-
-            @Override
-            public CallTarget accessMessage(Message msg) {
-                if (msg instanceof KnownMessage) {
-                    switch (msg.hashCode()) {
-                        case Execute.HASH1:
-                            return factory.accessInvoke(((Execute) msg).getArity());
-                        case Execute.HASH2:
-                            return factory.accessExecute(((Execute) msg).getArity());
-                        case GetSize.HASH:
-                            return factory.accessGetSize();
-                        case HasSize.HASH:
-                            return factory.accessHasSize();
-                        case IsBoxed.HASH:
-                            return factory.accessIsBoxed();
-                        case IsExecutable.HASH:
-                            return factory.accessIsExecutable();
-                        case IsNull.HASH:
-                            return factory.accessIsNull();
-                        case Read.HASH:
-                            return factory.accessRead();
-                        case Unbox.HASH:
-                            return factory.accessUnbox();
-                        case Write.HASH:
-                            return factory.accessWrite();
-                    }
-                }
-                return factory.accessMessage(msg);
-            }
-        }
-        return new ForeignAccess(new DelegatingFactory());
-    }
-
-    /**
-     * Creates new instance of {@link ForeignAccess} that delegates to provided factory.
-     *
-     * @param factory the factory that handles various access requests {@link Message}s.
-     * @return new instance wrapping <code>factory</code>
-     */
-    public static ForeignAccess create(Factory factory) {
-        return new ForeignAccess(factory);
-    }
-
-    /**
-     * Executes {@link Message#createNode() foreign node}.
-     * 
-     * @param foreignNode the createNode created by {@link Message#createNode()}
-     * @param frame the call frame
-     * @param receiver foreign object to receive the message passed to {@link Message#createNode()}
-     *            method
-     * @param arguments parameters for the receiver
-     * @return return value, if any
-     * @throws ClassCastException if the createNode has not been created by
-     *             {@link Message#createNode()} method.
-     */
-    public static Object execute(Node foreignNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) {
-        ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) foreignNode;
-        return fn.executeForeign(frame, receiver, arguments);
-    }
-
-    /**
-     * Read only access to foreign call arguments inside of a frame.
-     *
-     * @param frame the frame that was called via
-     *            {@link #execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) }
-     * @return read-only list of parameters passed to the frame
-     */
-    public static List<Object> getArguments(Frame frame) {
-        final Object[] arr = frame.getArguments();
-        return ReadOnlyArrayList.asList(arr, 1, arr.length);
-    }
-
-    /**
-     * The foreign receiver in the frame.
-     *
-     * @param frame the frame that was called via
-     *            {@link #execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) }
-     * @return the receiver used when invoking the frame
-     */
-    public static TruffleObject getReceiver(Frame frame) {
-        return (TruffleObject) frame.getArguments()[ForeignAccessArguments.RECEIVER_INDEX];
-    }
-
-    CallTarget access(Message message) {
-        return factory.accessMessage(message);
-    }
-
-    boolean canHandle(TruffleObject receiver) {
-        return factory.canHandle(receiver);
-    }
-
-    /**
-     * Interface of a factory that produces AST snippets that can access a foreign
-     * {@code TruffleObject}. A Truffle language implementation accesses a {@code TruffleObject} via
-     * a {@code Message}. The {@code TruffleObject} instance provides a {@link ForeignAccess}
-     * instance (built via {@link #create(com.oracle.truffle.api.interop.ForeignAccess.Factory)})
-     * that provides an AST snippet for a given {@link Message}. Rather than using this generic
-     * {@code Factory}, consider implementing {@link Factory10} interface that captures the set of
-     * messages each language should implement as of Truffle version 1.0.
-     */
-    public interface Factory {
-
-        /**
-         * * Checks whether provided {@link TruffleObject} can be accessed using AST snippets
-         * produced by this {@link Factory}.
-         *
-         * @param obj the object to check
-         * @return true, if the object can be processed
-         */
-        boolean canHandle(TruffleObject obj);
-
-        /**
-         * Provides an AST snippet to access a {@code TruffleObject}.
-         *
-         * @param tree the {@code Message} that represents the access to a {@code TruffleObject}.
-         * @return the AST snippet for accessing the {@code TruffleObject}, wrapped as a
-         *         {@code CallTarget}.
-         */
-        CallTarget accessMessage(Message tree);
-    }
-
-    /**
-     * Specialized {@link Factory factory} that handles {@link Message messages} known as of release
-     * 1.0 of Truffle API.
-     *
-     */
-    public interface Factory10 {
-        /**
-         * Handles {@link Message#IS_NULL} message.
-         *
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessIsNull();
-
-        /**
-         * Handles {@link Message#IS_EXECUTABLE} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessIsExecutable();
-
-        /**
-         * Handles {@link Message#IS_BOXED} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessIsBoxed();
-
-        /**
-         * Handles {@link Message#HAS_SIZE} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessHasSize();
-
-        /**
-         * Handles {@link Message#GET_SIZE} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessGetSize();
-
-        /**
-         * Handles {@link Message#UNBOX} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessUnbox();
-
-        /**
-         * Handles {@link Message#READ} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessRead();
-
-        /**
-         * Handles {@link Message#WRITE} message.
-         * 
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessWrite();
-
-        /**
-         * Handles {@link Message#createExecute(int)} messages.
-         * 
-         * @param argumentsLength number of parameters the messages has been created for
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessExecute(int argumentsLength);
-
-        /**
-         * Handles {@link Message#createInvoke(int)} messages.
-         * 
-         * @param argumentsLength number of parameters the messages has been created for
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessInvoke(int argumentsLength);
-
-        /**
-         * Handles request for access to a message not known in version 1.0.
-         *
-         * @param unknown the message
-         * @return call target to handle the message or <code>null</code> if this message is not
-         *         supported
-         */
-        CallTarget accessMessage(Message unknown);
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class ForeignAccessArguments {
-    static final Object[] EMPTY_ARGUMENTS_ARRAY = new Object[0];
-    static final int RECEIVER_INDEX = 0;
-    static final int RUNTIME_ARGUMENT_COUNT = 1;
-
-    static Object[] create(Object receiver, Object... arguments) {
-        if (arguments.length == 0) {
-            return new Object[]{receiver};
-        }
-        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + arguments.length];
-        objectArguments[RECEIVER_INDEX] = receiver;
-        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
-        return objectArguments;
-    }
-
-    private static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
-        for (int i = 0; i < length; i++) {
-            dest[destPos + i] = src[srcPos + i];
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignObjectAccessHeadNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.truffle.api.interop;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.Node;
-
-final class ForeignObjectAccessHeadNode extends Node {
-
-    @Child private ObjectAccessNode first;
-    private final Message accessTree;
-
-    protected ForeignObjectAccessHeadNode(Message tree) {
-        this.accessTree = tree;
-        this.first = new UnresolvedObjectAccessNode();
-        adoptChildren();
-    }
-
-    protected Message getAccessTree() {
-        return accessTree;
-    }
-
-    protected ObjectAccessNode getFirst() {
-        return first;
-    }
-
-    public Object executeForeign(VirtualFrame frame, TruffleObject receiver, Object... arguments) {
-        return first.executeWith(frame, receiver, arguments);
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GetSize.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class GetSize extends UnaryMessage {
-    public static final int HASH = 423432;
-
-    static Message INSTANCE = new GetSize();
-
-    @Override
-    public String toString() {
-        return "msgGetSize";
-    }
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/HasSize.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class HasSize extends UnaryMessage {
-    public static final int HASH = 423433;
-    static Message INSTANCE = new HasSize();
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgHasSize";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsBoxed.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class IsBoxed extends UnaryMessage {
-    public static final int HASH = 423434;
-    static Message INSTANCE = new IsBoxed();
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgIsBoxed";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsExecutable.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class IsExecutable extends UnaryMessage {
-    public static final int HASH = 423435;
-    static Message INSTANCE = new IsExecutable();
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgIsExecutable";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsNull.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class IsNull extends UnaryMessage {
-    public static final int HASH = 423436;
-    static Message INSTANCE = new IsNull();
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgIsNull";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/KnownMessage.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-/**
- * Marker class.
- */
-abstract class KnownMessage extends Message {
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.interop.ForeignAccess.Factory;
-
-/**
- * Inter-operability is based on sending messages. Standard messages are defined as as constants
- * like {@link #IS_NULL} or factory methods in this class, but one can always define their own,
- * specialized messages.
- */
-public abstract class Message {
-    /**
-     * Message to read a field.
-     */
-    public static final Message READ = Read.INSTANCE;
-
-    /**
-     * Converts {@link TruffleObject truffle value} to Java primitive type. Primitive types are
-     * subclasses of {@link Number}, {@link Boolean}, {@link Character} and {@link String}. Related
-     * to {@link #IS_BOXED} message.
-     */
-    public static final Message UNBOX = Unbox.INSTANCE;
-
-    /**
-     * Message to write a field.
-     */
-    public static Message WRITE = Write.INSTANCE;
-
-    /**
-     * Creates an execute message. All messages created by this method are
-     * {@link Object#equals(java.lang.Object) equal} to each other regardless of the value of
-     * <code>argumentsLength</code>.
-     *
-     * @param argumentsLength number of parameters to pass to the target
-     * @return execute message
-     */
-    public static Message createExecute(int argumentsLength) {
-        return Execute.create(false, argumentsLength);
-    }
-
-    /**
-     * Message to check for executability.
-     * <p>
-     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
-     * this message should yield value of {@link Boolean}.
-     */
-    public static final Message IS_EXECUTABLE = IsExecutable.INSTANCE;
-
-    /**
-     * Creates an execute message. All messages created by this method are
-     * {@link Object#equals(java.lang.Object) equal} to each other regardless of the value of
-     * <code>argumentsLength</code>. The expected behavior of this message is to perform
-     * {@link #READ} first and on the result invoke {@link #createExecute(int)}.
-     *
-     * @param argumentsLength number of parameters to pass to the target
-     * @return read & execute message
-     */
-    public static Message createInvoke(int argumentsLength) {
-        return Execute.create(true, argumentsLength);
-    }
-
-    /**
-     * Check for <code>null</code> message. The Truffle languages are suggested to have their own
-     * object representing <code>null</code> like values in their languages. For purposes of
-     * inter-operability it is essential to canonicalize such values from time to time - sending
-     * this message is a way to recognize such <code>null</code> representing values.
-     * <p>
-     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
-     * this message should yield value of {@link Boolean}.
-     */
-    public static final Message IS_NULL = IsNull.INSTANCE;
-
-    /**
-     * Message to check for having a size.
-     * <p>
-     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
-     * this message should yield value of {@link Boolean}.
-     */
-    public static final Message HAS_SIZE = HasSize.INSTANCE;
-
-    /**
-     * Getter of the size. If {@link #HAS_SIZE supported}, this message allows to obtain a size (of
-     * an array).
-     * <p>
-     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
-     * this message should yield value of {@link Integer}.
-     */
-    public static final Message GET_SIZE = GetSize.INSTANCE;
-
-    /**
-     * Check for value being boxed. Can you value be converted to one of the basic Java types? Many
-     * languages have a special representation for types like number, string, etc. To ensure
-     * inter-operability, these types should support unboxing - if they do, they should handle this
-     * message.
-     * <p>
-     * Calling {@link Factory#accessMessage(com.oracle.truffle.api.interop.Message) the target}
-     * created for this message should yield value of {@link Boolean}.
-     */
-    public static final Message IS_BOXED = IsBoxed.INSTANCE;
-
-    /**
-     * Compares types of two messages. Messages are encouraged to implement this method. All
-     * standard ones ({@link #IS_NULL}, {@link #READ}, etc.) do so. Messages obtained via the same
-     * {@link #createExecute(int) method} are equal, messages obtained by different methods or
-     * fields are not.
-     *
-     * @param message the object to compare to
-     * @return true, if the structure of the message is that same as of <code>this</code> one.
-     */
-    @Override
-    public abstract boolean equals(Object message);
-
-    /**
-     * When re-implementing {@link #equals(java.lang.Object)}, it is generally recommended to also
-     * implement <code>hashCode()</code>.
-     * 
-     * @return hash code
-     */
-    @Override
-    public abstract int hashCode();
-
-    /**
-     * Creates an AST node for this message. The node can be inserted into AST of your language and
-     * will handle communication with the foreign language.
-     *
-     * @return node to be inserted into your AST and passed back to
-     *         {@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object[])}
-     *         method.
-     */
-    public final Node createNode() {
-        return new ForeignObjectAccessHeadNode(this);
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ObjectAccessNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-abstract class ObjectAccessNode extends Node {
-
-    public abstract Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments);
-
-}
-
-class UnresolvedObjectAccessNode extends ObjectAccessNode {
-
-    private static final int CACHE_SIZE = 8;
-    private int cacheLength = 1;
-
-    @Override
-    public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        ForeignObjectAccessHeadNode nthParent = (ForeignObjectAccessHeadNode) NodeUtil.getNthParent(this, cacheLength);
-        ObjectAccessNode first = nthParent.getFirst();
-        if (cacheLength < CACHE_SIZE) {
-            cacheLength++;
-            CachedObjectAccessNode createCachedAccess = createCachedAccess(receiver, nthParent.getAccessTree(), first);
-            return first.replace(createCachedAccess).executeWith(frame, receiver, arguments);
-        } else {
-            return first.replace(createGenericAccess(nthParent.getAccessTree())).executeWith(frame, receiver, arguments);
-        }
-    }
-
-    private static CachedObjectAccessNode createCachedAccess(TruffleObject receiver, Message accessTree, ObjectAccessNode next) {
-        ForeignAccess fa = receiver.getForeignAccess();
-        final CallTarget ct = fa.access(accessTree);
-        if (ct == null) {
-            throw new IllegalArgumentException("Message " + accessTree + " not recognized by " + fa);
-        }
-        return new CachedObjectAccessNode(Truffle.getRuntime().createDirectCallNode(ct), next, fa);
-    }
-
-    private static GenericObjectAccessNode createGenericAccess(Message access) {
-        return new GenericObjectAccessNode(access);
-    }
-}
-
-class GenericObjectAccessNode extends ObjectAccessNode {
-
-    private final Message access;
-    @Child private IndirectCallNode indirectCallNode;
-
-    public GenericObjectAccessNode(Message access) {
-        this.access = access;
-        indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
-    }
-
-    public GenericObjectAccessNode(GenericObjectAccessNode prev) {
-        this(prev.access);
-    }
-
-    @Override
-    public Object executeWith(VirtualFrame frame, TruffleObject truffleObject, Object[] arguments) {
-        final ForeignAccess fa = truffleObject.getForeignAccess();
-        final CallTarget ct = fa.access(access);
-        if (ct == null) {
-            throw new IllegalStateException("Message " + access + " not recognized by " + fa);
-        }
-        return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments));
-    }
-}
-
-class CachedObjectAccessNode extends ObjectAccessNode {
-    @Child private DirectCallNode callTarget;
-    @Child private ObjectAccessNode next;
-
-    private final ForeignAccess languageCheck;
-
-    protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) {
-        this.callTarget = callTarget;
-        this.next = next;
-        this.languageCheck = languageCheck;
-        this.callTarget.forceInlining();
-    }
-
-    protected CachedObjectAccessNode(CachedObjectAccessNode prev) {
-        this(prev.callTarget, prev.next, prev.languageCheck);
-    }
-
-    @Override
-    public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
-        return doAccess(frame, receiver, arguments);
-    }
-
-    private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
-        if (languageCheck.canHandle(receiver)) {
-            return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments));
-        } else {
-            return doNext(frame, receiver, arguments);
-        }
-    }
-
-    private Object doNext(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
-        return next.executeWith(frame, receiver, arguments);
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Read.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class Read extends KnownMessage {
-    public static final int HASH = 423438;
-    static Message INSTANCE = new Read();
-
-    private Read() {
-    }
-
-    @Override
-    public boolean equals(Object message) {
-        return message instanceof Read;
-    }
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgRead";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/TruffleObject.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-/**
- * Interface for any entity of a Truffle guest language implementations that can be shared across
- * other language implementations.
- */
-public interface TruffleObject {
-    /**
-     * Provides the {@code ForeignAccessFactory} instance for this {@code TruffleObject} instance.
-     *
-     * @return the {@code ForeignAccessFactory} instance for this {@code TruffleObject} instance.
-     */
-    ForeignAccess getForeignAccess();
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/UnaryMessage.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-abstract class UnaryMessage extends KnownMessage {
-    protected UnaryMessage() {
-    }
-
-    @Override
-    public boolean equals(Object message) {
-        if (message == null) {
-            return false;
-        }
-        return this.getClass() == message.getClass();
-    }
-
-    @Override
-    public abstract int hashCode();
-
-    @Override
-    public abstract String toString();
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Unbox.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class Unbox extends UnaryMessage {
-    public static final int HASH = 423437;
-    static Message INSTANCE = new Unbox();
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgUnbox";
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Write.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop;
-
-final class Write extends KnownMessage {
-    public static final int HASH = 423431;
-
-    static Message INSTANCE = new Write();
-
-    @Override
-    public boolean equals(Object message) {
-        return message instanceof Write;
-    }
-
-    @Override
-    public int hashCode() {
-        return HASH;
-    }
-
-    @Override
-    public String toString() {
-        return "msgWrite";
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/ReadOnlyArrayList.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop.impl;
-
-import java.lang.reflect.Array;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-public final class ReadOnlyArrayList<T> implements List<T> {
-    private final T[] arr;
-    private final int first;
-    private final int last;
-
-    private ReadOnlyArrayList(T[] arr, int first, int last) {
-        this.arr = arr;
-        this.first = first;
-        this.last = last;
-    }
-
-    public static <T> List<T> asList(T[] arr, int first, int last) {
-        return new ReadOnlyArrayList<>(arr, first, last);
-    }
-
-    @Override
-    public int size() {
-        return last - first;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return first == last;
-    }
-
-    @Override
-    public boolean contains(Object o) {
-        for (int i = first; i < last; i++) {
-            if (o == arr[i] || (o != null && o.equals(arr[i]))) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public Iterator<T> iterator() {
-        return new LI(first);
-    }
-
-    @Override
-    public Object[] toArray() {
-        return toArray(new Object[size()]);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <A> A[] toArray(A[] b) {
-        A[] a;
-        if (b.length < size()) {
-            a = (A[]) Array.newInstance(b.getClass().getComponentType(), size());
-        } else {
-            a = b;
-        }
-        for (int i = 0, at = first; at < last; i++, at++) {
-            a[i] = (A) arr[at];
-        }
-        return a;
-    }
-
-    @Override
-    public boolean add(Object e) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean remove(Object o) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean containsAll(Collection<?> c) {
-        for (Object obj : c) {
-            if (!contains(obj)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public boolean addAll(Collection<? extends T> c) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean addAll(int index, Collection<? extends T> c) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean removeAll(Collection<?> c) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean retainAll(Collection<?> c) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void clear() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public T get(int index) {
-        int at = first + index;
-        T ret = arr[at];
-        if (at >= last) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-        return ret;
-    }
-
-    @Override
-    public T set(int index, Object element) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void add(int index, Object element) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public T remove(int index) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int indexOf(Object o) {
-        for (int i = first; i < last; i++) {
-            if (arr[i] == null) {
-                if (o == null) {
-                    return i - first;
-                }
-            } else {
-                if (arr[i].equals(o)) {
-                    return i - first;
-                }
-            }
-        }
-        return -1;
-    }
-
-    @Override
-    public int lastIndexOf(Object o) {
-        for (int i = last - 1; i >= first; i--) {
-            if (arr[i] == null) {
-                if (o == null) {
-                    return i - first;
-                }
-            } else {
-                if (arr[i].equals(o)) {
-                    return i - first;
-                }
-            }
-        }
-        return -1;
-    }
-
-    @Override
-    public ListIterator<T> listIterator() {
-        return new LI(first);
-    }
-
-    @Override
-    public ListIterator<T> listIterator(int index) {
-        return new LI(first + index);
-    }
-
-    @Override
-    public List<T> subList(int fromIndex, int toIndex) {
-        return new ReadOnlyArrayList<>(arr, first + fromIndex, first + toIndex);
-    }
-
-    private final class LI implements ListIterator<T>, Iterator<T> {
-        private int index;
-
-        public LI(int index) {
-            this.index = index;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return index < last;
-        }
-
-        @Override
-        public T next() {
-            if (index >= last) {
-                throw new NoSuchElementException();
-            }
-            return arr[index++];
-        }
-
-        @Override
-        public boolean hasPrevious() {
-            return index > first;
-        }
-
-        @Override
-        public T previous() {
-            if (first == index) {
-                throw new NoSuchElementException();
-            }
-            return arr[--index];
-        }
-
-        @Override
-        public int nextIndex() {
-            return index - first;
-        }
-
-        @Override
-        public int previousIndex() {
-            return index - 1 - first;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void set(Object e) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void add(Object e) {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.interop.impl;
-
-import java.io.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.*;
-
-public final class SymbolInvokerImpl extends SymbolInvoker {
-    static final FrameDescriptor UNUSED_FRAMEDESCRIPTOR = new FrameDescriptor();
-
-    @Override
-    protected Object invoke(Object symbol, Object... arr) throws IOException {
-        if (symbol instanceof String) {
-            return symbol;
-        }
-        if (symbol instanceof Number) {
-            return symbol;
-        }
-        if (symbol instanceof Boolean) {
-            return symbol;
-        }
-        Node executeMain = Message.createExecute(arr.length).createNode();
-        CallTarget callTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(executeMain, (TruffleObject) symbol, arr));
-        VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(arr, UNUSED_FRAMEDESCRIPTOR);
-        Object ret = callTarget.call(frame);
-        if (ret instanceof TruffleObject) {
-            TruffleObject tret = (TruffleObject) ret;
-            Object isBoxedResult;
-            try {
-                Node isBoxed = Message.IS_BOXED.createNode();
-                CallTarget isBoxedTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isBoxed, tret));
-                isBoxedResult = isBoxedTarget.call(frame);
-            } catch (IllegalArgumentException ex) {
-                isBoxedResult = false;
-            }
-            if (Boolean.TRUE.equals(isBoxedResult)) {
-                Node unbox = Message.UNBOX.createNode();
-                CallTarget unboxTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(unbox, tret));
-                Object unboxResult = unboxTarget.call(frame);
-                return unboxResult;
-            } else {
-                try {
-                    Node isNull = Message.IS_NULL.createNode();
-                    CallTarget isNullTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isNull, tret));
-                    Object isNullResult = isNullTarget.call(frame);
-                    if (Boolean.TRUE.equals(isNullResult)) {
-                        return null;
-                    }
-                } catch (IllegalArgumentException ex) {
-                    // fallthrough
-                }
-            }
-        }
-        return ret;
-    }
-
-    private static class TemporaryRoot extends RootNode {
-        @Child private Node foreignAccess;
-        private final TruffleObject function;
-        private final Object[] args;
-
-        public TemporaryRoot(Node foreignAccess, TruffleObject function, Object... args) {
-            this.foreignAccess = foreignAccess;
-            this.function = function;
-            this.args = args;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return ForeignAccess.execute(foreignAccess, frame, function, args);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/package-info.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * This package provides inter-operability between different
- * {@link com.oracle.truffle.api.TruffleLanguage Truffle languages}.
- * <p>
- * Languages can exchange primitive Java type wrapper objects (e.g., {@link java.lang.Integer},
- * {@link java.lang.Double}, {@link java.lang.String}, etc) as well as any type
- * implementing {@link com.oracle.truffle.api.interop.TruffleObject}. Foreign objects are
- * precisely those implementing {@link com.oracle.truffle.api.interop.TruffleObject}.
- * <p>
- * To use a {@link com.oracle.truffle.api.interop.TruffleObject} from a different language,
- * you need to ask the language to build appropriate AST for a given
- * {@link com.oracle.truffle.api.interop.Message} with
- * {@link com.oracle.truffle.api.interop.Message#createNode}. The message can then
- * be executed with {@link com.oracle.truffle.api.interop.ForeignAccess#execute}.
- */
-package com.oracle.truffle.api.interop;
-
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BaseLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface BaseLocation {
-    /**
-     * Get object value as object at this location in store.
-     *
-     * @param shape the current shape of the object, which must contain this location
-     */
-    Object get(DynamicObject store, Shape shape);
-
-    /**
-     * Get object value as object at this location in store. For internal use only and subject to
-     * change, use {@link #get(DynamicObject, Shape)} instead.
-     *
-     * @param condition the result of a shape check or {@code false}
-     * @see #get(DynamicObject, Shape)
-     */
-    Object get(DynamicObject store, boolean condition);
-
-    /**
-     * Set object value at this location in store.
-     *
-     * @throws IncompatibleLocationException for storage type invalidations
-     * @throws FinalLocationException for effectively final fields
-     */
-    void set(DynamicObject store, Object value) throws IncompatibleLocationException, FinalLocationException;
-
-    /**
-     * Set object value at this location in store.
-     *
-     * @param shape the current shape of the storage object
-     * @throws IncompatibleLocationException for storage type invalidations
-     * @throws FinalLocationException for effectively final fields
-     */
-    void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException;
-
-    /**
-     * Set object value at this location in store and update shape.
-     *
-     * @param oldShape the shape before the transition
-     * @param newShape new shape after the transition
-     * @throws IncompatibleLocationException if value is of non-assignable type
-     */
-    void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException;
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BooleanLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface BooleanLocation extends TypedLocation {
-    /**
-     * @see #get(DynamicObject, Shape)
-     */
-    boolean getBoolean(DynamicObject store, Shape shape);
-
-    /**
-     * @see #get(DynamicObject, boolean)
-     */
-    boolean getBoolean(DynamicObject store, boolean condition);
-
-    /**
-     * @see #set(DynamicObject, Object)
-     */
-    void setBoolean(DynamicObject store, boolean value) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape)
-     */
-    void setBoolean(DynamicObject store, boolean value, Shape shape) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape, Shape)
-     */
-    void setBoolean(DynamicObject store, boolean value, Shape oldShape, Shape newShape);
-
-    Class<Boolean> getType();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-public final class DebugCounter {
-    private static final ArrayList<DebugCounter> allCounters = new ArrayList<>();
-
-    private final String name;
-    private final AtomicLong value;
-
-    private DebugCounter(String name) {
-        this.name = name;
-        this.value = new AtomicLong();
-        allCounters.add(this);
-    }
-
-    public static DebugCounter create(String name) {
-        return new DebugCounter(name);
-    }
-
-    public long get() {
-        return value.get();
-    }
-
-    public void inc() {
-        value.incrementAndGet();
-    }
-
-    @Override
-    public String toString() {
-        return name + ": " + value;
-    }
-
-    public static void dumpCounters() {
-        dumpCounters(System.out);
-    }
-
-    public static void dumpCounters(PrintStream out) {
-        for (DebugCounter counter : allCounters) {
-            out.println(counter);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DoubleLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface DoubleLocation extends TypedLocation {
-    /**
-     * @see #get(DynamicObject, Shape)
-     */
-    double getDouble(DynamicObject store, Shape shape);
-
-    /**
-     * @see #get(DynamicObject, boolean)
-     */
-    double getDouble(DynamicObject store, boolean condition);
-
-    /**
-     * @see #set(DynamicObject, Object)
-     */
-    void setDouble(DynamicObject store, double value) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape)
-     */
-    void setDouble(DynamicObject store, double value, Shape shape) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape, Shape)
-     */
-    void setDouble(DynamicObject store, double value, Shape oldShape, Shape newShape);
-
-    Class<Double> getType();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.interop.*;
-
-public abstract class DynamicObject implements TypedObject, TruffleObject {
-    /**
-     * Get the object's current shape.
-     */
-    public abstract Shape getShape();
-
-    /**
-     * Get property value.
-     *
-     * @param key property identifier
-     * @param defaultValue return value if property is not found
-     * @return property value or defaultValue if object has no such property
-     */
-    public abstract Object get(Object key, Object defaultValue);
-
-    /**
-     * Set value of existing property.
-     *
-     * @param key property identifier
-     * @param value value to be set
-     * @return {@code true} if successful or {@code false} if property not found
-     */
-    public abstract boolean set(Object key, Object value);
-
-    /**
-     * Returns {@code true} if this object contains a property with the given key.
-     */
-    public final boolean containsKey(Object key) {
-        return getShape().getProperty(key) != null;
-    }
-
-    /**
-     * Define new property or redefine existing property.
-     *
-     * @param key property identifier
-     * @param value value to be set
-     */
-    public final void define(Object key, Object value) {
-        define(key, value, 0);
-    }
-
-    /**
-     * Define new property or redefine existing property.
-     *
-     * @param key property identifier
-     * @param value value to be set
-     * @param flags flags to be set
-     */
-    public abstract void define(Object key, Object value, int flags);
-
-    /**
-     * Define new property with a static location or change existing property.
-     *
-     * @param key property identifier
-     * @param value value to be set
-     * @param flags flags to be set
-     * @param locationFactory factory function that creates a location for a given shape and value
-     */
-    public abstract void define(Object key, Object value, int flags, LocationFactory locationFactory);
-
-    /**
-     * Change property flags.
-     *
-     * @param key property identifier
-     * @param newFlags flags to be set
-     * @return {@code true} if successful or {@code false} if property not found
-     */
-    public abstract boolean changeFlags(Object key, int newFlags);
-
-    /**
-     * Change property flags.
-     *
-     * @param key property identifier
-     * @param flagsUpdateFunction function updating old flags to new flags
-     * @return {@code true} if successful or {@code false} if property not found
-     */
-    public abstract boolean changeFlags(Object key, FlagsFunction flagsUpdateFunction);
-
-    /**
-     * Delete property.
-     *
-     * @param key property identifier
-     * @return {@code true} if successful or {@code false} if property not found
-     */
-    public abstract boolean delete(Object key);
-
-    /**
-     * Returns the number of properties in this object.
-     */
-    public abstract int size();
-
-    /**
-     * Returns {@code true} if this object contains no properties.
-     */
-    public abstract boolean isEmpty();
-
-    /**
-     * Set object shape and grow storage if necessary.
-     *
-     * @param oldShape the object's current shape (must equal {@link #getShape()})
-     * @param newShape the new shape to be set
-     */
-    public abstract void setShapeAndGrow(Shape oldShape, Shape newShape);
-
-    /**
-     * Set object shape and resize storage if necessary.
-     *
-     * @param oldShape the object's current shape (must equal {@link #getShape()})
-     * @param newShape the new shape to be set
-     */
-    public abstract void setShapeAndResize(Shape oldShape, Shape newShape);
-
-    /**
-     * Ensure object shape is up-to-date.
-     *
-     * @return {@code true} if shape has changed
-     */
-    public abstract boolean updateShape();
-
-    public interface FlagsFunction {
-        int apply(int t);
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObjectFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface DynamicObjectFactory {
-    DynamicObject newInstance(Object... initialValues);
-
-    Shape getShape();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import com.oracle.truffle.api.nodes.*;
-
-public final class FinalLocationException extends SlowPathException {
-    private static final long serialVersionUID = -30188494510914293L;
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public final class HiddenKey {
-    private final String name;
-
-    public HiddenKey(String name) {
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return name;
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import com.oracle.truffle.api.nodes.*;
-
-public final class IncompatibleLocationException extends SlowPathException {
-    private static final long serialVersionUID = -7734865392357341789L;
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IntLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface IntLocation extends TypedLocation {
-    /**
-     * @see #get(DynamicObject, Shape)
-     */
-    int getInt(DynamicObject store, Shape shape);
-
-    /**
-     * @see #get(DynamicObject, boolean)
-     */
-    int getInt(DynamicObject store, boolean condition);
-
-    /**
-     * @see #set(DynamicObject, Object)
-     */
-    void setInt(DynamicObject store, int value) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape)
-     */
-    void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape, Shape)
-     */
-    void setInt(DynamicObject store, int value, Shape oldShape, Shape newShape);
-
-    Class<Integer> getType();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
-import com.oracle.truffle.api.object.Shape.Allocator;
-
-public abstract class Layout {
-    public static final EnumSet<ImplicitCast> NONE = EnumSet.noneOf(ImplicitCast.class);
-    public static final EnumSet<ImplicitCast> INT_TO_DOUBLE = EnumSet.of(ImplicitCast.IntToDouble);
-    public static final EnumSet<ImplicitCast> INT_TO_LONG = EnumSet.of(ImplicitCast.IntToLong);
-
-    public static final String OPTION_PREFIX = "truffle.object.";
-
-    private static final LayoutFactory LAYOUT_FACTORY = loadLayoutFactory();
-
-    public enum ImplicitCast {
-        IntToDouble,
-        IntToLong,
-    }
-
-    public static Layout createLayout() {
-        return createLayout(NONE);
-    }
-
-    public static Layout createLayout(EnumSet<ImplicitCast> allowedImplicitCasts) {
-        return new LayoutBuilder().setAllowedImplicitCasts(allowedImplicitCasts).build();
-    }
-
-    public static Layout createLayout(EnumSet<ImplicitCast> allowedImplicitCasts, FieldOffsetProvider fieldOffsetProvider) {
-        return new LayoutBuilder().setAllowedImplicitCasts(allowedImplicitCasts).setFieldOffsetProvider(fieldOffsetProvider).build();
-    }
-
-    public abstract DynamicObject newInstance(Shape shape);
-
-    public abstract Class<? extends DynamicObject> getType();
-
-    public abstract Shape createShape(ObjectType operations);
-
-    public abstract Shape createShape(ObjectType operations, Object sharedData);
-
-    public abstract Shape createShape(ObjectType operations, Object sharedData, int id);
-
-    /**
-     * Create an allocator for static property creation. Reserves all array extension slots.
-     */
-    public abstract Allocator createAllocator();
-
-    protected static LayoutFactory getFactory() {
-        return LAYOUT_FACTORY;
-    }
-
-    private static LayoutFactory loadLayoutFactory() {
-        LayoutFactory bestLayoutFactory = null;
-
-        String layoutFactoryImplClassName = System.getProperty(OPTION_PREFIX + "LayoutFactory");
-        if (layoutFactoryImplClassName != null) {
-            Class<?> clazz;
-            try {
-                clazz = Class.forName(layoutFactoryImplClassName);
-            } catch (ClassNotFoundException e) {
-                throw new RuntimeException(e);
-            }
-            try {
-                bestLayoutFactory = (LayoutFactory) clazz.newInstance();
-            } catch (InstantiationException | IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        } else {
-            ServiceLoader<LayoutFactory> serviceLoader = ServiceLoader.load(LayoutFactory.class, Layout.class.getClassLoader());
-            for (LayoutFactory currentLayoutFactory : serviceLoader) {
-                if (bestLayoutFactory == null) {
-                    bestLayoutFactory = currentLayoutFactory;
-                } else if (currentLayoutFactory.getPriority() >= bestLayoutFactory.getPriority()) {
-                    assert currentLayoutFactory.getPriority() != bestLayoutFactory.getPriority();
-                    bestLayoutFactory = currentLayoutFactory;
-                }
-            }
-        }
-
-        if (bestLayoutFactory == null) {
-            throw new AssertionError("LayoutFactory not found");
-        }
-        return bestLayoutFactory;
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
-import com.oracle.truffle.api.object.Layout.ImplicitCast;
-
-public class LayoutBuilder {
-    private EnumSet<ImplicitCast> allowedImplicitCasts;
-    private FieldOffsetProvider fieldOffsetProvider;
-
-    public LayoutBuilder() {
-        this.allowedImplicitCasts = Layout.NONE;
-        this.fieldOffsetProvider = null;
-    }
-
-    public Layout build() {
-        return Layout.getFactory().createLayout(this);
-    }
-
-    public LayoutBuilder setAllowedImplicitCasts(EnumSet<ImplicitCast> allowedImplicitCasts) {
-        this.allowedImplicitCasts = allowedImplicitCasts;
-        return this;
-    }
-
-    public LayoutBuilder setFieldOffsetProvider(FieldOffsetProvider fieldOffsetProvider) {
-        this.fieldOffsetProvider = fieldOffsetProvider;
-        return this;
-    }
-
-    public EnumSet<ImplicitCast> getAllowedImplicitCasts() {
-        return allowedImplicitCasts;
-    }
-
-    public FieldOffsetProvider getFieldOffsetProvider() {
-        return fieldOffsetProvider;
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface LayoutFactory {
-    Layout createLayout(LayoutBuilder layoutBuilder);
-
-    Property createProperty(Object id, Location location);
-
-    Property createProperty(Object id, Location location, int flags);
-
-    int getPriority();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Location.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Property location.
- *
- * @see Shape
- * @see Property
- * @see DynamicObject
- */
-public abstract class Location implements BaseLocation {
-    protected static IncompatibleLocationException incompatibleLocation() throws IncompatibleLocationException {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        throw new IncompatibleLocationException();
-    }
-
-    protected static FinalLocationException finalLocation() throws FinalLocationException {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        throw new FinalLocationException();
-    }
-
-    public final Object get(DynamicObject store, Shape shape) {
-        return get(store, checkShape(store, shape));
-    }
-
-    public Object get(DynamicObject store, boolean condition) {
-        return getInternal(store);
-    }
-
-    public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
-        setInternal(store, value);
-    }
-
-    public final void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException {
-        if (canStore(value)) {
-            store.setShapeAndGrow(oldShape, newShape);
-            try {
-                setInternal(store, value);
-            } catch (IncompatibleLocationException ex) {
-                throw new IllegalStateException();
-            }
-        } else {
-            throw incompatibleLocation();
-        }
-    }
-
-    public final void set(DynamicObject store, Object value) throws IncompatibleLocationException, FinalLocationException {
-        set(store, value, null);
-    }
-
-    protected abstract Object getInternal(DynamicObject store);
-
-    /**
-     * Like {@link #set(DynamicObject, Object, Shape)}, but does not invalidate final locations. For
-     * internal use only and subject to change, use {@link DynamicObjectFactory} to create objects
-     * with predefined properties.
-     *
-     * @throws IncompatibleLocationException if value is of non-assignable type
-     */
-    protected abstract void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException;
-
-    /**
-     * Returns {@code true} if the location can be set to the value.
-     *
-     * @param store the receiver object
-     * @param value the value in question
-     */
-    public boolean canSet(DynamicObject store, Object value) {
-        return canStore(value);
-    }
-
-    /**
-     * Returns {@code true} if the location is compatible with the value.
-     *
-     * The value may still be rejected if {@link #canSet(DynamicObject, Object)} returns false.
-     *
-     * @param value the value in question
-     */
-    public boolean canStore(Object value) {
-        return true;
-    }
-
-    /**
-     * Returns {@code true} if this is a final location, i.e. readonly once set.
-     */
-    public boolean isFinal() {
-        return false;
-    }
-
-    /**
-     * Returns {@code true} if this is an immutable constant location.
-     */
-    public boolean isConstant() {
-        return false;
-    }
-
-    /*
-     * Abstract to force overriding.
-     */
-    @Override
-    public abstract int hashCode();
-
-    /*
-     * Abstract to force overriding.
-     */
-    @Override
-    public abstract boolean equals(Object obj);
-
-    protected static boolean checkShape(DynamicObject store, Shape shape) {
-        return store.getShape() == shape;
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface LocationFactory {
-    Location createLocation(Shape shape, Object value);
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public enum LocationModifier {
-    Final,
-    NonNull,
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LongLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface LongLocation extends TypedLocation {
-    /**
-     * @see #get(DynamicObject, Shape)
-     */
-    long getLong(DynamicObject store, Shape shape);
-
-    /**
-     * @see #get(DynamicObject, boolean)
-     */
-    long getLong(DynamicObject store, boolean condition);
-
-    /**
-     * @see #set(DynamicObject, Object)
-     */
-    void setLong(DynamicObject store, long value) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape)
-     */
-    void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException;
-
-    /**
-     * @see #set(DynamicObject, Object, Shape, Shape)
-     */
-    void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape);
-
-    Class<Long> getType();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface ObjectLocation extends TypedLocation {
-    Class<? extends Object> getType();
-
-    /**
-     * If {@code true}, this location does not accept {@code null} values.
-     */
-    boolean isNonNull();
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.interop.*;
-
-public class ObjectType {
-    /**
-     * Delegate method for {@link DynamicObject#equals(Object)}.
-     */
-    public boolean equals(DynamicObject object, Object other) {
-        return object == other;
-    }
-
-    /**
-     * Delegate method for {@link DynamicObject#hashCode()}.
-     */
-    public int hashCode(DynamicObject object) {
-        return System.identityHashCode(object);
-    }
-
-    /**
-     * Delegate method for {@link DynamicObject#toString()}.
-     */
-    @TruffleBoundary
-    public String toString(DynamicObject object) {
-        return "DynamicObject<" + this.toString() + ">@" + Integer.toHexString(hashCode(object));
-    }
-
-    /**
-     * Creates a data object to be associated with a newly created shape.
-     *
-     * @param shape the shape for which to create the data object
-     */
-    public Object createShapeData(Shape shape) {
-        return null;
-    }
-
-    public ForeignAccess getForeignAccessFactory() {
-        return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() {
-
-            public boolean canHandle(TruffleObject obj) {
-                throw new IllegalArgumentException(this.toString() + " cannot be shared");
-            }
-
-            public CallTarget accessMessage(Message tree) {
-                throw new IllegalArgumentException(this.toString() + " cannot be shared; Message not possible: " + tree.toString());
-            }
-        });
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Property.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-/**
- * Property objects represent the mapping between property identifiers (keys) and storage locations.
- * Optionally, properties may have metadata attached to them.
- */
-public abstract class Property {
-    protected Property() {
-    }
-
-    public static Property create(Object key, Location location, int flags) {
-        return Layout.getFactory().createProperty(key, location, flags);
-    }
-
-    /**
-     * Get property identifier.
-     */
-    public abstract Object getKey();
-
-    /**
-     * Get property flags.
-     */
-    public abstract int getFlags();
-
-    /**
-     * Change the property's location.
-     *
-     * @return a Property with the new location (or {@code this} if the location is unchanged).
-     */
-    public abstract Property relocate(Location newLocation);
-
-    /**
-     * Gets the value of this property of the object.
-     *
-     * @param store the store that this property resides in
-     * @param shape the current shape of the object, which must contain this location
-     * @see DynamicObject#get(Object, Object)
-     */
-    public abstract Object get(DynamicObject store, Shape shape);
-
-    /**
-     * Gets the value of this property of the object.
-     *
-     * @param store the store that this property resides in
-     * @param condition the result of a shape check or {@code false}
-     * @see DynamicObject#get(Object, Object)
-     * @see #get(DynamicObject, Shape)
-     */
-    public abstract Object get(DynamicObject store, boolean condition);
-
-    /**
-     * Assigns value to this property of the object.
-     *
-     * Throws an exception if the value cannot be assigned to the property's current location.
-     *
-     * @param store the store that this property resides in
-     * @param value the value to assign
-     * @param shape the current shape of the object or {@code null}
-     * @throws IncompatibleLocationException if the value is incompatible with the property location
-     * @throws FinalLocationException if the location is final and values differ
-     * @see DynamicObject#set(Object, Object)
-     */
-    public abstract void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException;
-
-    /**
-     * Assigns value to this property of the object.
-     *
-     * Automatically relocates the property if the value cannot be assigned to its current location.
-     *
-     * @param shape the current shape of the object or {@code null}
-     */
-    public abstract void setGeneric(DynamicObject store, Object value, Shape shape);
-
-    /**
-     * Like {@link #set(DynamicObject, Object, Shape)}, but throws an {@link IllegalStateException}
-     * instead.
-     */
-    public abstract void setSafe(DynamicObject store, Object value, Shape shape);
-
-    /**
-     * Like {@link #setSafe}, but ignores the finalness of the property. For internal use only.
-     *
-     * @param store the store that this property resides in
-     * @param value the value to assign
-     */
-    public abstract void setInternal(DynamicObject store, Object value);
-
-    /**
-     * Assigns value to this property of the object, changing the object's shape.
-     *
-     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
-     * {@link #set(DynamicObject, Object, Shape)} to an atomic operation.
-     *
-     * @param store the store that this property resides in
-     * @param value the value to assign
-     * @param oldShape the shape before the transition
-     * @param newShape the shape after the transition
-     * @throws IncompatibleLocationException if the value is incompatible with the property location
-     */
-    public abstract void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException;
-
-    /**
-     * Assigns value to this property of the object, changing the object's shape.
-     *
-     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
-     * {@link #setGeneric(DynamicObject, Object, Shape)} to an atomic operation.
-     *
-     * @param store the store that this property resides in
-     * @param value the value to assign
-     * @param oldShape the shape before the transition
-     * @param newShape the shape after the transition
-     */
-    public abstract void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape);
-
-    /**
-     * Assigns value to this property of the object, changing the object's shape.
-     *
-     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
-     * {@link #setSafe(DynamicObject, Object, Shape)} to an atomic operation.
-     *
-     * @param store the store that this property resides in
-     * @param value the value to assign
-     * @param oldShape the shape before the transition
-     * @param newShape the shape after the transition
-     */
-    public abstract void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape);
-
-    /**
-     * Returns {@code true} if this property and some other property have the same key and flags.
-     */
-    public abstract boolean isSame(Property other);
-
-    /**
-     * Get the property location.
-     */
-    public abstract Location getLocation();
-
-    /**
-     * Is this property hidden from iteration.
-     *
-     * @see HiddenKey
-     */
-    public abstract boolean isHidden();
-
-    public abstract boolean isShadow();
-
-    /**
-     * Create a copy of the property with the given flags.
-     */
-    public abstract Property copyWithFlags(int newFlags);
-
-    public abstract Property copyWithRelocatable(boolean newRelocatable);
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Shape objects create a mapping of Property objects to Locations. Shapes are immutable; adding or
- * deleting a property yields a new Shape which links to the old one. This allows inline caching to
- * simply check the identity of an object's Shape to determine if the cache is valid. There is one
- * exception to this immutability, the transition map, but that is used simply to assure that an
- * identical series of property additions and deletions will yield the same Shape object.
- *
- * @see DynamicObject
- * @see Property
- * @see Location
- */
-public abstract class Shape {
-    /**
-     * Get a property entry by key.
-     *
-     * @param key the identifier to look up
-     * @return a Property object, or null if not found
-     */
-    public abstract Property getProperty(Object key);
-
-    /**
-     * Add a new property in the map, yielding a new or cached Shape object.
-     *
-     * @param property the property to add
-     * @return the new Shape
-     */
-    public abstract Shape addProperty(Property property);
-
-    /**
-     * An {@link Iterable} over the shape's properties in insertion order.
-     */
-    public abstract Iterable<Property> getProperties();
-
-    /**
-     * Get a list of properties that this Shape stores.
-     *
-     * @return list of properties
-     */
-    public abstract List<Property> getPropertyList(Pred<Property> filter);
-
-    /**
-     * Get a list of all properties that this Shape stores.
-     *
-     * @return list of properties
-     */
-    public abstract List<Property> getPropertyList();
-
-    /**
-     * Returns all (also hidden) property objects in this shape.
-     *
-     * @param ascending desired order ({@code true} for insertion order, {@code false} for reverse
-     *            insertion order)
-     */
-    public abstract List<Property> getPropertyListInternal(boolean ascending);
-
-    /**
-     * Get a filtered list of property keys in insertion order.
-     */
-    public abstract List<Object> getKeyList(Pred<Property> filter);
-
-    /**
-     * Get a list of all property keys in insertion order.
-     */
-    public abstract List<Object> getKeyList();
-
-    /**
-     * Get all property keys in insertion order.
-     */
-    public abstract Iterable<Object> getKeys();
-
-    /**
-     * Get an assumption that the shape is valid.
-     */
-    public abstract Assumption getValidAssumption();
-
-    /**
-     * Check whether this shape is valid.
-     */
-    public abstract boolean isValid();
-
-    /**
-     * Get an assumption that the shape is a leaf.
-     */
-    public abstract Assumption getLeafAssumption();
-
-    /**
-     * Check whether this shape is a leaf in the transition graph, i.e. transitionless.
-     */
-    public abstract boolean isLeaf();
-
-    /**
-     * @return the parent shape or {@code null} if none.
-     */
-    public abstract Shape getParent();
-
-    /**
-     * Check whether the shape has a property with the given key.
-     */
-    public abstract boolean hasProperty(Object key);
-
-    /**
-     * Remove the given property from the shape.
-     */
-    public abstract Shape removeProperty(Property property);
-
-    /**
-     * Replace a property in the shape.
-     */
-    public abstract Shape replaceProperty(Property oldProperty, Property newProperty);
-
-    /**
-     * Get the last added property.
-     */
-    public abstract Property getLastProperty();
-
-    public abstract int getId();
-
-    /**
-     * Append the property, relocating it to the next allocated location.
-     */
-    public abstract Shape append(Property oldProperty);
-
-    /**
-     * Obtain an {@link Allocator} instance for the purpose of allocating locations.
-     */
-    public abstract Allocator allocator();
-
-    /**
-     * Get number of properties in this shape.
-     */
-    public abstract int getPropertyCount();
-
-    /**
-     * Get the shape's operations.
-     */
-    public abstract ObjectType getObjectType();
-
-    /**
-     * Get the root shape.
-     */
-    public abstract Shape getRoot();
-
-    /**
-     * Check whether this shape is identical to the given shape.
-     */
-    public abstract boolean check(DynamicObject subject);
-
-    /**
-     * Get the shape's layout.
-     */
-    public abstract Layout getLayout();
-
-    /**
-     * Get the shape's custom data.
-     */
-    public abstract Object getData();
-
-    /**
-     * Get the shape's shared data.
-     */
-    public abstract Object getSharedData();
-
-    /**
-     * Query whether the shape has a transition with the given key.
-     */
-    public abstract boolean hasTransitionWithKey(Object key);
-
-    /**
-     * Clone off a separate shape with new shared data.
-     */
-    public abstract Shape createSeparateShape(Object sharedData);
-
-    /**
-     * Change the shape's type, yielding a new shape.
-     */
-    public abstract Shape changeType(ObjectType newOps);
-
-    /**
-     * Reserve the primitive extension array field.
-     */
-    public abstract Shape reservePrimitiveExtensionArray();
-
-    /**
-     * Create a new {@link DynamicObject} instance with this shape.
-     */
-    public abstract DynamicObject newInstance();
-
-    /**
-     * Create a {@link DynamicObjectFactory} for creating instances of this shape.
-     */
-    public abstract DynamicObjectFactory createFactory();
-
-    /**
-     * Get mutex object shared by related shapes, i.e. shapes with a common root.
-     */
-    public abstract Object getMutex();
-
-    public abstract int getObjectArraySize();
-
-    public abstract int getObjectFieldSize();
-
-    public abstract int getPrimitiveArraySize();
-
-    public abstract int getPrimitiveFieldSize();
-
-    public abstract int getObjectArrayCapacity();
-
-    public abstract int getPrimitiveArrayCapacity();
-
-    public abstract boolean hasPrimitiveArray();
-
-    /**
-     * Are these two shapes related, i.e. do they have the same root?
-     *
-     * @param other Shape to compare to
-     * @return true if one shape is an upcast of the other, or the Shapes are equal
-     */
-    public abstract boolean isRelated(Shape other);
-
-    public abstract Shape tryMerge(Shape other);
-
-    public <R> R accept(ShapeVisitor<R> visitor) {
-        return visitor.visitShape(this);
-    }
-
-    public abstract static class Allocator {
-        protected abstract Location locationForValue(Object value, boolean useFinal, boolean nonNull);
-
-        public final Location locationForValue(Object value) {
-            return locationForValue(value, false, value != null);
-        }
-
-        public final Location locationForValue(Object value, EnumSet<LocationModifier> modifiers) {
-            assert value != null || !modifiers.contains(LocationModifier.NonNull);
-            return locationForValue(value, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
-        }
-
-        protected abstract Location locationForType(Class<?> type, boolean useFinal, boolean nonNull);
-
-        public final Location locationForType(Class<?> type) {
-            return locationForType(type, false, false);
-        }
-
-        public final Location locationForType(Class<?> type, EnumSet<LocationModifier> modifiers) {
-            return locationForType(type, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
-        }
-
-        public abstract Location constantLocation(Object value);
-
-        public abstract Location declaredLocation(Object value);
-
-        public abstract Allocator addLocation(Location location);
-    }
-
-    /**
-     * Represents a predicate (boolean-valued function) of one argument. For Java 7 compatibility.
-     *
-     * @param <T> the type of the input to the predicate
-     */
-    public interface Pred<T> {
-        /**
-         * Evaluates this predicate on the given argument.
-         *
-         * @param t the input argument
-         * @return {@code true} if the input argument matches the predicate, otherwise {@code false}
-         */
-        boolean test(T t);
-    }
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface ShapeListener {
-    /**
-     * Called when a property is added, removed, or replaced.
-     *
-     * @param key identifier of the property
-     */
-    void onPropertyTransition(Object key);
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface ShapeVisitor<R> {
-    R visitShape(Shape shape);
-}
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.object;
-
-public interface TypedLocation extends BaseLocation {
-    /**
-     * The type of this location.
-     */
-    Class<?> getType();
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Passing Arguments</h3>
- *
- * <p>
- * When invoking a call target with {@link CallTarget#call(Object[])}, arguments can be passed. A
- * Truffle node can access the arguments passed into the Truffle method by using
- * {@link VirtualFrame#getArguments}.
- * </p>
- *
- * <p>
- * The arguments class should only contain fields that are declared as final. This allows the
- * Truffle runtime to improve optimizations around guest language method calls. Also, the arguments
- * object array must never be stored into a field. It should be created immediately before invoking
- * {@link CallTarget#call(Object[])} and no longer be accessed afterwards.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FrameTest}
- * .
- * </p>
- */
-public class ArgumentsTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestRootNode rootNode = new TestRootNode(new TestArgumentNode[]{new TestArgumentNode(0), new TestArgumentNode(1)});
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Object result = target.call(new Object[]{20, 22});
-        Assert.assertEquals(42, result);
-    }
-
-    private static class TestRootNode extends RootNode {
-
-        @Children private final TestArgumentNode[] children;
-
-        TestRootNode(TestArgumentNode[] children) {
-            super(null);
-            this.children = children;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            int sum = 0;
-            for (int i = 0; i < children.length; ++i) {
-                sum += children[i].execute(frame);
-            }
-            return sum;
-        }
-    }
-
-    private static class TestArgumentNode extends Node {
-
-        private final int index;
-
-        TestArgumentNode(int index) {
-            super(null);
-            this.index = index;
-        }
-
-        int execute(VirtualFrame frame) {
-            return (Integer) frame.getArguments()[index];
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Calling Another Tree</h3>
- *
- * <p>
- * A guest language implementation can create multiple call targets using the
- * {@link TruffleRuntime#createCallTarget(RootNode)} method. Those call targets can be passed around
- * as normal Java objects and used for calling guest language methods.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.ArgumentsTest}.
- * </p>
- */
-public class CallTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        CallTarget foo = runtime.createCallTarget(new ConstantRootNode(20));
-        CallTarget bar = runtime.createCallTarget(new ConstantRootNode(22));
-        CallTarget main = runtime.createCallTarget(new DualCallNode(foo, bar));
-        Object result = main.call();
-        Assert.assertEquals(42, result);
-    }
-
-    class DualCallNode extends RootNode {
-
-        private final CallTarget firstTarget;
-        private final CallTarget secondTarget;
-
-        DualCallNode(CallTarget firstTarget, CallTarget secondTarget) {
-            super(null);
-            this.firstTarget = firstTarget;
-            this.secondTarget = secondTarget;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return ((Integer) firstTarget.call()) + ((Integer) secondTarget.call());
-        }
-    }
-
-    class ConstantRootNode extends RootNode {
-
-        private final int value;
-
-        public ConstantRootNode(int value) {
-            super(null);
-            this.value = value;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return value;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.Node.Child;
-
-/**
- * <h3>Creating a Child Node</h3>
- *
- * <p>
- * Child nodes are stored in the class of the parent node in fields that are marked with the
- * {@link Child} annotation. The {@link Node#getParent()} method allows access to this field. Every
- * node also provides the ability to iterate over its children using {@link Node#getChildren()}.
- * </p>
- *
- * <p>
- * A child node field must be declared private and non-final. It may only be assigned in the
- * constructor of the parent node. For changing the structure of the tree at run time, the method
- * {@link Node#replace(Node)} must be used (see {@link ReplaceTest}).
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.ChildrenNodesTest}.
- * </p>
- */
-public class ChildNodeTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestChildNode leftChild = new TestChildNode();
-        TestChildNode rightChild = new TestChildNode();
-        TestRootNode rootNode = new TestRootNode(leftChild, rightChild);
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Assert.assertEquals(rootNode, leftChild.getParent());
-        Assert.assertEquals(rootNode, rightChild.getParent());
-        Iterator<Node> iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(leftChild, iterator.next());
-        Assert.assertEquals(rightChild, iterator.next());
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Child private TestChildNode left;
-        @Child private TestChildNode right;
-
-        public TestRootNode(TestChildNode left, TestChildNode right) {
-            super(null);
-            this.left = left;
-            this.right = right;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return left.execute() + right.execute();
-        }
-    }
-
-    class TestChildNode extends Node {
-
-        public TestChildNode() {
-            super(null);
-        }
-
-        public int execute() {
-            return 21;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Creating an Array of Children Nodes</h3>
- *
- * <p>
- * An array of children nodes can be used as a field in a parent node. The field has to be annotated
- * with {@link com.oracle.truffle.api.nodes.Node.Children} and must be declared private and final.
- * Before assigning the field in the parent node constructor, {@link Node#adoptChildren} must be
- * called in order to update the parent pointers in the child nodes. After filling the array with
- * its first values, it must never be changed. It is only possible to call {@link Node#replace} on a
- * child node.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.FinalFieldTest}.
- * </p>
- */
-public class ChildrenNodesTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestChildNode firstChild = new TestChildNode();
-        TestChildNode secondChild = new TestChildNode();
-        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild});
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Assert.assertEquals(rootNode, firstChild.getParent());
-        Assert.assertEquals(rootNode, secondChild.getParent());
-        Iterator<Node> iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(firstChild, iterator.next());
-        Assert.assertEquals(secondChild, iterator.next());
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Children private final TestChildNode[] children;
-
-        public TestRootNode(TestChildNode[] children) {
-            super(null);
-            this.children = children;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            int sum = 0;
-            for (int i = 0; i < children.length; ++i) {
-                sum += children[i].execute();
-            }
-            return sum;
-        }
-    }
-
-    class TestChildNode extends Node {
-
-        public TestChildNode() {
-            super(null);
-        }
-
-        public int execute() {
-            return 21;
-        }
-    }
-
-    @Test
-    public void testMultipleChildrenFields() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestChildNode firstChild = new TestChildNode();
-        TestChildNode secondChild = new TestChildNode();
-        TestChildNode thirdChild = new TestChildNode();
-        TestChildNode forthChild = new TestChildNode();
-        TestRootNode rootNode = new TestRoot2Node(new TestChildNode[]{firstChild, secondChild}, new TestChildNode[]{thirdChild, forthChild});
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Assert.assertEquals(rootNode, firstChild.getParent());
-        Assert.assertEquals(rootNode, secondChild.getParent());
-        Assert.assertEquals(rootNode, thirdChild.getParent());
-        Assert.assertEquals(rootNode, forthChild.getParent());
-        Iterator<Node> iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(firstChild, iterator.next());
-        Assert.assertEquals(secondChild, iterator.next());
-        Assert.assertEquals(thirdChild, iterator.next());
-        Assert.assertEquals(forthChild, iterator.next());
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        Assert.assertEquals(2 * 42, result);
-    }
-
-    class TestRoot2Node extends TestRootNode {
-        @Children private final TestChildNode[] children1;
-        @Children private final TestChildNode[] children2;
-
-        public TestRoot2Node(TestChildNode[] children1, TestChildNode[] children2) {
-            super(new TestChildNode[0]);
-            this.children1 = children1;
-            this.children2 = children2;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            int sum = 0;
-            for (int i = 0; i < children1.length; ++i) {
-                sum += children1[i].execute();
-            }
-            for (int i = 0; i < children2.length; ++i) {
-                sum += children2[i].execute();
-            }
-            return sum;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Using Final Fields in Node Classes</h3>
- *
- * <p>
- * The usage of final fields in node classes is highly encouraged. It is beneficial for performance
- * to declare every field that is not pointing to a child node as final. This gives the Truffle
- * runtime an increased opportunity to optimize this node.
- * </p>
- *
- * <p>
- * If a node has a value which may change at run time, but will rarely do so, it is recommended to
- * speculate on the field being final. This involves starting executing with a node where this field
- * is final and only if this turns out to be no longer the case, the node is replaced with an
- * alternative implementation of the operation (see {@link ReplaceTest}).
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.ReplaceTest}.
- * </p>
- */
-public class FinalFieldTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{new TestChildNode(20), new TestChildNode(22)});
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-    }
-
-    private static class TestRootNode extends RootNode {
-
-        @Children private final TestChildNode[] children;
-
-        public TestRootNode(TestChildNode[] children) {
-            super(null);
-            this.children = children;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            int sum = 0;
-            for (int i = 0; i < children.length; ++i) {
-                sum += children[i].execute();
-            }
-            return sum;
-        }
-    }
-
-    private static class TestChildNode extends Node {
-
-        private final int value;
-
-        public TestChildNode(int value) {
-            super(null);
-            this.value = value;
-        }
-
-        public int execute() {
-            return value;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Specializing Frame Slot Types</h3>
- *
- * <p>
- * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run
- * time to a more generic type if necessary. The new type of a frame slot can be set using the
- * {@link FrameSlot#setKind(FrameSlotKind)} method.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}.
- * </p>
- */
-public class FrameSlotTypeSpecializationTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
-        Object result = target.call();
-        Assert.assertEquals("42", result);
-        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Child TestChildNode left;
-        @Child TestChildNode right;
-
-        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
-            super(null, descriptor);
-            this.left = left;
-            this.right = right;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            left.execute(frame);
-            return right.execute(frame);
-        }
-    }
-
-    abstract class TestChildNode extends Node {
-
-        protected TestChildNode() {
-            super(null);
-        }
-
-        abstract Object execute(VirtualFrame frame);
-    }
-
-    abstract class FrameSlotNode extends TestChildNode {
-
-        protected final FrameSlot slot;
-
-        public FrameSlotNode(FrameSlot slot) {
-            this.slot = slot;
-        }
-    }
-
-    class StringTestChildNode extends TestChildNode {
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            return "42";
-        }
-
-    }
-
-    class IntAssignLocal extends FrameSlotNode {
-
-        @Child private TestChildNode value;
-
-        IntAssignLocal(FrameSlot slot, TestChildNode value) {
-            super(slot);
-            this.value = value;
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            Object o = value.execute(frame);
-            if (o instanceof Integer) {
-                frame.setInt(slot, (Integer) o);
-            } else {
-                slot.setKind(FrameSlotKind.Object);
-                frame.setObject(slot, o);
-                this.replace(new ObjectAssignLocal(slot, value));
-            }
-            return null;
-        }
-    }
-
-    class ObjectAssignLocal extends FrameSlotNode {
-
-        @Child private TestChildNode value;
-
-        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
-            super(slot);
-            this.value = value;
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            Object o = value.execute(frame);
-            slot.setKind(FrameSlotKind.Object);
-            frame.setObject(slot, o);
-            return null;
-        }
-    }
-
-    class IntReadLocal extends FrameSlotNode {
-
-        IntReadLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            try {
-                return frame.getInt(slot);
-            } catch (FrameSlotTypeException e) {
-                return this.replace(new ObjectReadLocal(slot)).execute(frame);
-            }
-        }
-    }
-
-    class ObjectReadLocal extends FrameSlotNode {
-
-        ObjectReadLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            try {
-                return frame.getObject(slot);
-            } catch (FrameSlotTypeException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Storing Values in Frame Slots</h3>
- *
- * <p>
- * The frame is the preferred data structure for passing values between nodes. It can in particular
- * be used for storing the values of local variables of the guest language. The
- * {@link FrameDescriptor} represents the current structure of the frame. The method
- * {@link FrameDescriptor#addFrameSlot(Object, FrameSlotKind)} can be used to create predefined
- * frame slots. The setter and getter methods in the {@link Frame} class can be used to access the
- * current value of a particular frame slot. Values can be removed from a frame via the
- * {@link FrameDescriptor#removeFrameSlot(Object)} method.
- * </p>
- *
- * <p>
- * There are five primitive types for slots available: {@link java.lang.Boolean},
- * {@link java.lang.Integer}, {@link java.lang.Long}, {@link java.lang.Float}, and
- * {@link java.lang.Double} . It is encouraged to use those types whenever possible. Dynamically
- * typed languages can speculate on the type of a value fitting into a primitive (see
- * {@link FrameSlotTypeSpecializationTest}). When a frame slot is of one of those particular
- * primitive types, its value may only be accessed with the respectively typed getter method (
- * {@link Frame#getBoolean}, {@link Frame#getInt}, {@link Frame#getLong}, {@link Frame#getFloat}, or
- * {@link Frame#getDouble}) or setter method ({@link Frame#setBoolean}, {@link Frame#setInt},
- * {@link Frame#setLong}, {@link Frame#setFloat}, or {@link Frame#setDouble}) in the {@link Frame}
- * class.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}.
- * </p>
- */
-public class FrameTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        FrameDescriptor frameDescriptor = new FrameDescriptor();
-        String varName = "localVar";
-        FrameSlot slot = frameDescriptor.addFrameSlot(varName, FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(frameDescriptor, new AssignLocal(slot), new ReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-        frameDescriptor.removeFrameSlot(varName);
-        boolean slotMissing = false;
-        try {
-            result = target.call();
-        } catch (IllegalArgumentException iae) {
-            slotMissing = true;
-        }
-        Assert.assertTrue(slotMissing);
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Child TestChildNode left;
-        @Child TestChildNode right;
-
-        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
-            super(null, descriptor);
-            this.left = left;
-            this.right = right;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return left.execute(frame) + right.execute(frame);
-        }
-    }
-
-    abstract class TestChildNode extends Node {
-
-        public TestChildNode() {
-            super(null);
-        }
-
-        abstract int execute(VirtualFrame frame);
-    }
-
-    abstract class FrameSlotNode extends TestChildNode {
-
-        protected final FrameSlot slot;
-
-        public FrameSlotNode(FrameSlot slot) {
-            this.slot = slot;
-        }
-    }
-
-    class AssignLocal extends FrameSlotNode {
-
-        AssignLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            frame.setInt(slot, 42);
-            return 0;
-        }
-    }
-
-    class ReadLocal extends FrameSlotNode {
-
-        ReadLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            try {
-                return frame.getInt(slot);
-            } catch (FrameSlotTypeException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Test child fields declared with interface types instead of {@link Node} subclasses.
- */
-public class InterfaceChildFieldTest {
-
-    @Test
-    public void testChild() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestChildInterface leftChild = new TestLeafNode();
-        TestChildInterface rightChild = new TestLeafNode();
-        TestChildNode parent = new TestChildNode(leftChild, rightChild);
-        TestRootNode rootNode = new TestRootNode(parent);
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Iterator<Node> iterator = parent.getChildren().iterator();
-        Assert.assertEquals(leftChild, iterator.next());
-        Assert.assertEquals(rightChild, iterator.next());
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-
-        Assert.assertEquals(4, NodeUtil.countNodes(rootNode));
-        Assert.assertEquals(4, NodeUtil.countNodes(NodeUtil.cloneNode(rootNode)));
-    }
-
-    @Test
-    public void testChildren() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestChildInterface[] children = new TestChildInterface[5];
-        for (int i = 0; i < children.length; i++) {
-            children[i] = new TestLeafNode();
-        }
-        TestChildrenNode parent = new TestChildrenNode(children);
-        TestRootNode rootNode = new TestRootNode(parent);
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Iterator<Node> iterator = parent.getChildren().iterator();
-        for (int i = 0; i < children.length; i++) {
-            Assert.assertEquals(children[i], iterator.next());
-        }
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        Assert.assertEquals(105, result);
-
-        Assert.assertEquals(2 + children.length, NodeUtil.countNodes(rootNode));
-        Assert.assertEquals(2 + children.length, NodeUtil.countNodes(NodeUtil.cloneNode(rootNode)));
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Child private TestChildInterface child;
-
-        public TestRootNode(TestChildInterface child) {
-            super(null);
-            this.child = child;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return child.executeIntf();
-        }
-    }
-
-    interface TestChildInterface extends NodeInterface {
-        int executeIntf();
-    }
-
-    class TestLeafNode extends Node implements TestChildInterface {
-        public TestLeafNode() {
-            super(null);
-        }
-
-        public int executeIntf() {
-            return this.replace(new TestLeaf2Node()).executeIntf();
-        }
-    }
-
-    class TestLeaf2Node extends Node implements TestChildInterface {
-        public TestLeaf2Node() {
-            super(null);
-        }
-
-        public int executeIntf() {
-            return 21;
-        }
-    }
-
-    class TestChildNode extends Node implements TestChildInterface {
-
-        @Child private TestChildInterface left;
-        @Child private TestChildInterface right;
-
-        public TestChildNode(TestChildInterface left, TestChildInterface right) {
-            super(null);
-            this.left = left;
-            this.right = right;
-        }
-
-        @Override
-        public int executeIntf() {
-            return left.executeIntf() + right.executeIntf();
-        }
-    }
-
-    class TestChildrenNode extends Node implements TestChildInterface {
-
-        @Children private final TestChildInterface[] children;
-
-        public TestChildrenNode(TestChildInterface[] children) {
-            super(null);
-            this.children = children;
-        }
-
-        @Override
-        public int executeIntf() {
-            int sum = 0;
-            for (int i = 0; i < children.length; ++i) {
-                sum += children[i].executeIntf();
-            }
-            return sum;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Replacing Nodes at Run Time</h3>
- *
- * <p>
- * The structure of the Truffle tree can be changed at run time by replacing nodes using the
- * {@link Node#replace(Node)} method. This method will automatically change the child pointer in the
- * parent of the node and replace it with a pointer to the new node.
- * </p>
- *
- * <p>
- * Replacing nodes is a costly operation, so it should not happen too often. The convention is that
- * the implementation of the Truffle nodes should ensure that there are maximal a small (and
- * constant) number of node replacements per Truffle node.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.CallTest}.
- * </p>
- */
-public class ReplaceTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        UnresolvedNode leftChild = new UnresolvedNode("20");
-        UnresolvedNode rightChild = new UnresolvedNode("22");
-        TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild});
-        CallTarget target = runtime.createCallTarget(rootNode);
-        assertEquals(rootNode, leftChild.getParent());
-        assertEquals(rootNode, rightChild.getParent());
-        Iterator<Node> iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(leftChild, iterator.next());
-        Assert.assertEquals(rightChild, iterator.next());
-        Assert.assertFalse(iterator.hasNext());
-        Object result = target.call();
-        assertEquals(42, result);
-        assertEquals(42, target.call());
-        iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
-        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
-        Assert.assertFalse(iterator.hasNext());
-        iterator = rootNode.getChildren().iterator();
-        Assert.assertEquals(rootNode, iterator.next().getParent());
-        Assert.assertEquals(rootNode, iterator.next().getParent());
-        Assert.assertFalse(iterator.hasNext());
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Children private final ValueNode[] children;
-
-        public TestRootNode(ValueNode[] children) {
-            super(null);
-            this.children = children;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            int sum = 0;
-            for (int i = 0; i < children.length; ++i) {
-                sum += children[i].execute();
-            }
-            return sum;
-        }
-    }
-
-    abstract class ValueNode extends Node {
-
-        public ValueNode() {
-            super(null);
-        }
-
-        abstract int execute();
-    }
-
-    class UnresolvedNode extends ValueNode {
-
-        private final String value;
-
-        public UnresolvedNode(String value) {
-            this.value = value;
-        }
-
-        @Override
-        int execute() {
-            int intValue = Integer.parseInt(value);
-            ResolvedNode newNode = this.replace(new ResolvedNode(intValue));
-            return newNode.execute();
-        }
-    }
-
-    class ResolvedNode extends ValueNode {
-
-        private final int value;
-
-        ResolvedNode(int value) {
-            this.value = value;
-        }
-
-        @Override
-        int execute() {
-            return value;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Specializing Return Types</h3>
- *
- * <p>
- * In order to avoid boxing and/or type casts on the return value of a node, the return value the
- * method for executing a node can have a specific type and need not be of type
- * {@link java.lang.Object}. For dynamically typed languages, this return type is something that
- * should be speculated on. When the speculation fails and the child node cannot return the
- * appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the
- * result to the caller. In such a case, the caller must rewrite itself to a more general version in
- * order to avoid future failures of this kind.
- * </p>
- */
-public class ReturnTypeSpecializationTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
-        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
-        Object result = target.call();
-        Assert.assertEquals("42", result);
-        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
-    }
-
-    class TestRootNode extends RootNode {
-
-        @Child TestChildNode left;
-        @Child TestChildNode right;
-
-        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
-            super(null, descriptor);
-            this.left = left;
-            this.right = right;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            left.execute(frame);
-            return right.execute(frame);
-        }
-    }
-
-    abstract class TestChildNode extends Node {
-
-        public TestChildNode() {
-            super(null);
-        }
-
-        abstract Object execute(VirtualFrame frame);
-
-        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
-            Object result = execute(frame);
-            if (result instanceof Integer) {
-                return (Integer) result;
-            }
-            throw new UnexpectedResultException(result);
-        }
-    }
-
-    abstract class FrameSlotNode extends TestChildNode {
-
-        protected final FrameSlot slot;
-
-        public FrameSlotNode(FrameSlot slot) {
-            this.slot = slot;
-        }
-    }
-
-    class StringTestChildNode extends TestChildNode {
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            return "42";
-        }
-
-    }
-
-    class IntAssignLocal extends FrameSlotNode {
-
-        @Child private TestChildNode value;
-
-        IntAssignLocal(FrameSlot slot, TestChildNode value) {
-            super(slot);
-            this.value = value;
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            try {
-                int result = value.executeInt(frame);
-                frame.setInt(slot, result);
-            } catch (UnexpectedResultException e) {
-                slot.setKind(FrameSlotKind.Object);
-                frame.setObject(slot, e.getResult());
-                replace(new ObjectAssignLocal(slot, value));
-            }
-            return null;
-        }
-    }
-
-    class ObjectAssignLocal extends FrameSlotNode {
-
-        @Child private TestChildNode value;
-
-        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
-            super(slot);
-            this.value = value;
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            Object o = value.execute(frame);
-            slot.setKind(FrameSlotKind.Object);
-            frame.setObject(slot, o);
-            return null;
-        }
-    }
-
-    class IntReadLocal extends FrameSlotNode {
-
-        IntReadLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            try {
-                return frame.getInt(slot);
-            } catch (FrameSlotTypeException e) {
-                return replace(new ObjectReadLocal(slot)).execute(frame);
-            }
-        }
-
-        @Override
-        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
-            try {
-                return frame.getInt(slot);
-            } catch (FrameSlotTypeException e) {
-                return replace(new ObjectReadLocal(slot)).executeInt(frame);
-            }
-        }
-    }
-
-    class ObjectReadLocal extends FrameSlotNode {
-
-        ObjectReadLocal(FrameSlot slot) {
-            super(slot);
-        }
-
-        @Override
-        Object execute(VirtualFrame frame) {
-            try {
-                return frame.getObject(slot);
-            } catch (FrameSlotTypeException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * <h3>Creating a Root Node</h3>
- *
- * <p>
- * A Truffle root node is the entry point into a Truffle tree that represents a guest language
- * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a
- * {@link java.lang.Object} value as the result of the guest language method invocation. This method
- * must however never be called directly. Instead, the Truffle runtime must be used to create a
- * {@link CallTarget} object from a root node using the
- * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be
- * executed using the {@link CallTarget#call(Object...)} method or one of its overloads.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.ChildNodeTest}.
- * </p>
- */
-public class RootNodeTest {
-
-    @Test
-    public void test() {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestRootNode rootNode = new TestRootNode();
-        CallTarget target = runtime.createCallTarget(rootNode);
-        Object result = target.call();
-        Assert.assertEquals(42, result);
-    }
-
-    class TestRootNode extends RootNode {
-
-        public TestRootNode() {
-            super(null);
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return 42;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Test node rewriting in a tree shared across multiple threads (run with -ea).
- */
-public class ThreadSafetyTest {
-
-    @Test
-    @Ignore("sporadic failures with \"expected:<1000000> but was:<999999>\"")
-    public void test() throws InterruptedException {
-        TruffleRuntime runtime = Truffle.getRuntime();
-        TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42)))))));
-        final CallTarget target1 = runtime.createCallTarget(rootNode1);
-        NodeUtil.verify(rootNode1);
-
-        RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42));
-        TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode))))));
-        final CallTarget target2 = runtime.createCallTarget(rootNode2);
-        callNode.setCallNode(runtime.createDirectCallNode(target2));
-        NodeUtil.verify(rootNode2);
-
-        testTarget(target1, 47, 1_000_000);
-        testTarget(target2, 72, 1_000_000);
-    }
-
-    private static void testTarget(final CallTarget target, final int expectedResult, final int numberOfIterations) throws InterruptedException {
-        ExecutorService executorService = Executors.newFixedThreadPool(20);
-        final AtomicInteger ai = new AtomicInteger();
-        for (int i = 0; i < numberOfIterations; i++) {
-            executorService.submit(new Runnable() {
-                public void run() {
-                    try {
-                        Object result = target.call(new Object[]{5});
-                        assertEquals(expectedResult, result);
-                        ai.incrementAndGet();
-                    } catch (Throwable t) {
-                        t.printStackTrace(System.out);
-                    }
-                }
-            });
-        }
-        executorService.shutdown();
-        executorService.awaitTermination(90, TimeUnit.SECONDS);
-        assertTrue("test did not terminate", executorService.isTerminated());
-        assertEquals(numberOfIterations, ai.get());
-    }
-
-    static class TestRootNode extends RootNode {
-
-        @Child private ValueNode child;
-
-        public TestRootNode(ValueNode child) {
-            super(null);
-            this.child = child;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return child.execute(frame);
-        }
-    }
-
-    abstract static class ValueNode extends Node {
-
-        public ValueNode() {
-            super(null);
-        }
-
-        abstract int execute(VirtualFrame frame);
-    }
-
-    static class RewritingNode extends ValueNode {
-
-        @Child private ValueNode child;
-        private final Random random;
-
-        public RewritingNode(ValueNode child) {
-            this(child, new Random());
-        }
-
-        public RewritingNode(ValueNode child, Random random) {
-            this.child = child;
-            this.random = random;
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            boolean replace = random.nextBoolean();
-            if (replace) {
-                ValueNode newNode = this.replace(new OtherRewritingNode(child, random));
-                return newNode.execute(frame);
-            }
-            return 1 + child.execute(frame);
-        }
-    }
-
-    static class OtherRewritingNode extends ValueNode {
-
-        @Child private ValueNode child;
-        private final Random random;
-
-        public OtherRewritingNode(ValueNode child, Random random) {
-            this.child = child;
-            this.random = random;
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            boolean replace = random.nextBoolean();
-            if (replace) {
-                ValueNode newNode = this.replace(new RewritingNode(child, random));
-                return newNode.execute(frame);
-            }
-            return 1 + child.execute(frame);
-        }
-    }
-
-    static class ConstNode extends ValueNode {
-
-        private final int value;
-
-        ConstNode(int value) {
-            this.value = value;
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            return value;
-        }
-    }
-
-    static class RecursiveCallNode extends ValueNode {
-        @Child DirectCallNode callNode;
-        @Child private ValueNode valueNode;
-
-        RecursiveCallNode(ValueNode value) {
-            this.valueNode = value;
-        }
-
-        @Override
-        int execute(VirtualFrame frame) {
-            int arg = (Integer) frame.getArguments()[0];
-            if (arg > 0) {
-                return (int) callNode.call(frame, new Object[]{(arg - 1)});
-            } else {
-                return valueNode.execute(frame);
-            }
-        }
-
-        void setCallNode(DirectCallNode callNode) {
-            this.callNode = insert(callNode);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * <h3>Accessing the Truffle Runtime</h3>
- *
- * <p>
- * The Truffle runtime can be accessed at any point in time globally using the static method
- * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime
- * object with an identifying name. A Java Virtual Machine implementation can chose to replace the
- * default implementation of the {@link TruffleRuntime} interface with its own implementation for
- * providing improved performance.
- * </p>
- *
- * <p>
- * The next part of the Truffle API introduction is at
- * {@link com.oracle.truffle.api.test.RootNodeTest}.
- * </p>
- */
-public class TruffleRuntimeTest {
-
-    private TruffleRuntime runtime;
-
-    @Before
-    public void setUp() {
-        this.runtime = Truffle.getRuntime();
-    }
-
-    private static RootNode createTestRootNode() {
-        return new RootNode() {
-            @Override
-            public Object execute(VirtualFrame frame) {
-                return 42;
-            }
-        };
-    }
-
-    // @Test
-    public void verifyTheRealRuntimeIsUsedOnRealGraal() {
-        TruffleRuntime r = Truffle.getRuntime();
-        final String name = r.getClass().getName();
-        if (name.endsWith("DefaultTruffleRuntime")) {
-            fail("Wrong name " + name + " with following System.getProperties:\n" + System.getProperties().toString());
-        }
-    }
-
-    @Test
-    public void test() {
-        assertNotNull(runtime);
-        assertNotNull(runtime.getName());
-    }
-
-    @Test
-    public void testCreateCallTarget() {
-        RootNode rootNode = createTestRootNode();
-        RootCallTarget target = runtime.createCallTarget(rootNode);
-        assertNotNull(target);
-        assertEquals(target.call(), 42);
-        assertSame(rootNode, target.getRootNode());
-    }
-
-    @Test
-    public void testGetCallTargets1() {
-        RootNode rootNode = createTestRootNode();
-        RootCallTarget target = runtime.createCallTarget(rootNode);
-        assertTrue(runtime.getCallTargets().contains(target));
-    }
-
-    @Test
-    public void testGetCallTargets2() {
-        RootNode rootNode = createTestRootNode();
-        RootCallTarget target1 = runtime.createCallTarget(rootNode);
-        RootCallTarget target2 = runtime.createCallTarget(rootNode);
-        assertTrue(runtime.getCallTargets().contains(target1));
-        assertTrue(runtime.getCallTargets().contains(target2));
-    }
-
-    /*
-     * This test case documents the use case for profilers and debuggers where they need to access
-     * multiple call targets for the same source section. This case may happen when the optimization
-     * system decides to duplicate call targets to achieve better performance.
-     */
-    @Test
-    public void testGetCallTargets3() {
-        Source source1 = Source.fromText("a\nb\n", "");
-        SourceSection sourceSection1 = source1.createSection("foo", 1);
-        SourceSection sourceSection2 = source1.createSection("bar", 2);
-
-        RootNode rootNode1 = createTestRootNode();
-        rootNode1.assignSourceSection(sourceSection1);
-        RootNode rootNode2 = createTestRootNode();
-        rootNode2.assignSourceSection(sourceSection2);
-        RootNode rootNode2Copy = NodeUtil.cloneNode(rootNode2);
-
-        assertSame(rootNode2.getSourceSection(), rootNode2Copy.getSourceSection());
-
-        RootCallTarget target1 = runtime.createCallTarget(rootNode1);
-        RootCallTarget target2 = runtime.createCallTarget(rootNode2);
-        RootCallTarget target2Copy = runtime.createCallTarget(rootNode2Copy);
-
-        Map<SourceSection, List<RootCallTarget>> groupedTargets = groupUniqueCallTargets();
-
-        List<RootCallTarget> targets1 = groupedTargets.get(sourceSection1);
-        assertEquals(1, targets1.size());
-        assertEquals(target1, targets1.get(0));
-
-        List<RootCallTarget> targets2 = groupedTargets.get(sourceSection2);
-        assertEquals(2, targets2.size());
-        // order of targets2 is not guaranteed
-        assertTrue(target2 == targets2.get(0) ^ target2Copy == targets2.get(0));
-        assertTrue(target2 == targets2.get(1) ^ target2Copy == targets2.get(1));
-    }
-
-    private static Map<SourceSection, List<RootCallTarget>> groupUniqueCallTargets() {
-        Map<SourceSection, List<RootCallTarget>> groupedTargets = new HashMap<>();
-        for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) {
-            SourceSection section = target.getRootNode().getSourceSection();
-            if (section == null) {
-                // can not identify root node to a unique call target. Print warning?
-                continue;
-            }
-            List<RootCallTarget> targets = groupedTargets.get(section);
-            if (targets == null) {
-                targets = new ArrayList<>();
-                groupedTargets.put(section, targets);
-            }
-            targets.add(target);
-        }
-        return groupedTargets;
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.instrument;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdvancedInstrumentCounterRoot;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode;
-
-/**
- * Tests the kind of instrumentation where a client can provide an AST fragment to be
- * <em>spliced</em> directly into the AST.
- */
-public class AdvancedInstrumentTest {
-
-    @Test
-    public void testAdvancedInstrumentListener() {
-        // Create a simple addition AST
-        final TruffleRuntime runtime = Truffle.getRuntime();
-        final TestValueNode leftValueNode = new TestValueNode(6);
-        final TestValueNode rightValueNode = new TestValueNode(7);
-        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
-        final TestRootNode rootNode = new TestRootNode(addNode);
-        final CallTarget callTarget1 = runtime.createCallTarget(rootNode);
-
-        // Ensure it executes correctly
-        assertEquals(13, callTarget1.call());
-
-        // Probe the addition node
-        final Probe probe = addNode.probe();
-
-        assertEquals(13, callTarget1.call());
-
-        // Attach a null factory; it never actually attaches a node.
-        final Instrument instrument = Instrument.create(null, new AdvancedInstrumentRootFactory() {
-
-            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
-                return null;
-            }
-        }, null, "test AdvancedInstrument");
-        probe.attach(instrument);
-
-        assertEquals(13, callTarget1.call());
-
-        final TestAdvancedInstrumentCounterRoot counter = new TestAdvancedInstrumentCounterRoot();
-
-        // Attach a factory that splices an execution counter into the AST.
-        probe.attach(Instrument.create(null, new AdvancedInstrumentRootFactory() {
-
-            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
-                return counter;
-            }
-        }, null, "test AdvancedInstrument"));
-        assertEquals(0, counter.getCount());
-
-        assertEquals(13, callTarget1.call());
-
-        assertEquals(1, counter.getCount());
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.instrument;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeFailure.Reason;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageWrapperNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode;
-import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode;
-
-/**
- * <h3>AST Instrumentation</h3>
- *
- * Instrumentation allows the insertion into Truffle ASTs language-specific instances of
- * {@link WrapperNode} that propagate execution events through a {@link Probe} to any instances of
- * {@link Instrument} that might be attached to the particular probe by tools.
- * <ol>
- * <li>Creates a simple add AST</li>
- * <li>Verifies its structure</li>
- * <li>"Probes" the add node by adding a {@link WrapperNode} and associated {@link Probe}</li>
- * <li>Attaches a simple {@link Instrument} to the node via the Probe's {@link ProbeNode}</li>
- * <li>Verifies the structure of the probed AST</li>
- * <li>Verifies the execution of the probed AST</li>
- * <li>Verifies the results observed by the instrument.</li>
- * </ol>
- * To do these tests, several required classes have been implemented in their most basic form, only
- * implementing the methods necessary for the tests to pass, with stubs elsewhere.
- */
-public class InstrumentationTest {
-
-    private static final SyntaxTag ADD_TAG = new SyntaxTag() {
-
-        @Override
-        public String name() {
-            return "Addition";
-        }
-
-        @Override
-        public String getDescription() {
-            return "Test Language Addition Node";
-        }
-    };
-
-    private static final SyntaxTag VALUE_TAG = new SyntaxTag() {
-
-        @Override
-        public String name() {
-            return "Value";
-        }
-
-        @Override
-        public String getDescription() {
-            return "Test Language Value Node";
-        }
-    };
-
-    @Test
-    public void testInstrumentationStructure() {
-        // Create a simple addition AST
-        final TruffleRuntime runtime = Truffle.getRuntime();
-        final TestValueNode leftValueNode = new TestValueNode(6);
-        final TestValueNode rightValueNode = new TestValueNode(7);
-        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
-
-        try {
-            addNode.probe();
-        } catch (ProbeException e) {
-            assertEquals(e.getFailure().getReason(), Reason.NO_PARENT);
-        }
-        final TestRootNode rootNode = new TestRootNode(addNode);
-
-        // Creating a call target sets the parent pointers in this tree and is necessary prior to
-        // checking any parent/child relationships
-        final CallTarget callTarget1 = runtime.createCallTarget(rootNode);
-
-        // Check the tree structure
-        assertEquals(addNode, leftValueNode.getParent());
-        assertEquals(addNode, rightValueNode.getParent());
-        Iterator<Node> iterator = addNode.getChildren().iterator();
-        assertEquals(leftValueNode, iterator.next());
-        assertEquals(rightValueNode, iterator.next());
-        assertFalse(iterator.hasNext());
-        assertEquals(rootNode, addNode.getParent());
-        iterator = rootNode.getChildren().iterator();
-        assertEquals(addNode, iterator.next());
-        assertFalse(iterator.hasNext());
-
-        // Ensure it executes correctly
-        assertEquals(13, callTarget1.call());
-
-        // Probe the addition node
-        addNode.probe();
-
-        // Check the modified tree structure
-        assertEquals(addNode, leftValueNode.getParent());
-        assertEquals(addNode, rightValueNode.getParent());
-        iterator = addNode.getChildren().iterator();
-        assertEquals(leftValueNode, iterator.next());
-        assertEquals(rightValueNode, iterator.next());
-        assertFalse(iterator.hasNext());
-
-        // Ensure there's a WrapperNode correctly inserted into the AST
-        iterator = rootNode.getChildren().iterator();
-        Node wrapperNode = iterator.next();
-        assertTrue(wrapperNode instanceof TestLanguageWrapperNode);
-        assertFalse(iterator.hasNext());
-        assertEquals(rootNode, wrapperNode.getParent());
-
-        // Check that the WrapperNode has both the probe and the wrapped node as children
-        iterator = wrapperNode.getChildren().iterator();
-        assertEquals(addNode, iterator.next());
-        ProbeNode probeNode = (ProbeNode) iterator.next();
-        assertTrue(probeNode.getProbe() != null);
-        assertFalse(iterator.hasNext());
-
-        // Check that you can't probe the WrapperNodes
-        TestLanguageWrapperNode wrapper = (TestLanguageWrapperNode) wrapperNode;
-        try {
-            wrapper.probe();
-            fail();
-        } catch (ProbeException e) {
-            assertEquals(e.getFailure().getReason(), Reason.WRAPPER_NODE);
-        }
-
-        // Check that the "probed" AST still executes correctly
-        assertEquals(13, callTarget1.call());
-    }
-
-    @Test
-    public void testListeners() {
-
-        // Create a simple addition AST
-        final TruffleRuntime runtime = Truffle.getRuntime();
-        final TestValueNode leftValueNode = new TestValueNode(6);
-        final TestValueNode rightValueNode = new TestValueNode(7);
-        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
-        final TestRootNode rootNode = new TestRootNode(addNode);
-
-        // Creating a call target sets the parent pointers in this tree and is necessary prior to
-        // checking any parent/child relationships
-        final CallTarget callTarget = runtime.createCallTarget(rootNode);
-        // Probe the addition node
-        final Probe probe = addNode.probe();
-
-        // Check instrumentation with the simplest kind of counters.
-        // They should all be removed when the check is finished.
-        checkCounters(probe, callTarget, rootNode, new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter());
-
-        // Now try with the more complex flavor of listener
-        checkCounters(probe, callTarget, rootNode, new TestStandardInstrumentCounter(), new TestStandardInstrumentCounter(), new TestStandardInstrumentCounter());
-    }
-
-    private static void checkCounters(Probe probe, CallTarget callTarget, RootNode rootNode, TestCounter counterA, TestCounter counterB, TestCounter counterC) {
-
-        // Attach a counting instrument to the probe
-        counterA.attach(probe);
-
-        // Attach a second counting instrument to the probe
-        counterB.attach(probe);
-
-        // Run it again and check that the two instruments are working
-        assertEquals(13, callTarget.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 1);
-        assertEquals(counterB.leaveCount(), 1);
-
-        // Remove counterA
-        counterA.dispose();
-
-        // Run it again and check that instrument B is still working but not A
-        assertEquals(13, callTarget.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 2);
-        assertEquals(counterB.leaveCount(), 2);
-
-        // Simulate a split by cloning the AST
-        final CallTarget callTarget2 = Truffle.getRuntime().createCallTarget((TestRootNode) rootNode.copy());
-        // Run the clone and check that instrument B is still working but not A
-        assertEquals(13, callTarget2.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 3);
-        assertEquals(counterB.leaveCount(), 3);
-
-        // Run the original and check that instrument B is still working but not A
-        assertEquals(13, callTarget2.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 4);
-        assertEquals(counterB.leaveCount(), 4);
-
-        // Attach a second instrument to the probe
-        counterC.attach(probe);
-
-        // Run the original and check that instruments B,C working but not A
-        assertEquals(13, callTarget.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 5);
-        assertEquals(counterB.leaveCount(), 5);
-        assertEquals(counterC.enterCount(), 1);
-        assertEquals(counterC.leaveCount(), 1);
-
-        // Run the clone and check that instruments B,C working but not A
-        assertEquals(13, callTarget2.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 6);
-        assertEquals(counterB.leaveCount(), 6);
-        assertEquals(counterC.enterCount(), 2);
-        assertEquals(counterC.leaveCount(), 2);
-
-        // Remove instrumentC
-        counterC.dispose();
-
-        // Run the original and check that instrument B working but not A,C
-        assertEquals(13, callTarget.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 7);
-        assertEquals(counterB.leaveCount(), 7);
-        assertEquals(counterC.enterCount(), 2);
-        assertEquals(counterC.leaveCount(), 2);
-
-        // Run the clone and check that instrument B working but not A,C
-        assertEquals(13, callTarget2.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 8);
-        assertEquals(counterB.leaveCount(), 8);
-        assertEquals(counterC.enterCount(), 2);
-        assertEquals(counterC.leaveCount(), 2);
-
-        // Remove instrumentB
-        counterB.dispose();
-
-        // Run both the original and clone, check that no instruments working
-        assertEquals(13, callTarget.call());
-        assertEquals(13, callTarget2.call());
-        assertEquals(counterA.enterCount(), 1);
-        assertEquals(counterA.leaveCount(), 1);
-        assertEquals(counterB.enterCount(), 8);
-        assertEquals(counterB.leaveCount(), 8);
-        assertEquals(counterC.enterCount(), 2);
-        assertEquals(counterC.leaveCount(), 2);
-    }
-
-    @Test
-    public void testTagging() {
-        // Applies appropriate tags
-        final TestASTProber astProber = new TestASTProber();
-        Probe.registerASTProber(astProber);
-
-        // Listens for probes and tags being added
-        final TestProbeListener probeListener = new TestProbeListener();
-        Probe.addProbeListener(probeListener);
-
-        // Counts all entries to all instances of addition nodes
-        final TestMultiCounter additionCounter = new TestMultiCounter();
-
-        // Counts all entries to all instances of value nodes
-        final TestMultiCounter valueCounter = new TestMultiCounter();
-
-        // Create a simple addition AST
-        final TruffleRuntime runtime = Truffle.getRuntime();
-        final TestValueNode leftValueNode = new TestValueNode(6);
-        final TestValueNode rightValueNode = new TestValueNode(7);
-        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
-
-        final TestRootNode rootNode = new TestRootNode(addNode);
-
-        final CallTarget callTarget = runtime.createCallTarget(rootNode);
-
-        // Check that the prober added probes to the tree
-        assertEquals(probeListener.probeCount, 3);
-        assertEquals(probeListener.tagCount, 3);
-
-        assertEquals(Probe.findProbesTaggedAs(ADD_TAG).size(), 1);
-        assertEquals(Probe.findProbesTaggedAs(VALUE_TAG).size(), 2);
-
-        // Check that it executes correctly
-        assertEquals(13, callTarget.call());
-
-        // Dynamically attach a counter for all executions of all Addition nodes
-        for (Probe probe : Probe.findProbesTaggedAs(ADD_TAG)) {
-            additionCounter.attachCounter(probe);
-        }
-        // Dynamically attach a counter for all executions of all Value nodes
-        for (Probe probe : Probe.findProbesTaggedAs(VALUE_TAG)) {
-            valueCounter.attachCounter(probe);
-        }
-
-        // Counters initialized at 0
-        assertEquals(additionCounter.count, 0);
-        assertEquals(valueCounter.count, 0);
-
-        // Execute again
-        assertEquals(13, callTarget.call());
-
-        // There are two value nodes in the AST, but only one addition node
-        assertEquals(additionCounter.count, 1);
-        assertEquals(valueCounter.count, 2);
-
-        Probe.unregisterASTProber(astProber);
-    }
-
-    private interface TestCounter {
-
-        int enterCount();
-
-        int leaveCount();
-
-        void attach(Probe probe);
-
-        void dispose();
-    }
-
-    /**
-     * A counter for the number of times execution enters and leaves a probed AST node.
-     */
-    private class TestSimpleInstrumentCounter implements TestCounter {
-
-        public int enterCount = 0;
-        public int leaveCount = 0;
-        public final Instrument instrument;
-
-        public TestSimpleInstrumentCounter() {
-            this.instrument = Instrument.create(new SimpleInstrumentListener() {
-
-                public void enter(Probe probe) {
-                    enterCount++;
-                }
-
-                public void returnVoid(Probe probe) {
-                    leaveCount++;
-                }
-
-                public void returnValue(Probe probe, Object result) {
-                    leaveCount++;
-                }
-
-                public void returnExceptional(Probe probe, Exception exception) {
-                    leaveCount++;
-                }
-
-            }, "Instrumentation Test Counter");
-        }
-
-        @Override
-        public int enterCount() {
-            return enterCount;
-        }
-
-        @Override
-        public int leaveCount() {
-            return leaveCount;
-        }
-
-        @Override
-        public void attach(Probe probe) {
-            probe.attach(instrument);
-        }
-
-        @Override
-        public void dispose() {
-            instrument.dispose();
-        }
-    }
-
-    /**
-     * A counter for the number of times execution enters and leaves a probed AST node.
-     */
-    private class TestStandardInstrumentCounter implements TestCounter {
-
-        public int enterCount = 0;
-        public int leaveCount = 0;
-        public final Instrument instrument;
-
-        public TestStandardInstrumentCounter() {
-            this.instrument = Instrument.create(new StandardInstrumentListener() {
-
-                public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-                    enterCount++;
-                }
-
-                public void returnVoid(Probe probe, Node node, VirtualFrame vFrame) {
-                    leaveCount++;
-                }
-
-                public void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) {
-                    leaveCount++;
-                }
-
-                public void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
-                    leaveCount++;
-                }
-
-            }, "Instrumentation Test Counter");
-        }
-
-        @Override
-        public int enterCount() {
-            return enterCount;
-        }
-
-        @Override
-        public int leaveCount() {
-            return leaveCount;
-        }
-
-        @Override
-        public void attach(Probe probe) {
-            probe.attach(instrument);
-        }
-
-        @Override
-        public void dispose() {
-            instrument.dispose();
-        }
-    }
-
-    /**
-     * Tags selected nodes on newly constructed ASTs.
-     */
-    private static final class TestASTProber implements NodeVisitor, ASTProber {
-
-        @Override
-        public boolean visit(Node node) {
-            if (node instanceof TestLanguageNode) {
-
-                final TestLanguageNode testNode = (TestLanguageNode) node;
-
-                if (node instanceof TestValueNode) {
-                    testNode.probe().tagAs(VALUE_TAG, null);
-
-                } else if (node instanceof TestAdditionNode) {
-                    testNode.probe().tagAs(ADD_TAG, null);
-
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public void probeAST(Node node) {
-            node.accept(this);
-        }
-    }
-
-    /**
-     * Counts the number of "enter" events at probed nodes using the simplest AST listener.
-     */
-    static final class TestSimpleInstrumentListener extends DefaultSimpleInstrumentListener {
-
-        public int counter = 0;
-
-        @Override
-        public void enter(Probe probe) {
-            counter++;
-        }
-    }
-
-    /**
-     * Counts the number of "enter" events at probed nodes using the AST listener.
-     */
-    static final class TestASTInstrumentListener extends DefaultStandardInstrumentListener {
-
-        public int counter = 0;
-
-        @Override
-        public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-            counter++;
-        }
-    }
-
-    /**
-     * A counter that can count executions at multiple nodes; it attaches a separate instrument at
-     * each Probe, but keeps a total count.
-     */
-    private static final class TestMultiCounter {
-
-        public int count = 0;
-
-        public void attachCounter(Probe probe) {
-
-            // Attach a new instrument for every Probe
-            // where we want to count executions.
-            // it will get copied when ASTs cloned, so
-            // keep the count in this outer class.
-            probe.attach(Instrument.create(new DefaultSimpleInstrumentListener() {
-
-                @Override
-                public void enter(Probe p) {
-                    count++;
-                }
-            }, "Instrumentation Test MultiCounter"));
-        }
-    }
-
-    private static final class TestProbeListener extends DefaultProbeListener {
-
-        public int probeCount = 0;
-        public int tagCount = 0;
-
-        @Override
-        public void newProbeInserted(Probe probe) {
-            probeCount++;
-        }
-
-        @Override
-        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-            tagCount++;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.instrument;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Tests instrumentation where a client can attach a node that gets attached into the AST.
- */
-class InstrumentationTestNodes {
-
-    abstract static class TestLanguageNode extends Node {
-        public abstract Object execute(VirtualFrame vFrame);
-
-        @Override
-        public boolean isInstrumentable() {
-            return true;
-        }
-
-        @Override
-        public WrapperNode createWrapperNode() {
-            return new TestLanguageWrapperNode(this);
-        }
-    }
-
-    @NodeInfo(cost = NodeCost.NONE)
-    static class TestLanguageWrapperNode extends TestLanguageNode implements WrapperNode {
-        @Child private TestLanguageNode child;
-        @Child private ProbeNode probeNode;
-
-        public TestLanguageWrapperNode(TestLanguageNode child) {
-            assert !(child instanceof TestLanguageWrapperNode);
-            this.child = child;
-        }
-
-        @Override
-        public String instrumentationInfo() {
-            return "Wrapper node for testing";
-        }
-
-        @Override
-        public boolean isInstrumentable() {
-            return false;
-        }
-
-        @Override
-        public void insertProbe(ProbeNode newProbeNode) {
-            this.probeNode = newProbeNode;
-        }
-
-        @Override
-        public Probe getProbe() {
-            return probeNode.getProbe();
-        }
-
-        @Override
-        public Node getChild() {
-            return child;
-        }
-
-        @Override
-        public Object execute(VirtualFrame vFrame) {
-            probeNode.enter(child, vFrame);
-            Object result;
-            try {
-                result = child.execute(vFrame);
-                probeNode.returnValue(child, vFrame, result);
-            } catch (KillException e) {
-                throw (e);
-            } catch (Exception e) {
-                probeNode.returnExceptional(child, vFrame, e);
-                throw (e);
-            }
-            return result;
-        }
-    }
-
-    /**
-     * A simple node for our test language to store a value.
-     */
-    static class TestValueNode extends TestLanguageNode {
-        private final int value;
-
-        public TestValueNode(int value) {
-            this.value = value;
-        }
-
-        @Override
-        public Object execute(VirtualFrame vFrame) {
-            return new Integer(this.value);
-        }
-    }
-
-    /**
-     * A node for our test language that adds up two {@link TestValueNode}s.
-     */
-    static class TestAdditionNode extends TestLanguageNode {
-        @Child private TestLanguageNode leftChild;
-        @Child private TestLanguageNode rightChild;
-
-        public TestAdditionNode(TestValueNode leftChild, TestValueNode rightChild) {
-            this.leftChild = insert(leftChild);
-            this.rightChild = insert(rightChild);
-        }
-
-        @Override
-        public Object execute(VirtualFrame vFrame) {
-            return new Integer(((Integer) leftChild.execute(vFrame)).intValue() + ((Integer) rightChild.execute(vFrame)).intValue());
-        }
-    }
-
-    /**
-     * Truffle requires that all guest languages to have a {@link RootNode} which sits atop any AST
-     * of the guest language. This is necessary since creating a {@link CallTarget} is how Truffle
-     * completes an AST. The root nodes serves as our entry point into a program.
-     */
-    static class TestRootNode extends RootNode {
-        @Child private TestLanguageNode body;
-
-        /**
-         * This constructor emulates the global machinery that applies registered probers to every
-         * newly created AST. Global registry is not used, since that would interfere with other
-         * tests run in the same environment.
-         */
-        public TestRootNode(TestLanguageNode body) {
-            super(null);
-            this.body = body;
-        }
-
-        @Override
-        public Object execute(VirtualFrame vFrame) {
-            return body.execute(vFrame);
-        }
-
-        @Override
-        public boolean isCloningAllowed() {
-            return true;
-        }
-
-        @Override
-        public void applyInstrumentation() {
-            Probe.applyASTProbers(body);
-        }
-    }
-
-    static class TestAdvancedInstrumentCounterRoot extends AdvancedInstrumentRoot {
-
-        private long count;
-
-        @Override
-        public Object executeRoot(Node node, VirtualFrame vFrame) {
-            count++;
-            return null;
-        }
-
-        public long getCount() {
-            return count;
-        }
-
-        public String instrumentationInfo() {
-            return null;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/NodeUtilTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class NodeUtilTest {
-
-    @Test
-    public void testRecursiveIterator1() {
-        TestRootNode root = new TestRootNode();
-        root.child0 = new TestNode();
-        root.adoptChildren();
-
-        int count = iterate(NodeUtil.makeRecursiveIterator(root));
-
-        assertThat(count, is(2));
-        assertThat(root.visited, is(0));
-        assertThat(root.child0.visited, is(1));
-    }
-
-    private static int iterate(Iterator<Node> iterator) {
-        int iterationCount = 0;
-        while (iterator.hasNext()) {
-            Node node = iterator.next();
-            if (node == null) {
-                continue;
-            }
-            if (node instanceof TestNode) {
-                ((TestNode) node).visited = iterationCount;
-            } else if (node instanceof TestRootNode) {
-                ((TestRootNode) node).visited = iterationCount;
-            } else {
-                throw new AssertionError();
-            }
-            iterationCount++;
-        }
-        return iterationCount;
-    }
-
-    private static class TestNode extends Node {
-
-        @Child TestNode child0;
-        @Child TestNode child1;
-
-        private int visited;
-
-        public TestNode() {
-        }
-
-    }
-
-    private static class TestRootNode extends RootNode {
-
-        @Child TestNode child0;
-
-        private int visited;
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return null;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Tests optional method for ensuring that a node replacement is type safe. Ordinary node
- * replacement is performed by unsafe assignment of a parent node's child field.
- */
-public class SafeReplaceTest {
-
-    @Test
-    public void testCorrectReplacement() {
-        TestRootNode root = new TestRootNode();
-        final TestNode oldChild = new TestNode();
-        final TestNode newChild = new TestNode();
-        root.child = oldChild;
-        assertFalse(oldChild.isSafelyReplaceableBy(newChild));  // No parent node
-        root.adoptChildren();
-        assertTrue(oldChild.isSafelyReplaceableBy(newChild));   // Now adopted by parent
-        // new node
-        oldChild.replace(newChild);
-        root.execute(null);
-        assertEquals(root.executed, 1);
-        assertEquals(oldChild.executed, 0);
-        assertEquals(newChild.executed, 1);
-    }
-
-    @Test
-    public void testIncorrectReplacement() {
-        TestRootNode root = new TestRootNode();
-        final TestNode oldChild = new TestNode();
-        root.child = oldChild;
-        root.adoptChildren();
-        final TestNode newChild = new TestNode();
-        final TestNode strayChild = new TestNode();
-        assertFalse(strayChild.isSafelyReplaceableBy(newChild)); // Stray not a child of parent
-        final WrongTestNode wrongTypeNewChild = new WrongTestNode();
-        assertFalse(oldChild.isSafelyReplaceableBy(wrongTypeNewChild));
-    }
-
-    private static class TestNode extends Node {
-
-        private int executed;
-
-        public Object execute() {
-            executed++;
-            return null;
-        }
-    }
-
-    private static class TestRootNode extends RootNode {
-
-        @Child TestNode child;
-
-        private int executed;
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            executed++;
-            child.execute();
-            return null;
-        }
-    }
-
-    private static class WrongTestNode extends Node {
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes.serial;
-
-import java.nio.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.serial.*;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithOneChild;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoChilds;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode;
-
-public class PostOrderDeserializerTest {
-
-    private PostOrderDeserializer d;
-    private TestSerializerConstantPool cp;
-
-    @Before
-    public void setUp() {
-        cp = new TestSerializerConstantPool();
-        d = new PostOrderDeserializer(cp);
-    }
-
-    @After
-    public void tearDown() {
-        d = null;
-        cp = null;
-    }
-
-    private Node deserialize(byte[] bytes) {
-        return d.deserialize(bytes, Node.class);
-    }
-
-    @Test
-    public void testNull() {
-        createCP();
-        Node ast = deserialize(createBytes(VariableLengthIntBuffer.NULL));
-        Assert.assertNull(ast);
-    }
-
-    @Test
-    public void testSingleNode() {
-        createCP(EmptyNode.class);
-        Node expectedAst = new EmptyNode();
-        Node ast = deserialize(createBytes(0));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testThreeChilds() {
-        createCP(EmptyNode.class, NodeWithThreeChilds.class);
-        Node expectedAst = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode());
-        Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 0, 1));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testFields() {
-        createCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
-                        (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1);
-        NodeWithFields expectedAst = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE,
-                        Double.MAX_VALUE, Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE);
-        Node ast = deserialize(createBytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testFieldsNull() {
-        createCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D);
-        NodeWithFields expectedAst = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null);
-        int nil = VariableLengthIntBuffer.NULL;
-        Node ast = deserialize(createBytes(0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testNullChilds() {
-        createCP(Node[].class, NodeWithArray.class);
-        Node expectedAst = new NodeWithArray(null);
-        Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 1));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testNChilds() {
-        Node expectedAst = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()});
-        createCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class);
-        Node ast = deserialize(createBytes(0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4));
-
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void test2xNChilds() {
-        Node expectedAst = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")});
-        createCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class);
-        Node ast = deserialize(createBytes(0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9));
-
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testBug0() {
-        Node expectedAst = new NodeWithArray(new Node[]{new NodeWithOneChild(new EmptyNode())});
-
-        createCP(Node[].class, 1, EmptyNode.class, NodeWithOneChild.class, NodeWithArray.class);
-        Node ast = deserialize(createBytes(0, 1, 2, 3, 4));
-        assertAST(expectedAst, ast);
-    }
-
-    @Test
-    public void testBug1() {
-        Node expectedAst = new NodeWithArray(new Node[]{new NodeWithTwoChilds(new EmptyNode(), new EmptyNode())});
-
-        createCP(Node[].class, 1, EmptyNode.class, NodeWithTwoChilds.class, NodeWithArray.class);
-        Node ast = deserialize(createBytes(0, 1, 2, 2, 3, 4));
-        assertAST(expectedAst, ast);
-    }
-
-    private static void assertAST(Node expectedAst, Node actualAst) {
-        if (expectedAst == null) {
-            Assert.assertNull(actualAst);
-            return;
-        }
-
-        expectedAst.adoptChildren();
-
-        Assert.assertNotNull(actualAst);
-        // fields are asserted using the corresponding equals implementation
-        Assert.assertEquals(expectedAst, actualAst);
-
-        Iterable<Node> expectedChildIterator = expectedAst.getChildren();
-        Iterator<Node> actualChildIterator = actualAst.getChildren().iterator();
-        for (Node node : expectedChildIterator) {
-            Assert.assertTrue(actualChildIterator.hasNext());
-            assertAST(node, actualChildIterator.next());
-        }
-        Assert.assertFalse(actualChildIterator.hasNext());
-    }
-
-    private static byte[] createBytes(int... refs) {
-        VariableLengthIntBuffer buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
-        for (int i = 0; i < refs.length; i++) {
-            buf.put(refs[i]);
-        }
-        return buf.getBytes();
-    }
-
-    private void createCP(Object... cpData) {
-        for (int i = 0; i < cpData.length; i++) {
-            Object object = cpData[i];
-
-            cp.putObject(object.getClass(), object);
-
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderSerializerTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes.serial;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.serial.*;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray;
-import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode;
-
-public class PostOrderSerializerTest {
-
-    private PostOrderSerializer s;
-    private TestSerializerConstantPool cp;
-
-    @Before
-    public void setUp() {
-        cp = new TestSerializerConstantPool();
-        s = new PostOrderSerializer(cp);
-    }
-
-    @After
-    public void tearDown() {
-        cp = null;
-        s = null;
-    }
-
-    @Test
-    public void testNull() {
-        Node ast = null;
-        assertBytes(s.serialize(ast), VariableLengthIntBuffer.NULL);
-        assertCP();
-    }
-
-    @Test
-    public void testSingleEmptyNode() {
-        Node ast = new EmptyNode();
-        assertBytes(s.serialize(ast), 0);
-        assertCP(EmptyNode.class);
-    }
-
-    @Test
-    public void testThreeChilds() {
-        Node ast = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode());
-        assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 0, 1);
-        assertCP(EmptyNode.class, NodeWithThreeChilds.class);
-    }
-
-    @Test
-    public void testFields() {
-        NodeWithFields ast = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
-                        Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE);
-        assertBytes(s.serialize(ast), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10);
-        assertCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
-                        (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1);
-    }
-
-    @Test
-    public void testFieldsNull() {
-        NodeWithFields ast = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null);
-        int nil = VariableLengthIntBuffer.NULL;
-        assertBytes(s.serialize(ast), 0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil);
-        assertCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D);
-    }
-
-    @Test
-    public void testNChilds() {
-        Node ast = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()});
-        assertBytes(s.serialize(ast), 0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4);
-        assertCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class);
-    }
-
-    @Test
-    public void testNullChilds() {
-        Node ast = new NodeWithArray(null);
-        assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 1);
-        assertCP(Node[].class, NodeWithArray.class);
-    }
-
-    @Test
-    public void test2xNChilds() {
-        Node ast = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")});
-        assertBytes(s.serialize(ast), 0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9);
-        assertCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class);
-    }
-
-    private static void assertBytes(byte[] actualBytes, int... expectedIndexes) {
-        VariableLengthIntBuffer buf = new VariableLengthIntBuffer(actualBytes);
-        for (int i = 0; i < expectedIndexes.length; i++) {
-            Assert.assertTrue("Unexpected EOF " + i, buf.hasRemaining());
-            Assert.assertEquals("Index at pos " + i + ".", expectedIndexes[i], buf.get());
-        }
-        Assert.assertFalse(buf.hasRemaining());
-    }
-
-    private void assertCP(Object... object) {
-        for (int i = 0; i < object.length; i++) {
-            Object cpvalue = object[i];
-            Assert.assertNotNull("CP at index " + i, cpvalue);
-            Assert.assertEquals("CP at index " + i, cpvalue, cp.getObject(cpvalue.getClass(), i));
-        }
-        Assert.assertEquals(object.length, cp.getIndex());
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes.serial;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-final class TestNodes {
-
-    private TestNodes() {
-    }
-
-    static class StringNode extends Node {
-
-        private final String name;
-
-        public StringNode(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(name);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            } else if (obj.getClass() != getClass()) {
-                return false;
-            } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) {
-                return false;
-            } else if (!Objects.equals(name, ((StringNode) obj).name)) {
-                return false;
-            }
-            return true;
-        }
-    }
-
-    static class EmptyNode extends Node {
-
-        @Override
-        public int hashCode() {
-            return super.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == null) {
-                return false;
-            } else if (obj.getClass() != getClass()) {
-                return false;
-            } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) {
-                return false;
-            }
-            return true;
-        }
-    }
-
-    static class NodeWithOneChild extends EmptyNode {
-
-        @Child Node child;
-
-        public NodeWithOneChild(Node child) {
-            this.child = child;
-        }
-
-    }
-
-    static class NodeWithTwoChilds extends EmptyNode {
-
-        @Child Node child1;
-        @Child Node child2;
-
-        public NodeWithTwoChilds(Node child1, Node child2) {
-            this.child1 = child1;
-            this.child2 = child2;
-        }
-
-    }
-
-    static class NodeWithThreeChilds extends EmptyNode {
-
-        @Child Node child1;
-        @Child Node child2;
-        @Child Node child3;
-
-        public NodeWithThreeChilds(Node child1, Node child2, Node child3) {
-            this.child1 = child1;
-            this.child2 = child2;
-            this.child3 = child3;
-        }
-
-    }
-
-    static class NodeWithArray extends EmptyNode {
-
-        @Children private final Node[] childNodes;
-
-        NodeWithArray(Node[] children) {
-            this.childNodes = children;
-        }
-
-        Node[] getChildNodes() {
-            return childNodes;
-        }
-    }
-
-    static class NodeWithTwoArray extends EmptyNode {
-
-        @Children private final Node[] childNodes1;
-        @Children private final Node[] childNodes2;
-
-        NodeWithTwoArray(Node[] childs1, Node[] childs2) {
-            this.childNodes1 = childs1;
-            this.childNodes2 = childs2;
-        }
-
-        Node[] getChildNodes1() {
-            return childNodes1;
-        }
-
-        Node[] getChildNodes2() {
-            return childNodes2;
-        }
-    }
-
-    static class NodeWithFields extends EmptyNode {
-
-        String stringField;
-        int integerField;
-        Integer integerObjectField;
-        long longField;
-        Long longObjectField;
-        float floatField;
-        Float floatObjectField;
-        double doubleField;
-        Double doubleObjectField;
-        char charField;
-        Character charObjectField;
-        short shortField;
-        Short shortObjecField;
-        byte byteField;
-        Byte byteObjectField;
-        boolean booleanField;
-        Boolean booleanObjectfield;
-
-        public NodeWithFields(String stringField, int integerField, Integer integerObjectField, long longField, Long longObjectField, float floatField, Float floatObjectField, double doubleField,
-                        Double doubleObjectField, char charField, Character charObjectField, short shortField, Short shortObjecField, byte byteField, Byte byteObjectField, boolean booleanField,
-                        Boolean booleanObjectfield) {
-            this.stringField = stringField;
-            this.integerField = integerField;
-            this.integerObjectField = integerObjectField;
-            this.longField = longField;
-            this.longObjectField = longObjectField;
-            this.floatField = floatField;
-            this.floatObjectField = floatObjectField;
-            this.doubleField = doubleField;
-            this.doubleObjectField = doubleObjectField;
-            this.charField = charField;
-            this.charObjectField = charObjectField;
-            this.shortField = shortField;
-            this.shortObjecField = shortObjecField;
-            this.byteField = byteField;
-            this.byteObjectField = byteObjectField;
-            this.booleanField = booleanField;
-            this.booleanObjectfield = booleanObjectfield;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField,
-                            shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj.getClass() != getClass()) {
-                return false;
-            }
-            NodeWithFields o = (NodeWithFields) obj;
-            return Objects.deepEquals(fieldArray(), o.fieldArray());
-        }
-
-        private Object[] fieldArray() {
-            return array(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField,
-                            shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield);
-        }
-
-        private static Object[] array(Object... values) {
-            return values;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestSerializerConstantPool.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes.serial;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.serial.*;
-
-class TestSerializerConstantPool implements SerializerConstantPool {
-
-    private final Map<Integer, Object> int2object = new HashMap<>();
-    private final Map<Object, Integer> object2int = new HashMap<>();
-
-    private int index;
-
-    public void setIndex(int index) {
-        this.index = index;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    @Override
-    public double getDouble(int cpi) {
-        return (Double) int2object.get(cpi);
-    }
-
-    @Override
-    public float getFloat(int cpi) {
-        return (Float) int2object.get(cpi);
-    }
-
-    @Override
-    public Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException {
-        return int2object.get(cpi);
-    }
-
-    @Override
-    public int putDouble(double value) {
-        return put(value);
-    }
-
-    public int putFloat(float value) {
-        return put(value);
-    }
-
-    public int putObject(java.lang.Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException {
-        return put(value);
-    }
-
-    @Override
-    public int putClass(Class<?> clazz) {
-        return put(clazz);
-    }
-
-    private int put(Object o) {
-        Integer currentIndex = object2int.get(o);
-        if (currentIndex == null) {
-            int2object.put(index, o);
-            object2int.put(o, index);
-            return index++;
-        } else {
-            return currentIndex;
-        }
-    }
-
-    @Override
-    public Class<?> getClass(int idx) {
-        return (Class<?>) int2object.get(idx);
-    }
-
-    @Override
-    public int putInt(int constant) {
-        return put(constant);
-    }
-
-    @Override
-    public int getInt(int idx) {
-        return (Integer) int2object.get(idx);
-    }
-
-    @Override
-    public long getLong(int idx) {
-        return (Long) int2object.get(idx);
-    }
-
-    @Override
-    public int putLong(long value) {
-        return put(value);
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/VariableLengthIntBufferTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.nodes.serial;
-
-import java.nio.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.nodes.serial.*;
-
-public class VariableLengthIntBufferTest {
-
-    private VariableLengthIntBuffer buf;
-
-    @Before
-    public void setUp() {
-        buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
-    }
-
-    @After
-    public void tearDown() {
-        buf = null;
-    }
-
-    @Test
-    public void testPutNull() {
-        buf.put(VariableLengthIntBuffer.NULL);
-        assertBytes(0xFF);
-    }
-
-    @Test
-    public void testPutByteCornerCase0() {
-        buf.put(0x00); // 0
-        assertBytes(0x00);
-    }
-
-    @Test
-    public void testPutByteCornerCase1() {
-        buf.put(0x7F); // 127
-        assertBytes(0x7F);
-    }
-
-    @Test
-    public void testPutByteCornerCase2() {
-        buf.put(0x3FFF_FFFF);
-        assertBytes(0xBF, 0xFF, 0xFF, 0xFF);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testPutByteCornerCase3() {
-        buf.put(0x4000_0000); // out of encodeable
-    }
-
-    @Test
-    public void testGetNull() {
-        create(0xFF);
-        assertGet(VariableLengthIntBuffer.NULL);
-    }
-
-    @Test
-    public void testGetCornerCase0() {
-        create(0x00);
-        assertGet(0x00);
-    }
-
-    @Test
-    public void testGetCornerCase1() {
-        create(0x7F);
-        assertGet(0x7F);
-    }
-
-    @Test
-    public void testGetCornerCase2() {
-        create(0xBF, 0xFF, 0xFF, 0xFF);
-        assertGet(0x3FFF_FFFF);
-    }
-
-    @Test(expected = AssertionError.class)
-    public void testGetCornerCase3() {
-        create(0xFF, 0xFF, 0xFF, 0xFF);
-        assertGet(0x0);
-    }
-
-    private void create(int... bytes) {
-        byte[] convBytes = new byte[bytes.length];
-        for (int i = 0; i < bytes.length; i++) {
-            convBytes[i] = (byte) bytes[i];
-        }
-        buf = new VariableLengthIntBuffer(convBytes);
-    }
-
-    private void assertGet(int expected) {
-        Assert.assertEquals(expected, buf.get());
-    }
-
-    private void assertBytes(int... expectedBytes) {
-        byte[] actualBytes = buf.getBytes();
-        Assert.assertEquals(expectedBytes.length, actualBytes.length);
-        for (int i = 0; i < expectedBytes.length; i++) {
-            Assert.assertTrue(actualBytes[i] == (byte) expectedBytes[i]);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * <p>This package contains basic tests of the Truffle API and serves at the same
- * time as an introduction to the Truffle API for language implementors. Every test gives an example on how to use the construct explained in the class description.</p>
- *
- * <p>
- * Truffle is a language implementation framework. A guest language method is represented as a tree of executable nodes.
- * The framework provides mechanisms for those trees to call each other. Additionally it contains dedicated data structures for storing data local to a tree invocation.
- * </p>
- *
- * <p>
- * This introduction to Truffle contains items in the following recommended order:
- *
- * <ul>
- * <li>How to get access to the Truffle runtime? {@link com.oracle.truffle.api.test.TruffleRuntimeTest}</li>
- * <li>How to create a root node? {@link com.oracle.truffle.api.test.RootNodeTest}</li>
- * <li>How to create a child node and link it with its parent? {@link com.oracle.truffle.api.test.ChildNodeTest}</li>
- * <li>How to create an array of child nodes? {@link com.oracle.truffle.api.test.ChildrenNodesTest}</li>
- * <li>Why are final fields in node classes important? {@link com.oracle.truffle.api.test.FinalFieldTest}</li>
- * <li>How to replace one node with another node and what for? {@link com.oracle.truffle.api.test.ReplaceTest}</li>
- * <li>How to let one Truffle tree invoke another one? {@link com.oracle.truffle.api.test.CallTest}</li>
- * <li>How to pass arguments when executing a tree? {@link com.oracle.truffle.api.test.ArgumentsTest}</li>
- * <li>How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}</li>
- * <li>How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}</li>
- * <li>How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}</li>
- * <li>How to "instrument" an AST with nodes that can provide access to runtime state from external tools {@link com.oracle.truffle.api.test.instrument.InstrumentationTest}</li>
- * </ul>
- *
- *
- */
-package com.oracle.truffle.api.test;
-
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/BytesSourceSectionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.source;
-
-import static org.junit.Assert.*;
-
-import java.nio.charset.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class BytesSourceSectionTest {
-
-    @Test
-    public void testSectionsFromLineNumberASCII() {
-        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.US_ASCII);
-        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
-        assertEquals("foo", source.createSection("identifier", 1).getCode());
-        assertEquals("bar", source.createSection("identifier", 2).getCode());
-        assertEquals("baz", source.createSection("identifier", 3).getCode());
-    }
-
-    @Test
-    public void testSectionsFromOffsetsASCII() {
-        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.US_ASCII);
-        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
-        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
-        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
-        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
-    }
-
-    @Test
-    public void testOffset() {
-        final byte[] bytes = "xxxfoo\nbar\nbaz\nxxx".getBytes(StandardCharsets.US_ASCII);
-        final Source source = Source.fromBytes(bytes, 3, bytes.length - 6, "description", new BytesDecoder.UTF8BytesDecoder());
-        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
-        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
-        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceSectionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.source;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SourceSectionTest {
-
-    private final Source emptySource = Source.fromText("", null);
-
-    private final Source emptyLineSource = Source.fromText("\n", null);
-
-    private final Source shortSource = Source.fromText("01", null);
-
-    private final Source longSource = Source.fromText("01234\n67\n9\n", null);
-
-    public void emptySourceTest0() {
-        SourceSection section = emptySource.createSection("test", 0, 0);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "");
-    }
-
-    @Test
-    public void emptyLineTest0() {
-        SourceSection section = emptyLineSource.createSection("test", 0, 0);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "");
-        assertEquals(section.getCharIndex(), 0);
-        assertEquals(section.getCharLength(), 0);
-        assertEquals(section.getStartLine(), 1);
-        assertEquals(section.getStartColumn(), 1);
-    }
-
-    @Ignore
-    @Test
-    public void emptyLineTest0a() {
-        SourceSection section = emptyLineSource.createSection("test", 0, 0);
-        assertEquals(section.getEndLine(), 1);
-        assertEquals(section.getEndColumn(), 1);
-    }
-
-    @Test
-    public void emptyLineTest1() {
-        SourceSection section = emptyLineSource.createSection("test", 0, 1);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "\n");
-        assertEquals(section.getCharIndex(), 0);
-        assertEquals(section.getCharLength(), 1);
-        assertEquals(section.getStartLine(), 1);
-        assertEquals(section.getStartColumn(), 1);
-        assertEquals(section.getEndLine(), 1);
-        assertEquals(section.getEndColumn(), 1);
-    }
-
-    @Ignore
-    @Test
-    public void emptyLineTest2() {
-        SourceSection section = emptyLineSource.createSection("test", 1, 0);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "");
-        assertEquals(section.getCharIndex(), 1);
-        assertEquals(section.getCharLength(), 0);
-        assertEquals(section.getStartLine(), 1);
-        assertEquals(section.getStartColumn(), 1);
-        assertEquals(section.getEndLine(), 1);
-        assertEquals(section.getEndColumn(), 1);
-    }
-
-    @Test
-    public void emptySectionTest2() {
-        SourceSection section = shortSource.createSection("test", 0, 0);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "");
-    }
-
-    @Test
-    public void emptySectionTest3() {
-        SourceSection section = longSource.createSection("test", 0, 0);
-        assertNotNull(section);
-        assertEquals(section.getCode(), "");
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.source;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SourceTagTest {
-
-    @Test
-    public void sourceTagTest() {
-
-        // Private tag
-        final SourceTag testTag = new SourceTag() {
-
-            public String name() {
-                return null;
-            }
-
-            public String getDescription() {
-                return null;
-            }
-        };
-
-        // No sources exist with the private tag
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
-
-        // Create a new source
-        final Source source = Source.fromText("test1 source", "test1 source");
-
-        // Initially has only the default tag
-        assertEquals(source.getSourceTags().size(), 1);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertFalse(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
-
-        // Add a private tag
-        source.tagAs(testTag);
-
-        // Now there are exactly two tags
-        assertEquals(source.getSourceTags().size(), 2);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertTrue(source.getSourceTags().contains(testTag));
-        assertTrue(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
-        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
-
-        // Add the private tag again
-        source.tagAs(testTag);
-
-        // Nothing has changed
-        assertEquals(source.getSourceTags().size(), 2);
-
-        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
-        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
-        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
-
-        assertTrue(source.getSourceTags().contains(testTag));
-        assertTrue(source.isTaggedAs(testTag));
-        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
-        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
-    }
-
-    @Test
-    public void sourceListenerTest() {
-
-        // Private tag
-        final SourceTag testTag = new SourceTag() {
-
-            public String name() {
-                return null;
-            }
-
-            public String getDescription() {
-                return null;
-            }
-        };
-
-        final int[] newSourceEvents = {0};
-        final Source[] newSource = {null};
-
-        final int[] newTagEvents = {0};
-        final Source[] taggedSource = {null};
-        final SourceTag[] newTag = {null};
-
-        Source.addSourceListener(new SourceListener() {
-
-            public void sourceCreated(Source source) {
-                newSourceEvents[0] = newSourceEvents[0] + 1;
-                newSource[0] = source;
-            }
-
-            public void sourceTaggedAs(Source source, SourceTag tag) {
-                newTagEvents[0] = newTagEvents[0] + 1;
-                taggedSource[0] = source;
-                newTag[0] = tag;
-            }
-        });
-
-        // New source has a default tag applied.
-        // Get one event for the new source, another one when it gets tagged
-        final Source source = Source.fromText("testSource", "testSource");
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], source);
-        assertEquals(newTagEvents[0], 1);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], Source.Tags.FROM_LITERAL);
-
-        // reset
-        newSource[0] = null;
-        taggedSource[0] = null;
-        newTag[0] = null;
-
-        // Add a tag; only get one event (the new tag)
-        source.tagAs(testTag);
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], null);
-        assertEquals(newTagEvents[0], 2);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], testTag);
-
-        // Add the same tag; no events, and nothing changes.
-        source.tagAs(testTag);
-        assertEquals(newSourceEvents[0], 1);
-        assertEquals(newSource[0], null);
-        assertEquals(newTagEvents[0], 2);
-        assertEquals(taggedSource[0], source);
-        assertEquals(newTag[0], testTag);
-
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.source;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.source.*;
-
-public class SourceTextTest {
-
-    private final Source emptySource = Source.fromText("", null);
-
-    private final Source emptyLineSource = Source.fromText("\n", null);
-
-    private final Source shortSource = Source.fromText("01", null);
-
-    private final Source longSource = Source.fromText("01234\n67\n9\n", null);
-
-    @Test
-    public void emptyTextTest0() {
-        assertEquals(emptySource.getLineCount(), 0);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest1() {
-        emptySource.getLineNumber(0);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest2() {
-        emptySource.getColumnNumber(0);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest3() {
-        emptySource.getLineNumber(-1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest4() {
-        emptySource.getLineStartOffset(0);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest5() {
-        emptySource.getLineStartOffset(1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyTextTest6() {
-        emptySource.getLineLength(1);
-    }
-
-    @Test
-    public void emptyLineTest0() {
-        assertEquals(emptyLineSource.getLineCount(), 1);
-        assertEquals(emptyLineSource.getLineNumber(0), 1);
-        assertEquals(emptyLineSource.getLineStartOffset(1), 0);
-        assertEquals(emptyLineSource.getColumnNumber(0), 1);
-        assertEquals(emptyLineSource.getLineLength(1), 0);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyLineTest1() {
-        emptyLineSource.getLineNumber(1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyLineTest2() {
-        emptyLineSource.getLineStartOffset(2);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyLineTest3() {
-        emptyLineSource.getColumnNumber(1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyLineTest4() {
-        emptyLineSource.getLineLength(2);
-    }
-
-    @Test
-    public void shortTextTest0() {
-
-        assertEquals(shortSource.getLineCount(), 1);
-
-        assertEquals(shortSource.getLineNumber(0), 1);
-        assertEquals(shortSource.getLineStartOffset(1), 0);
-        assertEquals(shortSource.getColumnNumber(0), 1);
-
-        assertEquals(shortSource.getLineNumber(1), 1);
-        assertEquals(shortSource.getColumnNumber(1), 2);
-
-        assertEquals(shortSource.getLineLength(1), 2);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest1() {
-        shortSource.getLineNumber(-1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest2() {
-        shortSource.getColumnNumber(-1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest3() {
-        shortSource.getLineNumber(2);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest4() {
-        shortSource.getColumnNumber(2);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest5() {
-        shortSource.getLineLength(2);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void shortTextTest6() {
-        shortSource.getLineLength(2);
-    }
-
-    @Test
-    public void longTextTest0() {
-
-        assertEquals(longSource.getLineCount(), 3);
-
-        assertEquals(longSource.getLineNumber(0), 1);
-        assertEquals(longSource.getLineStartOffset(1), 0);
-        assertEquals(longSource.getColumnNumber(0), 1);
-
-        assertEquals(longSource.getLineNumber(4), 1);
-        assertEquals(longSource.getColumnNumber(4), 5);
-
-        assertEquals(longSource.getLineNumber(5), 1); // newline
-        assertEquals(longSource.getColumnNumber(5), 6); // newline
-        assertEquals(longSource.getLineLength(1), 5);
-
-        assertEquals(longSource.getLineNumber(6), 2);
-        assertEquals(longSource.getLineStartOffset(2), 6);
-        assertEquals(longSource.getColumnNumber(6), 1);
-
-        assertEquals(longSource.getLineNumber(7), 2);
-        assertEquals(longSource.getColumnNumber(7), 2);
-
-        assertEquals(longSource.getLineNumber(8), 2); // newline
-        assertEquals(longSource.getLineNumber(8), 2); // newline
-        assertEquals(longSource.getLineLength(2), 2);
-
-        assertEquals(longSource.getLineNumber(9), 3);
-        assertEquals(longSource.getLineStartOffset(3), 9);
-        assertEquals(longSource.getColumnNumber(9), 1);
-
-        assertEquals(longSource.getLineNumber(10), 3); // newline
-        assertEquals(longSource.getColumnNumber(10), 2); // newline
-        assertEquals(longSource.getLineLength(3), 1);
-
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void longTextTest1() {
-        longSource.getLineNumber(11);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void longTextTest2() {
-        longSource.getColumnNumber(11);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void longTextTest3() {
-        longSource.getLineStartOffset(4);
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-public class AlwaysValidAssumptionTest {
-
-    @Test
-    public void testCheck() throws InvalidAssumptionException {
-        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
-        assumption.check();
-    }
-
-    @Test
-    public void testIsValid() {
-        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
-        assertTrue(assumption.isValid());
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testCannotInvalidate() {
-        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
-        assumption.invalidate();
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-public class AssumedValueTest {
-
-    @Test
-    public void testGet() {
-        final AssumedValue<String> assumedValue = new AssumedValue<>("assumed-value", "1");
-        assertEquals("1", assumedValue.get());
-    }
-
-    @Test
-    public void testSet() {
-        final AssumedValue<String> assumedValue = new AssumedValue<>("assumed-value", "1");
-        assertEquals("1", assumedValue.get());
-        assumedValue.set("2");
-        assertEquals("2", assumedValue.get());
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-@RunWith(Theories.class)
-public class BinaryConditionProfileTest {
-
-    @DataPoints public static boolean[] data = new boolean[]{true, false};
-
-    private BinaryConditionProfile profile;
-
-    @Before
-    public void create() {
-        profile = (BinaryConditionProfile) ConditionProfile.createBinaryProfile();
-    }
-
-    @Test
-    public void testInitial() {
-        assertThat(profile.wasTrue(), is(false));
-        assertThat(profile.wasFalse(), is(false));
-    }
-
-    @Theory
-    public void testProfileOne(boolean value) {
-        boolean result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertThat(profile.wasTrue(), is(value));
-        assertThat(profile.wasFalse(), is(!value));
-    }
-
-    @Theory
-    public void testProfileTwo(boolean value0, boolean value1) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(profile.wasTrue(), is(value0 || value1));
-        assertThat(profile.wasFalse(), is(!value0 || !value1));
-    }
-
-    @Theory
-    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-        boolean result2 = profile.profile(value2);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(result2, is(value2));
-        assertThat(profile.wasTrue(), is(value0 || value1 || value2));
-        assertThat(profile.wasFalse(), is(!value0 || !value1 || !value2));
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-public class BranchProfileTest {
-
-    @Test
-    public void testEnter() {
-        BranchProfile profile = BranchProfile.create();
-        profile.enter();
-        profile.enter();
-    }
-
-    @Test
-    public void testToString() {
-        BranchProfile profile = BranchProfile.create();
-        assertTrue(profile.toString().contains(profile.getClass().getSimpleName()));
-        assertTrue(profile.toString().contains("not-visited"));
-        assertTrue(profile.toString().contains(Integer.toHexString(profile.hashCode())));
-        profile.enter();
-        assertTrue(profile.toString().contains(profile.getClass().getSimpleName()));
-        assertTrue(profile.toString().contains("visited"));
-        assertTrue(profile.toString().contains(Integer.toHexString(profile.hashCode())));
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-@RunWith(Theories.class)
-public class CountingConditionProfileTest {
-
-    @DataPoints public static boolean[] data = new boolean[]{true, false};
-
-    private CountingConditionProfile profile;
-
-    @Before
-    public void create() {
-        profile = (CountingConditionProfile) ConditionProfile.createCountingProfile();
-    }
-
-    @Test
-    public void testInitial() {
-        assertThat(profile.getTrueCount(), is(0));
-        assertThat(profile.getFalseCount(), is(0));
-    }
-
-    @Theory
-    public void testProfileOne(boolean value) {
-        boolean result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertThat(profile.getTrueCount(), is(value ? 1 : 0));
-        assertThat(profile.getFalseCount(), is(!value ? 1 : 0));
-    }
-
-    @Theory
-    public void testProfileTwo(boolean value0, boolean value1) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0)));
-        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0)));
-    }
-
-    @Theory
-    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-        boolean result2 = profile.profile(value2);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(result2, is(value2));
-        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0) + (value2 ? 1 : 0)));
-        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0) + (!value2 ? 1 : 0)));
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.utilities.*;
-
-public class CyclicAssumptionTest {
-
-    @Test
-    public void testIsValid() {
-        final CyclicAssumption assumption = new CyclicAssumption("cyclic-assumption");
-        assertTrue(assumption.getAssumption().isValid());
-    }
-
-    @Test
-    public void testInvalidate() {
-        final CyclicAssumption cyclicAssumption = new CyclicAssumption("cyclic-assumption");
-
-        final Assumption firstAssumption = cyclicAssumption.getAssumption();
-        assertEquals("cyclic-assumption", firstAssumption.getName());
-        assertTrue(firstAssumption.isValid());
-
-        cyclicAssumption.invalidate();
-
-        assertFalse(firstAssumption.isValid());
-
-        final Assumption secondAssumption = cyclicAssumption.getAssumption();
-        assertEquals("cyclic-assumption", secondAssumption.getName());
-        assertTrue(secondAssumption.isValid());
-
-        cyclicAssumption.invalidate();
-
-        assertFalse(firstAssumption.isValid());
-        assertFalse(secondAssumption.isValid());
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-@RunWith(Theories.class)
-public class ExactClassValueProfileTest {
-
-    @DataPoint public static final String O1 = new String();
-    @DataPoint public static final String O2 = new String();
-    @DataPoint public static final Object O3 = new Object();
-    @DataPoint public static final Integer O4 = new Integer(1);
-    @DataPoint public static final Integer O5 = null;
-
-    private ExactClassValueProfile profile;
-
-    @Before
-    public void create() {
-        profile = (ExactClassValueProfile) ValueProfile.createClassProfile();
-    }
-
-    @Test
-    public void testInitial() {
-        assertThat(profile.isGeneric(), is(false));
-        assertThat(profile.isUninitialized(), is(true));
-        assertNull(profile.getCachedClass());
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOne(Object value) {
-        Object result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedClass(), expectedClass(value));
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwo(Object value0, Object value1) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-
-        Object expectedClass = expectedClass(value0) == expectedClass(value1) ? expectedClass(value0) : Object.class;
-
-        assertEquals(profile.getCachedClass(), expectedClass);
-        assertThat(profile.isUninitialized(), is(false));
-        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThree(Object value0, Object value1, Object value2) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-        Object result2 = profile.profile(value2);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(result2, is(value2));
-
-        Object expectedClass = expectedClass(value0) == expectedClass(value1) && expectedClass(value1) == expectedClass(value2) ? expectedClass(value0) : Object.class;
-
-        assertEquals(profile.getCachedClass(), expectedClass);
-        assertThat(profile.isUninitialized(), is(false));
-        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
-        profile.toString(); // test that it is not crashing
-    }
-
-    private static Class<?> expectedClass(Object value) {
-        return value == null ? Object.class : value.getClass();
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-@RunWith(Theories.class)
-public class IdentityValueProfileTest {
-
-    @DataPoint public static final String O1 = new String();
-    @DataPoint public static final String O2 = O1;
-    @DataPoint public static final Object O3 = new Object();
-    @DataPoint public static final Integer O4 = new Integer(1);
-    @DataPoint public static final Integer O5 = null;
-
-    private IdentityValueProfile profile;
-
-    @Before
-    public void create() {
-        profile = (IdentityValueProfile) ValueProfile.createIdentityProfile();
-    }
-
-    @Test
-    public void testInitial() {
-        assertThat(profile.isGeneric(), is(false));
-        assertThat(profile.isUninitialized(), is(true));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOne(Object value) {
-        Object result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwo(Object value0, Object value1) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-
-        if (value0 == value1) {
-            assertThat(profile.getCachedValue(), is(value0));
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThree(Object value0, Object value1, Object value2) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-        Object result2 = profile.profile(value2);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(result2, is(value2));
-
-        if (value0 == value1 && value1 == value2) {
-            assertThat(profile.getCachedValue(), is(value0));
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/NeverValidAssumptionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-public class NeverValidAssumptionTest {
-
-    @Test
-    public void testCheck() {
-        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
-
-        try {
-            assumption.check();
-            fail();
-        } catch (InvalidAssumptionException e) {
-        } catch (Exception e) {
-            fail();
-        }
-    }
-
-    @Test
-    public void testIsValid() {
-        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
-        assertFalse(assumption.isValid());
-    }
-
-    @Test
-    public void testInvalidateDoesNothing() {
-        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
-        assumption.invalidate();
-        assumption.invalidate();
-        assumption.invalidate();
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/PrimitiveValueProfileTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,945 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-import org.junit.experimental.theories.*;
-import org.junit.runner.*;
-
-import com.oracle.truffle.api.utilities.*;
-
-@RunWith(Theories.class)
-public class PrimitiveValueProfileTest {
-
-    @DataPoint public static final String O1 = new String();
-    @DataPoint public static final String O2 = O1;
-    @DataPoint public static final Object O3 = new Object();
-    @DataPoint public static final Object O4 = null;
-
-    @DataPoint public static final byte B1 = Byte.MIN_VALUE;
-    @DataPoint public static final byte B2 = 0;
-    @DataPoint public static final byte B3 = 14;
-    @DataPoint public static final byte B4 = Byte.MAX_VALUE;
-
-    @DataPoint public static final short S1 = Short.MIN_VALUE;
-    @DataPoint public static final short S2 = 0;
-    @DataPoint public static final short S3 = 14;
-    @DataPoint public static final short S4 = Short.MAX_VALUE;
-
-    @DataPoint public static final int I1 = Integer.MIN_VALUE;
-    @DataPoint public static final int I2 = 0;
-    @DataPoint public static final int I3 = 14;
-    @DataPoint public static final int I4 = Integer.MAX_VALUE;
-
-    @DataPoint public static final long L1 = Long.MIN_VALUE;
-    @DataPoint public static final long L2 = 0;
-    @DataPoint public static final long L3 = 14;
-    @DataPoint public static final long L4 = Long.MAX_VALUE;
-
-    @DataPoint public static final float F1 = Float.MIN_VALUE;
-    @DataPoint public static final float F2 = -0.0f;
-    @DataPoint public static final float F3 = +0.0f;
-    @DataPoint public static final float F4 = 14.5f;
-    @DataPoint public static final float F5 = Float.MAX_VALUE;
-
-    @DataPoint public static final double D1 = Double.MIN_VALUE;
-    @DataPoint public static final double D2 = -0.0;
-    @DataPoint public static final double D3 = +0.0;
-    @DataPoint public static final double D4 = 14.5;
-    @DataPoint public static final double D5 = Double.MAX_VALUE;
-
-    @DataPoint public static final boolean T1 = false;
-    @DataPoint public static final boolean T2 = true;
-
-    @DataPoint public static final char C1 = Character.MIN_VALUE;
-    @DataPoint public static final char C2 = 0;
-    @DataPoint public static final char C3 = 14;
-    @DataPoint public static final char C4 = Character.MAX_VALUE;
-
-    private static final float FLOAT_DELTA = 0.00001f;
-    private static final double DOUBLE_DELTA = 0.00001;
-
-    private PrimitiveValueProfile profile;
-
-    @Before
-    public void create() {
-        profile = ValueProfile.createPrimitiveProfile();
-    }
-
-    @Test
-    public void testInitial() {
-        assertThat(profile.isGeneric(), is(false));
-        assertThat(profile.isUninitialized(), is(true));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneObject(Object value) {
-        Object result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoObject(Object value0, Object value1) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-
-        if (value0 == value1) {
-            assertThat(profile.getCachedValue(), is(value0));
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeObject(Object value0, Object value1, Object value2) {
-        Object result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-        Object result2 = profile.profile(value2);
-
-        assertThat(result0, is(value0));
-        assertThat(result1, is(value1));
-        assertThat(result2, is(value2));
-
-        if (value0 == value1 && value1 == value2) {
-            assertThat(profile.getCachedValue(), is(value0));
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneByte(byte value) {
-        byte result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoByte(byte value0, byte value1) {
-        byte result0 = profile.profile(value0);
-        byte result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Byte);
-            assertEquals((byte) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeByte(byte value0, byte value1, byte value2) {
-        byte result0 = profile.profile(value0);
-        byte result1 = profile.profile(value1);
-        byte result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Byte);
-            assertEquals((byte) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneShort(short value) {
-        short result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoShort(short value0, short value1) {
-        short result0 = profile.profile(value0);
-        short result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Short);
-            assertEquals((short) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeShort(short value0, short value1, short value2) {
-        short result0 = profile.profile(value0);
-        short result1 = profile.profile(value1);
-        short result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Short);
-            assertEquals((short) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneInteger(int value) {
-        int result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoInteger(int value0, int value1) {
-        int result0 = profile.profile(value0);
-        int result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Integer);
-            assertEquals((int) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeInteger(int value0, int value1, int value2) {
-        int result0 = profile.profile(value0);
-        int result1 = profile.profile(value1);
-        int result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Integer);
-            assertEquals((int) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneLong(long value) {
-        long result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoLong(long value0, long value1) {
-        long result0 = profile.profile(value0);
-        long result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Long);
-            assertEquals((long) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeLong(long value0, long value1, long value2) {
-        long result0 = profile.profile(value0);
-        long result1 = profile.profile(value1);
-        long result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Long);
-            assertEquals((long) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneFloat(float value) {
-        float result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoFloat(float value0, float value1) {
-        float result0 = profile.profile(value0);
-        float result1 = profile.profile(value1);
-
-        assertEquals(result0, value0, FLOAT_DELTA);
-        assertEquals(result1, value1, FLOAT_DELTA);
-
-        if (PrimitiveValueProfile.exactCompare(value0, value1)) {
-            assertTrue(profile.getCachedValue() instanceof Float);
-            assertEquals((float) profile.getCachedValue(), value0, FLOAT_DELTA);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeFloat(float value0, float value1, float value2) {
-        float result0 = profile.profile(value0);
-        float result1 = profile.profile(value1);
-        float result2 = profile.profile(value2);
-
-        assertEquals(result0, value0, FLOAT_DELTA);
-        assertEquals(result1, value1, FLOAT_DELTA);
-        assertEquals(result2, value2, FLOAT_DELTA);
-
-        if (PrimitiveValueProfile.exactCompare(value0, value1) && PrimitiveValueProfile.exactCompare(value1, value2)) {
-            assertTrue(profile.getCachedValue() instanceof Float);
-            assertEquals((float) profile.getCachedValue(), value0, FLOAT_DELTA);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneDouble(double value) {
-        double result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoDouble(double value0, double value1) {
-        double result0 = profile.profile(value0);
-        double result1 = profile.profile(value1);
-
-        assertEquals(result0, value0, DOUBLE_DELTA);
-        assertEquals(result1, value1, DOUBLE_DELTA);
-
-        if (PrimitiveValueProfile.exactCompare(value0, value1)) {
-            assertTrue(profile.getCachedValue() instanceof Double);
-            assertEquals((double) profile.getCachedValue(), value0, DOUBLE_DELTA);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeDouble(double value0, double value1, double value2) {
-        double result0 = profile.profile(value0);
-        double result1 = profile.profile(value1);
-        double result2 = profile.profile(value2);
-
-        assertEquals(result0, value0, DOUBLE_DELTA);
-        assertEquals(result1, value1, DOUBLE_DELTA);
-        assertEquals(result2, value2, DOUBLE_DELTA);
-
-        if (PrimitiveValueProfile.exactCompare(value0, value1) && PrimitiveValueProfile.exactCompare(value1, value2)) {
-            assertTrue(profile.getCachedValue() instanceof Double);
-            assertEquals((double) profile.getCachedValue(), value0, DOUBLE_DELTA);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneBoolean(boolean value) {
-        boolean result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoBoolean(boolean value0, boolean value1) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Boolean);
-            assertEquals((boolean) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeBoolean(boolean value0, boolean value1, boolean value2) {
-        boolean result0 = profile.profile(value0);
-        boolean result1 = profile.profile(value1);
-        boolean result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Boolean);
-            assertEquals((boolean) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileOneChar(char value) {
-        char result = profile.profile(value);
-
-        assertThat(result, is(value));
-        assertEquals(profile.getCachedValue(), value);
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileTwoChar(char value0, char value1) {
-        char result0 = profile.profile(value0);
-        char result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-
-        if (value0 == value1) {
-            assertTrue(profile.getCachedValue() instanceof Character);
-            assertEquals((char) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testProfileThreeChar(char value0, char value1, char value2) {
-        char result0 = profile.profile(value0);
-        char result1 = profile.profile(value1);
-        char result2 = profile.profile(value2);
-
-        assertEquals(result0, value0);
-        assertEquals(result1, value1);
-        assertEquals(result2, value2);
-
-        if (value0 == value1 && value1 == value2) {
-            assertTrue(profile.getCachedValue() instanceof Character);
-            assertEquals((char) profile.getCachedValue(), value0);
-            assertThat(profile.isGeneric(), is(false));
-        } else {
-            assertThat(profile.isGeneric(), is(true));
-        }
-        assertThat(profile.isUninitialized(), is(false));
-        profile.toString(); // test that it is not crashing
-    }
-
-    @Theory
-    public void testWithBoxedBoxedByte(byte value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Byte);
-        assertEquals((byte) result0, value);
-        assertTrue(result1 instanceof Byte);
-        assertEquals((byte) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedByte(byte value) {
-        byte result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Byte);
-        assertEquals((byte) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedByte(byte value) {
-        Object result0 = profile.profile((Object) value);
-        byte result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Byte);
-        assertEquals((byte) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedShort(short value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Short);
-        assertEquals((short) result0, value);
-        assertTrue(result1 instanceof Short);
-        assertEquals((short) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedShort(short value) {
-        short result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Short);
-        assertEquals((short) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedShort(short value) {
-        Object result0 = profile.profile((Object) value);
-        short result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Short);
-        assertEquals((short) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedInt(int value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Integer);
-        assertEquals((int) result0, value);
-        assertTrue(result1 instanceof Integer);
-        assertEquals((int) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedInt(int value) {
-        int result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Integer);
-        assertEquals((int) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedInt(int value) {
-        Object result0 = profile.profile((Object) value);
-        int result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Integer);
-        assertEquals((int) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedLong(long value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Long);
-        assertEquals((long) result0, value);
-        assertTrue(result1 instanceof Long);
-        assertEquals((long) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedLong(long value) {
-        long result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Long);
-        assertEquals((long) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedLong(long value) {
-        Object result0 = profile.profile((Object) value);
-        long result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Long);
-        assertEquals((long) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedFloat(float value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Float);
-        assertTrue(PrimitiveValueProfile.exactCompare((float) result0, value));
-        assertTrue(result1 instanceof Float);
-        assertTrue(PrimitiveValueProfile.exactCompare((float) result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedFloat(float value) {
-        float result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(PrimitiveValueProfile.exactCompare(result0, value));
-        assertTrue(result1 instanceof Float);
-        assertTrue(PrimitiveValueProfile.exactCompare((float) result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedFloat(float value) {
-        Object result0 = profile.profile((Object) value);
-        float result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Float);
-        assertTrue(PrimitiveValueProfile.exactCompare((float) result0, value));
-        assertTrue(PrimitiveValueProfile.exactCompare(result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedDouble(double value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Double);
-        assertTrue(PrimitiveValueProfile.exactCompare((double) result0, value));
-        assertTrue(result1 instanceof Double);
-        assertTrue(PrimitiveValueProfile.exactCompare((double) result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedDouble(double value) {
-        double result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(PrimitiveValueProfile.exactCompare(result0, value));
-        assertTrue(result1 instanceof Double);
-        assertTrue(PrimitiveValueProfile.exactCompare((double) result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedDouble(double value) {
-        Object result0 = profile.profile((Object) value);
-        double result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Double);
-        assertTrue(PrimitiveValueProfile.exactCompare((double) result0, value));
-        assertTrue(PrimitiveValueProfile.exactCompare(result1, value));
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedBoolean(boolean value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Boolean);
-        assertEquals((boolean) result0, value);
-        assertTrue(result1 instanceof Boolean);
-        assertEquals((boolean) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedBoolean(boolean value) {
-        boolean result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Boolean);
-        assertEquals((boolean) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedBoolean(boolean value) {
-        Object result0 = profile.profile((Object) value);
-        boolean result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Boolean);
-        assertEquals((boolean) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedBoxedChar(char value) {
-        Object result0 = profile.profile((Object) value);
-        Object result1 = profile.profile((Object) value);
-
-        assertTrue(result0 instanceof Character);
-        assertEquals((char) result0, value);
-        assertTrue(result1 instanceof Character);
-        assertEquals((char) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithUnboxedBoxedChar(char value) {
-        char result0 = profile.profile(value);
-        Object result1 = profile.profile((Object) value);
-
-        assertEquals(result0, value);
-        assertTrue(result1 instanceof Character);
-        assertEquals((char) result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBoxedUnboxedCharacter(char value) {
-        Object result0 = profile.profile((Object) value);
-        char result1 = profile.profile(value);
-
-        assertTrue(result0 instanceof Character);
-        assertEquals((char) result0, value);
-        assertEquals(result1, value);
-        assertFalse(profile.isUninitialized());
-        assertFalse(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithByteThenObject(byte value0, Object value1) {
-        byte result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithShortThenObject(short value0, Object value1) {
-        short result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithIntThenObject(int value0, Object value1) {
-        int result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithLongThenObject(long value0, Object value1) {
-        long result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithFloatThenObject(float value0, Object value1) {
-        float result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertTrue(PrimitiveValueProfile.exactCompare(result0, value0));
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithDoubleThenObject(double value0, Object value1) {
-        double result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertTrue(PrimitiveValueProfile.exactCompare(result0, value0));
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithBooleanThenObject(boolean value0, Object value1) {
-        boolean result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Theory
-    public void testWithCharThenObject(char value0, Object value1) {
-        char result0 = profile.profile(value0);
-        Object result1 = profile.profile(value1);
-
-        assertEquals(result0, value0);
-        assertSame(result1, value1);
-        assertFalse(profile.isUninitialized());
-        assertTrue(profile.isGeneric());
-    }
-
-    @Test
-    public void testNegativeZeroFloat() {
-        profile.profile(-0.0f);
-        profile.profile(+0.0f);
-        assertThat(profile.isGeneric(), is(true));
-    }
-
-    @Test
-    public void testNegativeZeroDouble() {
-        profile.profile(-0.0);
-        profile.profile(+0.0);
-        assertThat(profile.isGeneric(), is(true));
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.utilities;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-
-public class UnionAssumptionTest {
-
-    @Test
-    public void testIsValid() {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-        assertTrue(union.isValid());
-    }
-
-    @Test
-    public void testCheck() throws InvalidAssumptionException {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-        union.check();
-    }
-
-    @Test
-    public void testFirstInvalidateIsValid() {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        first.invalidate();
-
-        assertFalse(union.isValid());
-    }
-
-    @Test(expected = InvalidAssumptionException.class)
-    public void testFirstInvalidateCheck() throws InvalidAssumptionException {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        first.invalidate();
-
-        union.check();
-    }
-
-    @Test
-    public void testSecondInvalidateIsValid() {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        second.invalidate();
-
-        assertFalse(union.isValid());
-    }
-
-    @Test(expected = InvalidAssumptionException.class)
-    public void testSecondInvalidateCheck() throws InvalidAssumptionException {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        second.invalidate();
-
-        union.check();
-    }
-
-    @Test
-    public void testBothInvalidateIsValid() {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        first.invalidate();
-        second.invalidate();
-
-        assertFalse(union.isValid());
-    }
-
-    @Test(expected = InvalidAssumptionException.class)
-    public void testBothInvalidateCheck() throws InvalidAssumptionException {
-        final Assumption first = Truffle.getRuntime().createAssumption("first");
-        final Assumption second = Truffle.getRuntime().createAssumption("second");
-        final UnionAssumption union = new UnionAssumption(first, second);
-
-        first.invalidate();
-        second.invalidate();
-
-        union.check();
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.vm;
-
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.util.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.*;
-
-public class ImplicitExplicitExportTest {
-    private TruffleVM vm;
-
-    @Before
-    public void initializeVM() {
-        vm = TruffleVM.newVM().build();
-        assertTrue("Found " + L1 + " language", vm.getLanguages().containsKey(L1));
-        assertTrue("Found " + L2 + " language", vm.getLanguages().containsKey(L2));
-        assertTrue("Found " + L3 + " language", vm.getLanguages().containsKey(L3));
-    }
-
-    @Test
-    public void explicitExportFound() throws IOException {
-        // @formatter:off
-        vm.eval(L1,
-            "explicit.ahoj=42"
-        );
-        Object ret = vm.eval(L3,
-            "return=ahoj"
-        );
-        // @formatter:on
-        assertEquals("42", ret);
-    }
-
-    @Test
-    public void implicitExportFound() throws IOException {
-        // @formatter:off
-        vm.eval(L1,
-            "implicit.ahoj=42"
-        );
-        Object ret = vm.eval(L3,
-            "return=ahoj"
-        );
-        // @formatter:on
-        assertEquals("42", ret);
-    }
-
-    @Test
-    public void explicitExportPreferred2() throws IOException {
-        // @formatter:off
-        vm.eval(L1,
-            "implicit.ahoj=42"
-        );
-        vm.eval(L2,
-            "explicit.ahoj=43"
-        );
-        Object ret = vm.eval(L3,
-            "return=ahoj"
-        );
-        // @formatter:on
-        assertEquals("Explicit import from L2 is used", "43", ret);
-        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
-    }
-
-    @Test
-    public void explicitExportPreferred1() throws IOException {
-        // @formatter:off
-        vm.eval(L1,
-            "explicit.ahoj=43"
-        );
-        vm.eval(L2,
-            "implicit.ahoj=42"
-        );
-        Object ret = vm.eval(L3,
-            "return=ahoj"
-        );
-        // @formatter:on
-        assertEquals("Explicit import from L2 is used", "43", ret);
-        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
-    }
-
-    private abstract static class AbstractExportImportLanguage extends TruffleLanguage {
-        protected AbstractExportImportLanguage(Env env) {
-            super(env);
-        }
-
-        private final Map<String, String> explicit = new HashMap<>();
-        private final Map<String, String> implicit = new HashMap<>();
-
-        @Override
-        protected Object eval(Source code) throws IOException {
-            Properties p = new Properties();
-            try (Reader r = code.getReader()) {
-                p.load(r);
-            }
-            Enumeration<Object> en = p.keys();
-            while (en.hasMoreElements()) {
-                Object n = en.nextElement();
-                if (n instanceof String) {
-                    String k = (String) n;
-                    if (k.startsWith("explicit.")) {
-                        explicit.put(k.substring(9), p.getProperty(k));
-                    }
-                    if (k.startsWith("implicit.")) {
-                        implicit.put(k.substring(9), p.getProperty(k));
-                    }
-                    if (k.equals("return")) {
-                        return env().importSymbol(p.getProperty(k));
-                    }
-                }
-            }
-            return null;
-        }
-
-        @Override
-        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-            if (explicit.containsKey(globalName)) {
-                return explicit.get(globalName);
-            }
-            if (!onlyExplicit && implicit.containsKey(globalName)) {
-                return implicit.get(globalName);
-            }
-            return null;
-        }
-
-        @Override
-        protected Object getLanguageGlobal() {
-            return null;
-        }
-
-        @Override
-        protected boolean isObjectOfLanguage(Object object) {
-            return false;
-        }
-
-        @Override
-        protected ToolSupportProvider getToolSupport() {
-            return null;
-        }
-
-        @Override
-        protected DebugSupportProvider getDebugSupport() {
-            return null;
-        }
-    }
-
-    private static final String L1 = "application/x-test-import-export-1";
-    private static final String L2 = "application/x-test-import-export-2";
-    private static final String L3 = "application/x-test-import-export-3";
-
-    @TruffleLanguage.Registration(mimeType = L1, name = "ImportExport1", version = "0")
-    public static final class ExportImportLanguage1 extends AbstractExportImportLanguage {
-        public ExportImportLanguage1(Env env) {
-            super(env);
-        }
-    }
-
-    @TruffleLanguage.Registration(mimeType = L2, name = "ImportExport2", version = "0")
-    public static final class ExportImportLanguage2 extends AbstractExportImportLanguage {
-        public ExportImportLanguage2(Env env) {
-            super(env);
-        }
-    }
-
-    @TruffleLanguage.Registration(mimeType = L3, name = "ImportExport3", version = "0")
-    public static final class ExportImportLanguage3 extends AbstractExportImportLanguage {
-        public ExportImportLanguage3(Env env) {
-            super(env);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.test.vm;
-
-import java.io.*;
-import java.net.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.vm.*;
-
-public class TruffleVMSingleThreadedTest {
-    TruffleVM tvm;
-
-    @Before
-    public void initInDifferentThread() throws InterruptedException {
-        final TruffleVM.Builder b = TruffleVM.newVM();
-        Thread t = new Thread("Initializer") {
-            @Override
-            public void run() {
-                tvm = b.build();
-            }
-        };
-        t.start();
-        t.join();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void evalURI() throws IOException, URISyntaxException {
-        tvm.eval(new URI("http://unknown.js"));
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void evalString() throws IOException {
-        tvm.eval("text/javascript", "1 + 1");
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void evalReader() throws IOException {
-        try (StringReader sr = new StringReader("1 + 1")) {
-            tvm.eval("text/javascript", sr);
-        }
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void findGlobalSymbol() {
-        tvm.findGlobalSymbol("doesNotExists");
-    }
-}
--- a/graal/com.oracle.truffle.api/.checkstyle_checks.xml	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-<?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: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <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-zA-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="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="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <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">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-     <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </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.  Oracle designates this\n \* particular file as subject to the &quot;Classpath&quot; exception as provided\n \* by Oracle in the LICENSE file that accompanied this code.\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"/>
-    <property name="fileExtensions" value="java"/>
-  </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="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 name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop system..print check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume system..print check"/>
-    <property name="checkFormat" value="RegexpSingleline"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-    <property name="checkFormat" value=".*Header"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: start generated"/>
-    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength"/>
-  </module>
-  <module name="RegexpSingleline">
-    <property name="format" value="System\.(out|err)\.print"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-</module>
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An assumption is a global boolean flag that starts with the value true (i.e., the assumption is
- * valid) and can subsequently be invalidated (using {@link Assumption#invalidate()}). Once
- * invalidated, an assumption can never get valid again. Assumptions can be created using the
- * {@link TruffleRuntime#createAssumption()} or the {@link TruffleRuntime#createAssumption(String)}
- * method. The Truffle compiler has special knowledge of this class in order to produce efficient
- * machine code for checking an assumption in case the assumption object is a compile time constant.
- * Therefore, assumptions should be stored in final fields in Truffle nodes.
- *
- * All instances of classes implementing {@code Assumption} must be held in {@code final} fields for
- * compiler optimizations to take effect.
- */
-public interface Assumption {
-
-    /**
-     * Checks that this assumption is still valid. The method throws an exception, if this is no
-     * longer the case. This method is preferred over the {@link #isValid()} method when writing
-     * guest language interpreter code. The catch block should perform a node rewrite (see
-     * {@link Node#replace(Node)}) with a node that no longer relies on the assumption.
-     *
-     * @throws InvalidAssumptionException If the assumption is no longer valid.
-     */
-    void check() throws InvalidAssumptionException;
-
-    /**
-     * Checks whether the assumption is still valid.
-     *
-     * @return a boolean value indicating the validity of the assumption
-     */
-    boolean isValid();
-
-    /**
-     * Invalidates this assumption. Performs no operation, if the assumption is already invalid.
-     */
-    void invalidate();
-
-    /**
-     * A name for the assumption that is used for debug output.
-     *
-     * @return the name of the assumption
-     */
-    String getName();
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-/**
- * Represents the target of a call.
- */
-public interface CallTarget {
-
-    /**
-     * Calls this target as a root method.
-     *
-     * @param arguments passed arguments as an object array
-     * @return the return result of the call
-     */
-    Object call(Object... arguments);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-/**
- * Assertions about the code produced by the Truffle compiler. All operations have no effect when
- * either executed in the interpreter or in the compiled code. The assertions are checked during
- * code generation and the Truffle compiler produces for failing assertions a stack trace that
- * identifies the code position of the assertion in the context of the current compilation.
- *
- */
-public class CompilerAsserts {
-    /**
-     * Assertion that this code position should never be reached during compilation. It can be used
-     * for exceptional code paths or rare code paths that should never be included in a compilation
-     * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler
-     * directive.
-     */
-    public static void neverPartOfCompilation() {
-        neverPartOfCompilation("");
-    }
-
-    /**
-     * Assertion that this code position should never be reached during compilation. It can be used
-     * for exceptional code paths or rare code paths that should never be included in a compilation
-     * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler
-     * directive.
-     *
-     * @param message text associated with the bailout exception
-     */
-    public static void neverPartOfCompilation(String message) {
-    }
-
-    /**
-     * Assertion that the corresponding value is reduced to a constant during compilation.
-     *
-     * @param value the value that must be constant during compilation
-     */
-    public static <T> void compilationConstant(Object value) {
-        if (!CompilerDirectives.isCompilationConstant(value)) {
-            neverPartOfCompilation("Value is not compilation constant");
-        }
-    }
-
-    /**
-     * Assertion that the corresponding value is reduced to a constant during the initial partial
-     * evaluation phase.
-     *
-     * @param value the value that must be constant during compilation
-     */
-    public static <T> void partialEvaluationConstant(Object value) {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import java.lang.annotation.*;
-import java.util.concurrent.*;
-
-/**
- * Directives that influence the optimizations of the Truffle compiler. All of the operations have
- * no effect when executed in the Truffle interpreter.
- */
-public final class CompilerDirectives {
-
-    public static final double LIKELY_PROBABILITY = 0.75;
-    public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY;
-
-    public static final double SLOWPATH_PROBABILITY = 0.0001;
-    public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;
-
-    /**
-     * Directive for the compiler to discontinue compilation at this code position and instead
-     * insert a transfer to the interpreter.
-     */
-    public static void transferToInterpreter() {
-        if (inInterpreter()) {
-            Truffle.getRuntime().notifyTransferToInterpreter();
-        }
-    }
-
-    /**
-     * Directive for the compiler to discontinue compilation at this code position and instead
-     * insert a transfer to the interpreter, invalidating the currently executing machine code.
-     */
-    public static void transferToInterpreterAndInvalidate() {
-        if (inInterpreter()) {
-            Truffle.getRuntime().notifyTransferToInterpreter();
-        }
-    }
-
-    /**
-     * Returns a boolean value indicating whether the method is executed in the interpreter.
-     *
-     * @return {@code true} when executed in the interpreter, {@code false} in compiled code.
-     */
-    public static boolean inInterpreter() {
-        return true;
-    }
-
-    /**
-     * Returns a boolean value indicating whether the method is executed in the compiled code.
-     *
-     * @return {@code false} when executed in the interpreter, {@code true} in compiled code.
-     */
-    public static boolean inCompiledCode() {
-        return false;
-    }
-
-    /**
-     * Returns a boolean indicating whether or not a given value is seen as constant in optimized
-     * code. If this method is called in the interpreter this method will always return
-     * <code>true</code>.
-     *
-     * Note that optimizations that a compiler will apply to code that is conditional on
-     * <code>isCompilationConstant</code> may be limited. For this reason
-     * <code>isCompilationConstant</code> is not recommended for use to select between alternate
-     * implementations of functionality depending on whether a value is constant. Instead, it is
-     * intended for use as a diagnostic mechanism.
-     *
-     * @param value
-     * @return {@code true} when given value is seen as compilation constant, {@code false} if not
-     *         compilation constant.
-     */
-    public static boolean isCompilationConstant(Object value) {
-        return CompilerDirectives.inInterpreter();
-    }
-
-    /**
-     * Directive for the compiler that the given runnable should only be executed in the interpreter
-     * and ignored in the compiled code.
-     *
-     * @param runnable the closure that should only be executed in the interpreter
-     */
-    public static void interpreterOnly(Runnable runnable) {
-        runnable.run();
-    }
-
-    /**
-     * Directive for the compiler that the given callable should only be executed in the
-     * interpreter.
-     *
-     * @param callable the closure that should only be executed in the interpreter
-     * @return the result of executing the closure in the interpreter and null in the compiled code
-     * @throws Exception If the closure throws an exception when executed in the interpreter.
-     */
-    public static <T> T interpreterOnly(Callable<T> callable) throws Exception {
-        return callable.call();
-    }
-
-    /**
-     * Injects a probability for the given condition into the probability information of the
-     * immediately succeeding branch instruction for the condition. The probability must be a value
-     * between 0.0 and 1.0 (inclusive). The condition should not be a combined condition.
-     *
-     * Example usage immediately before an if statement (it specifies that the likelihood for a to
-     * be greater than b is 90%):
-     *
-     * <code>
-     * if (injectBranchProbability(0.9, a &gt; b)) {
-     *    // ...
-     * }
-     * </code>
-     *
-     * Example usage for a combined condition (it specifies that the likelihood for a to be greater
-     * than b is 90% and under the assumption that this is true, the likelihood for a being 0 is
-     * 10%):
-     *
-     * <code>
-     * if (injectBranchProbability(0.9, a &gt; b) &amp;&amp; injectBranchProbability(0.1, a == 0)) {
-     *    // ...
-     * }
-     * </code>
-     *
-     * There are predefined constants for commonly used probabilities (see
-     * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY},
-     * {@link #FASTPATH_PROBABILITY} ).
-     *
-     * @param probability the probability value between 0.0 and 1.0 that should be injected
-     */
-    public static boolean injectBranchProbability(double probability, boolean condition) {
-        assert probability >= 0.0 && probability <= 1.0;
-        return condition;
-    }
-
-    /**
-     * Bails out of a compilation (e.g., for guest language features that should never be compiled).
-     *
-     * @param reason the reason for the bailout
-     */
-    public static void bailout(String reason) {
-    }
-
-    /**
-     * Marks fields that should be considered final for a Truffle compilation although they are not
-     * final while executing in the interpreter.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    public @interface CompilationFinal {
-    }
-
-    /**
-     * Marks a method that it is considered as a boundary for Truffle partial evaluation.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
-    public @interface TruffleBoundary {
-    }
-
-    /**
-     * Marks classes as value types. Reference comparisons (==) between instances of those classes
-     * have undefined semantics and can either return true or false.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.TYPE})
-    public @interface ValueType {
-    }
-
-    /**
-     * Ensures that the given object is not virtual, i.e., not removed by Escape Analysis at the
-     * point of this call.
-     *
-     * @param obj the object to exclude from Escape Analysis
-     */
-    public static void materialize(Object obj) {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerOptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Allows options to be set to control the compilation of a specific {@link RootNode}, without
- * creating a dependency on the specific compiler used. Options can be tested for support before
- * setting.
- */
-public interface CompilerOptions {
-
-    boolean supportsOption(String name);
-
-    void setOption(String name, Object value);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-/**
- * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8
- * is release, we duplicate them here because they are generally useful for dynamic language
- * implementations.
- */
-public class ExactMath {
-
-    public static int addExact(int x, int y) {
-        int r = x + y;
-        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
-        if (((x ^ r) & (y ^ r)) < 0) {
-            throw new ArithmeticException("integer overflow");
-        }
-        return r;
-    }
-
-    public static long addExact(long x, long y) {
-        long r = x + y;
-        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
-        if (((x ^ r) & (y ^ r)) < 0) {
-            throw new ArithmeticException("long overflow");
-        }
-        return r;
-    }
-
-    public static int subtractExact(int x, int y) {
-        int r = x - y;
-        // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
-        if (((x ^ y) & (x ^ r)) < 0) {
-            throw new ArithmeticException("integer overflow");
-        }
-        return r;
-    }
-
-    public static long subtractExact(long x, long y) {
-        long r = x - y;
-        // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
-        if (((x ^ y) & (x ^ r)) < 0) {
-            throw new ArithmeticException("long overflow");
-        }
-        return r;
-    }
-
-    public static int multiplyExact(int x, int y) {
-        long r = (long) x * (long) y;
-        if ((int) r != r) {
-            throw new ArithmeticException("long overflow");
-        }
-        return (int) r;
-    }
-
-    public static long multiplyExact(long x, long y) {
-        long r = x * y;
-        long ax = Math.abs(x);
-        long ay = Math.abs(y);
-        if (((ax | ay) >>> 31 != 0)) {
-            // Some bits greater than 2^31 that might cause overflow
-            // Check the result using the divide operator
-            // and check for the special case of Long.MIN_VALUE * -1
-            if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {
-                throw new ArithmeticException("long overflow");
-            }
-        }
-        return r;
-    }
-
-    public static int multiplyHigh(int x, int y) {
-        long r = (long) x * (long) y;
-        return (int) (r >> 32);
-    }
-
-    public static int multiplyHighUnsigned(int x, int y) {
-        long xl = x & 0xFFFFFFFFL;
-        long yl = y & 0xFFFFFFFFL;
-        long r = xl * yl;
-        return (int) (r >> 32);
-    }
-
-    public static long multiplyHigh(long x, long y) {
-        // Checkstyle: stop
-        long x0, y0, z0;
-        long x1, y1, z1, z2, t;
-        // Checkstyle: resume
-
-        x0 = x & 0xFFFFFFFFL;
-        x1 = x >> 32;
-
-        y0 = y & 0xFFFFFFFFL;
-        y1 = y >> 32;
-
-        z0 = x0 * y0;
-        t = x1 * y0 + (z0 >>> 32);
-        z1 = t & 0xFFFFFFFFL;
-        z2 = t >> 32;
-        z1 += x0 * y1;
-
-        return x1 * y1 + z2 + (z1 >> 32);
-    }
-
-    public static long multiplyHighUnsigned(long x, long y) {
-        // Checkstyle: stop
-        long x0, y0, z0;
-        long x1, y1, z1, z2, t;
-        // Checkstyle: resume
-
-        x0 = x & 0xFFFFFFFFL;
-        x1 = x >>> 32;
-
-        y0 = y & 0xFFFFFFFFL;
-        y1 = y >>> 32;
-
-        z0 = x0 * y0;
-        t = x1 * y0 + (z0 >>> 32);
-        z1 = t & 0xFFFFFFFFL;
-        z2 = t >>> 32;
-        z1 += x0 * y1;
-
-        return x1 * y1 + z2 + (z1 >>> 32);
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import com.oracle.truffle.api.impl.*;
-
-/**
- * Access to information and basic services in the runtime context for a Truffle-implemented guest
- * language.
- */
-public abstract class ExecutionContext {
-
-    protected ExecutionContext() {
-    }
-
-    /**
-     * Get compiler options specific to this <code>ExecutionContext</code>.
-     */
-    public CompilerOptions getCompilerOptions() {
-        return DefaultCompilerOptions.INSTANCE;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/LoopCountReceiver.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-/**
- * Accepts the execution count of a loop that is a child of this node. The optimization heuristics
- * can use the loop count to guide compilation and inlining.
- */
-public interface LoopCountReceiver {
-
-    void reportLoopCount(int count);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/OptimizationFailedException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-public class OptimizationFailedException extends RuntimeException {
-
-    private final RootCallTarget callTarget;
-
-    public OptimizationFailedException(Throwable cause, RootCallTarget callTarget) {
-        super(cause);
-        this.callTarget = callTarget;
-    }
-
-    public RootCallTarget getCallTarget() {
-        return callTarget;
-    }
-
-    private static final long serialVersionUID = -8797188744430210785L;
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An observer that is notified whenever a child node is replaced.
- */
-public interface ReplaceObserver {
-
-    /**
-     * Returns <code>true</code> if the event is consumed and no parent nodes should be notified by
-     * for replaces. Returns <code>false</code> if the parent {@link Node} or {@link CallTarget}
-     * should get notified.
-     */
-    boolean nodeReplaced(Node oldNode, Node newNode, CharSequence reason);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances
- * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}.
- */
-public interface RootCallTarget extends CallTarget {
-
-    RootNode getRootNode();
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import java.lang.reflect.*;
-import java.security.*;
-
-import com.oracle.truffle.api.impl.*;
-
-/**
- * Class for obtaining the Truffle runtime singleton object of this virtual machine.
- */
-public class Truffle {
-
-    private static final TruffleRuntime RUNTIME = initRuntime();
-
-    /**
-     * Gets the singleton {@link TruffleRuntime} object.
-     */
-    public static TruffleRuntime getRuntime() {
-        return RUNTIME;
-    }
-
-    private static TruffleRuntime initRuntime() {
-        if (TruffleOptions.ForceInterpreter) {
-            /*
-             * Force Truffle to run in interpreter mode even if we have a specialized implementation
-             * of TruffleRuntime available.
-             */
-            return new DefaultTruffleRuntime();
-        }
-
-        return AccessController.doPrivileged(new PrivilegedAction<TruffleRuntime>() {
-            public TruffleRuntime run() {
-                TruffleRuntimeAccess access = null;
-                Class<?> servicesClass = null;
-                try {
-                    servicesClass = Class.forName("com.oracle.jvmci.service.Services");
-                } catch (ClassNotFoundException e) {
-                    // JVMCI is unavailable
-                    e.printStackTrace();
-                } catch (IllegalArgumentException ex) {
-                    throw new IllegalStateException("jvmci service found but yields error", ex);
-                }
-                if (servicesClass != null) {
-                    try {
-                        Method m = servicesClass.getDeclaredMethod("loadSingle", Class.class, boolean.class);
-                        access = (TruffleRuntimeAccess) m.invoke(null, TruffleRuntimeAccess.class, false);
-                    } catch (Throwable e) {
-                        // Fail fast for other errors
-                        throw (InternalError) new InternalError().initCause(e);
-                    }
-                }
-                // TODO: try standard ServiceLoader?
-                if (access != null) {
-                    return access.getRuntime();
-                }
-                return new DefaultTruffleRuntime();
-            }
-        });
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-
-/**
- * An entry point for everyone who wants to implement a Truffle based language. By providing
- * implementation of this type and registering it using {@link Registration} annotation, your
- * language becomes accessible to users of the {@link TruffleVM Truffle virtual machine} - all they
- * will need to do is to include your JAR into their application and all the Truffle goodies (multi
- * language support, multitenant hosting, debugging, etc.) will be made available to them.
- */
-public abstract class TruffleLanguage {
-    private final Env env;
-
-    /**
-     * Constructor to be called by subclasses.
-     *
-     * @param env language environment that will be available via {@link #env()} method to
-     *            subclasses.
-     */
-    protected TruffleLanguage(Env env) {
-        this.env = env;
-    }
-
-    /**
-     * The annotation to use to register your language to the {@link TruffleVM Truffle} system. By
-     * annotating your implementation of {@link TruffleLanguage} by this annotation you are just a
-     * <em>one JAR drop to the class path</em> away from your users. Once they include your JAR in
-     * their application, your language will be available to the {@link TruffleVM Truffle virtual
-     * machine}.
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @Target(ElementType.TYPE)
-    public @interface Registration {
-        /**
-         * Unique name of your language. This name will be exposed to users via the
-         * {@link Language#getName()} getter.
-         *
-         * @return identifier of your language
-         */
-        String name();
-
-        /**
-         * Unique string identifying the language version. This name will be exposed to users via
-         * the {@link Language#getVersion()} getter.
-         *
-         * @return version of your language
-         */
-        String version();
-
-        /**
-         * List of MIME types associated with your language. Users will use them (directly or
-         * indirectly) when {@link TruffleVM#eval(java.lang.String, java.lang.String) executing}
-         * their code snippets or their {@link TruffleVM#eval(java.net.URI) files}.
-         *
-         * @return array of MIME types assigned to your language files
-         */
-        String[] mimeType();
-    }
-
-    protected final Env env() {
-        if (this.env == null) {
-            throw new NullPointerException("Accessing env before initialization is finished");
-        }
-        return this.env;
-    }
-
-    protected abstract Object eval(Source code) throws IOException;
-
-    /**
-     * Called when some other language is seeking for a global symbol. This method is supposed to do
-     * lazy binding, e.g. there is no need to export symbols in advance, it is fine to wait until
-     * somebody asks for it (by calling this method).
-     * <p>
-     * The exported object can either be <code>TruffleObject</code> (e.g. a native object from the
-     * other language) to support interoperability between languages, {@link String} or one of Java
-     * primitive wrappers ( {@link Integer}, {@link Double}, {@link Short}, {@link Boolean}, etc.).
-     * <p>
-     * The way a symbol becomes <em>exported</em> is language dependent. In general it is preferred
-     * to make the export explicit - e.g. call some function or method to register an object under
-     * specific name. Some languages may however decide to support implicit export of symbols (for
-     * example from global scope, if they have one). However explicit exports should always be
-     * preferred. Implicitly exported object of some name should only be used when there is no
-     * explicit export under such <code>globalName</code>. To ensure so the infrastructure first
-     * asks all known languages for <code>onlyExplicit</code> symbols and only when none is found,
-     * it does one more round with <code>onlyExplicit</code> set to <code>false</code>.
-     *
-     * @param globalName the name of the global symbol to find
-     * @param onlyExplicit should the language seek for implicitly exported object or only consider
-     *            the explicitly exported ones?
-     * @return an exported object or <code>null</code>, if the symbol does not represent anything
-     *         meaningful in this language
-     */
-    protected abstract Object findExportedSymbol(String globalName, boolean onlyExplicit);
-
-    /**
-     * Returns global object for the language.
-     * <p>
-     * The object is expected to be <code>TruffleObject</code> (e.g. a native object from the other
-     * language) but technically it can be one of Java primitive wrappers ({@link Integer},
-     * {@link Double}, {@link Short}, etc.).
-     *
-     * @return the global object or <code>null</code> if the language does not support such concept
-     */
-    protected abstract Object getLanguageGlobal();
-
-    /**
-     * Checks whether the object is provided by this language.
-     *
-     * @param object the object to check
-     * @return <code>true</code> if this language can deal with such object in native way
-     */
-    protected abstract boolean isObjectOfLanguage(Object object);
-
-    protected abstract ToolSupportProvider getToolSupport();
-
-    protected abstract DebugSupportProvider getDebugSupport();
-
-    /**
-     * Represents execution environment of the {@link TruffleLanguage}. Each active
-     * {@link TruffleLanguage} receives instance of the environment before any code is executed upon
-     * it. The environment has knowledge of all active languages and can exchange symbols between
-     * them.
-     */
-    public static final class Env {
-        private final TruffleVM vm;
-        private final TruffleLanguage lang;
-        private final Reader in;
-        private final Writer err;
-        private final Writer out;
-
-        Env(TruffleVM vm, Constructor<?> langConstructor, Writer out, Writer err, Reader in) {
-            this.vm = vm;
-            this.in = in;
-            this.err = err;
-            this.out = out;
-            try {
-                this.lang = (TruffleLanguage) langConstructor.newInstance(this);
-            } catch (Exception ex) {
-                throw new IllegalStateException("Cannot construct language " + langConstructor.getDeclaringClass().getName(), ex);
-            }
-        }
-
-        /**
-         * Asks the environment to go through other registered languages and find whether they
-         * export global symbol of specified name. The expected return type is either
-         * <code>TruffleObject</code>, or one of wrappers of Java primitive types ({@link Integer},
-         * {@link Double}).
-         *
-         * @param globalName the name of the symbol to search for
-         * @return object representing the symbol or <code>null</code>
-         */
-        public Object importSymbol(String globalName) {
-            return API.importSymbol(vm, lang, globalName);
-        }
-
-        /**
-         * Input associated with this {@link TruffleVM}.
-         *
-         * @return reader, never <code>null</code>
-         */
-        public Reader stdIn() {
-            return in;
-        }
-
-        /**
-         * Standard output writer for this {@link TruffleVM}.
-         *
-         * @return writer, never <code>null</code>
-         */
-        public Writer stdOut() {
-            return out;
-        }
-
-        /**
-         * Standard error writer for this {@link TruffleVM}.
-         *
-         * @return writer, never <code>null</code>
-         */
-        public Writer stdErr() {
-            return err;
-        }
-    }
-
-    private static final AccessAPI API = new AccessAPI();
-
-    private static final class AccessAPI extends Accessor {
-        @Override
-        protected TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
-            Env env = new Env(vm, langClazz, stdOut, stdErr, stdIn);
-            return env.lang;
-        }
-
-        @Override
-        public Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
-            return super.importSymbol(vm, queryingLang, globalName);
-        }
-
-        @Override
-        protected Object eval(TruffleLanguage l, Source s) throws IOException {
-            return l.eval(s);
-        }
-
-        @Override
-        protected Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
-            return l.findExportedSymbol(globalName, onlyExplicit);
-        }
-
-        @Override
-        protected Object languageGlobal(TruffleLanguage l) {
-            return l.getLanguageGlobal();
-        }
-
-        @Override
-        protected ToolSupportProvider getToolSupport(TruffleLanguage l) {
-            return l.getToolSupport();
-        }
-
-        @Override
-        protected DebugSupportProvider getDebugSupport(TruffleLanguage l) {
-            return l.getDebugSupport();
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import java.security.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Class containing general Truffle options.
- */
-public class TruffleOptions {
-
-    /**
-     * Force truffle to run in interpreter mode.
-     * <p>
-     * Can be set with {@code -Dtruffle.ForceInterpreter=true}.
-     */
-    public static final boolean ForceInterpreter = Boolean.getBoolean("truffle.ForceInterpreter");
-
-    /**
-     * Enables/disables the rewriting of traces in the Truffle runtime to stdout.
-     * <p>
-     * Can be set with {@code -Dtruffle.TraceRewrites=true}.
-     */
-    public static final boolean TraceRewrites;
-
-    /**
-     * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead
-     * for rewriting nodes.
-     * <p>
-     * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}.
-     */
-    public static final boolean DetailedRewriteReasons;
-
-    /**
-     * Filters rewrites that do not contain the given string in the qualified name of the source or
-     * target class hierarchy.
-     * <p>
-     * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}.
-     */
-    public static String TraceRewritesFilterClass;
-
-    /**
-     * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}.
-     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
-     * <p>
-     * Can be set with
-     * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}.
-     */
-    public static NodeCost TraceRewritesFilterFromCost;
-
-    /**
-     * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}.
-     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
-     * <p>
-     * Can be set with
-     * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
-     */
-    public static NodeCost TraceRewritesFilterToCost;
-
-    /**
-     * Enables the dumping of Node creations and AST rewrites in JSON format.
-     * <p>
-     * Can be set with {@code -Dtruffle.TraceASTJSON=true}.
-     */
-    public static final boolean TraceASTJSON;
-
-    private static NodeCost parseNodeInfoKind(String kind) {
-        if (kind == null) {
-            return null;
-        }
-
-        return NodeCost.valueOf(kind);
-    }
-
-    static {
-        final boolean[] values = new boolean[3];
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            public Void run() {
-                values[0] = Boolean.getBoolean("truffle.TraceRewrites");
-                TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
-                TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
-                TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
-                values[1] = Boolean.getBoolean("truffle.DetailedRewriteReasons");
-                values[2] = Boolean.getBoolean("truffle.TraceASTJSON");
-                return null;
-            }
-        });
-        TraceRewrites = values[0];
-        DetailedRewriteReasons = values[1];
-        TraceASTJSON = values[2];
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Interface representing a Truffle runtime object. The runtime is responsible for creating call
- * targets and performing optimizations for them.
- */
-public interface TruffleRuntime {
-
-    /**
-     * Name describing this runtime implementation for debugging purposes.
-     *
-     * @return the name as a String
-     */
-    String getName();
-
-    /**
-     * Creates a new call target for a given root node.
-     *
-     * @param rootNode the root node whose
-     *            {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method
-     *            represents the entry point
-     * @return the new call target object
-     */
-    RootCallTarget createCallTarget(RootNode rootNode);
-
-    /**
-     * Creates a new runtime specific version of {@link DirectCallNode}.
-     *
-     * @param target the direct {@link CallTarget} to call
-     * @return the new call node
-     */
-    DirectCallNode createDirectCallNode(CallTarget target);
-
-    /**
-     * Experimental API. May change without notice.
-     */
-    LoopNode createLoopNode(RepeatingNode body);
-
-    /**
-     * Creates a new runtime specific version of {@link IndirectCallNode}.
-     *
-     * @return the new call node
-     */
-    IndirectCallNode createIndirectCallNode();
-
-    /**
-     * Creates a new assumption object that can be checked and invalidated.
-     *
-     * @return the newly created assumption object
-     */
-    Assumption createAssumption();
-
-    /**
-     * Creates a new assumption object with a given name that can be checked and invalidated.
-     *
-     * @param name the name for the new assumption
-     * @return the newly created assumption object
-     */
-    Assumption createAssumption(String name);
-
-    /**
-     * Creates a new virtual frame object that can be used to store values and is potentially
-     * optimizable by the runtime.
-     *
-     * @return the newly created virtual frame object
-     */
-    VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor);
-
-    /**
-     * Creates a new materialized frame object that can be used to store values.
-     *
-     * @return the newly created materialized frame object
-     */
-    MaterializedFrame createMaterializedFrame(Object[] arguments);
-
-    /**
-     * Creates a new materialized frame object with the given frame descriptor that can be used to
-     * store values.
-     *
-     * @param frameDescriptor the frame descriptor describing this frame's values
-     * @return the newly created materialized frame object
-     */
-    MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor);
-
-    /**
-     * Creates an object which allows you to test for support of and set options specific for this
-     * runtime.
-     *
-     * @return the newly created compiler options object
-     */
-    CompilerOptions createCompilerOptions();
-
-    /**
-     * Accesses the current stack, i.e., the contents of the {@link Frame}s and the associated
-     * {@link CallTarget}s. Iteration starts at the caller frame, i.e., it does not include the
-     * current frame.
-     *
-     * Iteration continues as long as {@link FrameInstanceVisitor#visitFrame}, which is invoked for
-     * every {@link FrameInstance}, returns null. Any non-null result of the visitor indicates that
-     * frame iteration should stop.
-     *
-     * @param visitor the visitor that is called for every matching frame.
-     * @return the last result returned by the visitor (which is non-null to indicate that iteration
-     *         should stop), or null if the whole stack was iterated.
-     */
-    <T> T iterateFrames(FrameInstanceVisitor<T> visitor);
-
-    /**
-     * Accesses the caller frame. This is a convenience method that returns the first frame that is
-     * passed to the visitor of {@link #iterateFrames}.
-     */
-    FrameInstance getCallerFrame();
-
-    /**
-     * Accesses the current frame, i.e., the frame of the closest {@link CallTarget}. It is
-     * important to note that this {@link FrameInstance} supports only slow path access.
-     */
-    FrameInstance getCurrentFrame();
-
-    /**
-     * Requests a capability from the runtime.
-     *
-     * @param capability the type of the interface representing the capability
-     * @return an implementation of the capability or {@code null} if the runtime does not offer it
-     */
-    <T> T getCapability(Class<T> capability);
-
-    /**
-     * Returns a list of all still referenced {@link RootCallTarget} instances that were created
-     * using {@link #createCallTarget(RootNode)}.
-     */
-    Collection<RootCallTarget> getCallTargets();
-
-    /**
-     * Internal API method. Do not use.
-     */
-    void notifyTransferToInterpreter();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-/**
- * A service that provides access to a {@link TruffleRuntime} implementation.
- */
-public interface TruffleRuntimeAccess {
-
-    /**
-     * Gets the {@link TruffleRuntime} implementation available via this access object.
-     */
-    TruffleRuntime getRuntime();
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api;
-
-public interface TypedObject {
-
-    Object getTypeIdentifier();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.debug;
-
-public class DebugSupportException extends Exception {
-
-    private static final long serialVersionUID = 3039074861617372741L;
-
-    public DebugSupportException(String string) {
-        super(string);
-    }
-
-    public DebugSupportException(Exception ex) {
-        super(ex);
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.debug;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Access to language-specific information and execution services to enable debugging.
- */
-public interface DebugSupportProvider extends ToolSupportProvider {
-
-    /**
-     * Runs source code.
-     *
-     * @param source code
-     * @throws DebugSupportException if unable to run successfully
-     */
-    void run(Source source) throws DebugSupportException;
-
-    /**
-     * Runs source code in a halted execution context, or at top level.
-     *
-     * @param source the code to run
-     * @param node node where execution halted, {@code null} if no execution context
-     * @param mFrame frame where execution halted, {@code null} if no execution context
-     * @return result of running the code in the context, or at top level if no execution context.
-     * @throws DebugSupportException if the evaluation cannot be performed
-     */
-    Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException;
-
-    /**
-     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
-     * that, when executed, computes the result of a textual expression in the language; used to
-     * create an
-     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
-     * Advanced Instrument}.
-     *
-     * @param expr a guest language expression
-     * @param resultListener optional listener for the result of each evaluation.
-     * @return a new factory
-     * @throws DebugSupportException if the factory cannot be created, for example if the expression
-     *             is badly formed.
-     */
-    AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-/**
- * Represents a frame containing values of local variables of the guest language. Instances of this
- * type must not be stored in a field or cast to {@link java.lang.Object}.
- */
-public interface Frame {
-
-    /**
-     * @return the object describing the layout of this frame
-     */
-    FrameDescriptor getFrameDescriptor();
-
-    /**
-     * Retrieves the arguments object from this frame. The runtime assumes that the arguments object
-     * is never null.
-     *
-     * @return the arguments used when calling this method
-     */
-    Object[] getArguments();
-
-    /**
-     * Read access to a local variable of type {@link Object}.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    Object getObject(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type {@link Object}.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setObject(FrameSlot slot, Object value);
-
-    /**
-     * Read access to a local variable of type byte.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     * @throws FrameSlotTypeException
-     */
-    byte getByte(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type byte.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-
-    void setByte(FrameSlot slot, byte value);
-
-    /**
-     * Read access to a local variable of type boolean.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type boolean.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setBoolean(FrameSlot slot, boolean value);
-
-    /**
-     * Read access to a local variable of type int.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    int getInt(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type int.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setInt(FrameSlot slot, int value);
-
-    /**
-     * Read access to a local variable of type long.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    long getLong(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type long.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setLong(FrameSlot slot, long value);
-
-    /**
-     * Read access to a local variable of type float.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    float getFloat(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type float.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setFloat(FrameSlot slot, float value);
-
-    /**
-     * Read access to a local variable of type double.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable
-     */
-    double getDouble(FrameSlot slot) throws FrameSlotTypeException;
-
-    /**
-     * Write access to a local variable of type double.
-     *
-     * @param slot the slot of the local variable
-     * @param value the new value of the local variable
-     */
-    void setDouble(FrameSlot slot, double value);
-
-    /**
-     * Read access to a local variable of any type.
-     *
-     * @param slot the slot of the local variable
-     * @return the current value of the local variable or defaultValue if unset
-     */
-    Object getValue(FrameSlot slot);
-
-    /**
-     * Materializes this frame, which allows it to be stored in a field or cast to
-     * {@link java.lang.Object}.
-     *
-     * @return the new materialized frame
-     */
-    MaterializedFrame materialize();
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type object.
-     */
-    boolean isObject(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type byte.
-     */
-    boolean isByte(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type boolean.
-     */
-    boolean isBoolean(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type int.
-     */
-    boolean isInt(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type long.
-     */
-    boolean isLong(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type float.
-     */
-    boolean isFloat(FrameSlot slot);
-
-    /**
-     * Check whether the given {@link FrameSlot} is of type double.
-     */
-    boolean isDouble(FrameSlot slot);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Descriptor of the slots of frame objects. Multiple frame instances are associated with one such
- * descriptor.
- */
-public final class FrameDescriptor implements Cloneable {
-
-    private final Object defaultValue;
-    private final ArrayList<FrameSlot> slots;
-    private final HashMap<Object, FrameSlot> identifierToSlotMap;
-    private Assumption version;
-    private HashMap<Object, Assumption> identifierToNotInFrameAssumptionMap;
-
-    public FrameDescriptor() {
-        this(null);
-    }
-
-    public FrameDescriptor(Object defaultValue) {
-        this.defaultValue = defaultValue;
-        slots = new ArrayList<>();
-        identifierToSlotMap = new HashMap<>();
-        version = createVersion();
-    }
-
-    public static FrameDescriptor create() {
-        return new FrameDescriptor();
-    }
-
-    public static FrameDescriptor create(Object defaultValue) {
-        return new FrameDescriptor(defaultValue);
-    }
-
-    public FrameSlot addFrameSlot(Object identifier) {
-        return addFrameSlot(identifier, null, FrameSlotKind.Illegal);
-    }
-
-    public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) {
-        return addFrameSlot(identifier, null, kind);
-    }
-
-    public FrameSlot addFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
-        CompilerAsserts.neverPartOfCompilation("interpreter-only.  includes hashmap operations.");
-        assert !identifierToSlotMap.containsKey(identifier);
-        FrameSlot slot = new FrameSlot(this, identifier, info, slots.size(), kind);
-        slots.add(slot);
-        identifierToSlotMap.put(identifier, slot);
-        updateVersion();
-        invalidateNotInFrameAssumption(identifier);
-        return slot;
-    }
-
-    public FrameSlot findFrameSlot(Object identifier) {
-        return identifierToSlotMap.get(identifier);
-    }
-
-    public FrameSlot findOrAddFrameSlot(Object identifier) {
-        FrameSlot result = findFrameSlot(identifier);
-        if (result != null) {
-            return result;
-        }
-        return addFrameSlot(identifier);
-    }
-
-    public FrameSlot findOrAddFrameSlot(Object identifier, FrameSlotKind kind) {
-        FrameSlot result = findFrameSlot(identifier);
-        if (result != null) {
-            return result;
-        }
-        return addFrameSlot(identifier, kind);
-    }
-
-    public FrameSlot findOrAddFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
-        FrameSlot result = findFrameSlot(identifier);
-        if (result != null) {
-            return result;
-        }
-        return addFrameSlot(identifier, info, kind);
-    }
-
-    public void removeFrameSlot(Object identifier) {
-        CompilerAsserts.neverPartOfCompilation("interpreter-only.  includes hashmap operations.");
-        assert identifierToSlotMap.containsKey(identifier);
-        slots.remove(identifierToSlotMap.get(identifier));
-        identifierToSlotMap.remove(identifier);
-        updateVersion();
-        getNotInFrameAssumption(identifier);
-    }
-
-    public int getSize() {
-        return slots.size();
-    }
-
-    public List<? extends FrameSlot> getSlots() {
-        return Collections.unmodifiableList(slots);
-    }
-
-    /**
-     * Retrieve the list of all the identifiers associated with this frame descriptor.
-     *
-     * @return the list of all the identifiers in this frame descriptor
-     */
-    public Set<Object> getIdentifiers() {
-        return Collections.unmodifiableSet(identifierToSlotMap.keySet());
-    }
-
-    public FrameDescriptor copy() {
-        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
-        for (int i = 0; i < this.getSlots().size(); i++) {
-            Object identifier = this.getSlots().get(i).getIdentifier();
-            clonedFrameDescriptor.addFrameSlot(identifier);
-        }
-        return clonedFrameDescriptor;
-    }
-
-    public FrameDescriptor shallowCopy() {
-        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
-        clonedFrameDescriptor.slots.addAll(slots);
-        clonedFrameDescriptor.identifierToSlotMap.putAll(identifierToSlotMap);
-        return clonedFrameDescriptor;
-    }
-
-    void updateVersion() {
-        version.invalidate();
-        version = createVersion();
-    }
-
-    public Assumption getVersion() {
-        return version;
-    }
-
-    private static Assumption createVersion() {
-        return Truffle.getRuntime().createAssumption("frame version");
-    }
-
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    public Assumption getNotInFrameAssumption(Object identifier) {
-        if (identifierToSlotMap.containsKey(identifier)) {
-            throw new IllegalArgumentException("Cannot get not-in-frame assumption for existing frame slot!");
-        }
-
-        if (identifierToNotInFrameAssumptionMap == null) {
-            identifierToNotInFrameAssumptionMap = new HashMap<>();
-        } else {
-            Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
-            if (assumption != null) {
-                return assumption;
-            }
-        }
-        Assumption assumption = Truffle.getRuntime().createAssumption("not in frame: " + identifier);
-        identifierToNotInFrameAssumptionMap.put(identifier, assumption);
-        return assumption;
-    }
-
-    private void invalidateNotInFrameAssumption(Object identifier) {
-        if (identifierToNotInFrameAssumptionMap != null) {
-            Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
-            if (assumption != null) {
-                assumption.invalidate();
-                identifierToNotInFrameAssumptionMap.remove(identifier);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("FrameDescriptor@").append(Integer.toHexString(hashCode()));
-        sb.append("{");
-        boolean comma = false;
-        for (FrameSlot slot : slots) {
-            if (comma) {
-                sb.append(", ");
-            } else {
-                comma = true;
-            }
-            sb.append(slot.getIndex()).append(":").append(slot.getIdentifier());
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-public interface FrameInstance {
-
-    public static enum FrameAccess {
-        NONE,
-        READ_ONLY,
-        READ_WRITE,
-        MATERIALIZE
-    }
-
-    Frame getFrame(FrameAccess access, boolean slowPath);
-
-    boolean isVirtualFrame();
-
-    Node getCallNode();
-
-    CallTarget getCallTarget();
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Callback interface for {@link TruffleRuntime#iterateFrames}. Implementations of
- * {@link #visitFrame} return null to indicate that frame iteration should continue and the next
- * caller frame should be visited; and return any non-null value to indicate that frame iteration
- * should stop.
- */
-public interface FrameInstanceVisitor<T> {
-
-    T visitFrame(FrameInstance frameInstance);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * A slot in a frame that can store a value of a given type.
- */
-public final class FrameSlot implements Cloneable {
-
-    private final FrameDescriptor descriptor;
-    private final Object identifier;
-    private final Object info;
-    private final int index;
-    @CompilationFinal private FrameSlotKind kind;
-
-    public FrameSlot(FrameDescriptor descriptor, Object identifier, Object info, int index, FrameSlotKind kind) {
-        this.descriptor = descriptor;
-        this.identifier = identifier;
-        this.info = info;
-        this.index = index;
-        this.kind = kind;
-    }
-
-    public Object getIdentifier() {
-        return identifier;
-    }
-
-    public Object getInfo() {
-        return info;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public FrameSlotKind getKind() {
-        return kind;
-    }
-
-    public void setKind(final FrameSlotKind kind) {
-        if (this.kind != kind) {
-            CompilerDirectives.transferToInterpreter();
-            this.kind = kind;
-            this.descriptor.updateVersion();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "[" + index + "," + identifier + "," + kind + "]";
-    }
-
-    public FrameDescriptor getFrameDescriptor() {
-        return this.descriptor;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-public enum FrameSlotKind {
-    Object,
-    Illegal,
-    Long,
-    Int,
-    Double,
-    Float,
-    Boolean,
-    Byte;
-
-    public final byte tag;
-
-    private FrameSlotKind() {
-        this.tag = (byte) ordinal();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Exception thrown if the frame slot type does not match the access type.
- */
-public final class FrameSlotTypeException extends SlowPathException {
-
-    private static final long serialVersionUID = 6972120475215757452L;
-
-    public FrameSlotTypeException() {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-public final class FrameUtil {
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getObject(FrameSlot)
-     */
-    public static Object getObjectSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getObject(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getByte(FrameSlot)
-     */
-    public static byte getByteSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getByte(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getBoolean(FrameSlot)
-     */
-    public static boolean getBooleanSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getBoolean(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getInt(FrameSlot)
-     */
-    public static int getIntSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getInt(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getLong(FrameSlot)
-     */
-    public static long getLongSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getLong(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getDouble(FrameSlot)
-     */
-    public static double getDoubleSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getDouble(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    /**
-     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
-     * a guard or statically known).
-     *
-     * @param frameSlot the slot of the variable
-     * @throws IllegalStateException if the slot kind does not match
-     * @see Frame#getFloat(FrameSlot)
-     */
-    public static float getFloatSafe(Frame frame, FrameSlot frameSlot) {
-        try {
-            return frame.getFloat(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-/**
- * Represents a materialized frame containing values of local variables of the guest language. It
- * can be created using the {@link VirtualFrame#materialize()} method. Instances of this type are
- * the only frame instances that may be stored in fields or cast to {@link java.lang.Object}.
- */
-public interface MaterializedFrame extends Frame {
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.frame;
-
-/**
- * Represents a frame containing values of local variables of the guest language. Instances of this
- * type must not be stored in a field or cast to {@link java.lang.Object}. If this is necessary, the
- * frame must be explicitly converted into a materialized frame using the
- * {@link VirtualFrame#materialize()} method.
- */
-public interface VirtualFrame extends Frame {
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-
-public abstract class AbstractAssumption implements Assumption {
-
-    protected final String name;
-    protected boolean isValid;
-
-    protected AbstractAssumption(String name) {
-        this.name = name;
-        this.isValid = true;
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return "Assumption(" + (isValid ? "valid" : "invalid") + ", name=" + name + ")";
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.*;
-
-/**
- * Communication between TruffleVM and TruffleLanguage API/SPI.
- */
-public abstract class Accessor {
-    private static Accessor API;
-    private static Accessor SPI;
-    static {
-        TruffleLanguage lng = new TruffleLanguage(null) {
-            @Override
-            protected Object eval(Source code) throws IOException {
-                return null;
-            }
-
-            @Override
-            protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-                return null;
-            }
-
-            @Override
-            protected Object getLanguageGlobal() {
-                return null;
-            }
-
-            @Override
-            protected boolean isObjectOfLanguage(Object object) {
-                return false;
-            }
-
-            @Override
-            protected ToolSupportProvider getToolSupport() {
-                return null;
-            }
-
-            @Override
-            protected DebugSupportProvider getDebugSupport() {
-                return null;
-            }
-        };
-        lng.hashCode();
-    }
-
-    protected Accessor() {
-        if (this.getClass().getSimpleName().endsWith("API")) {
-            if (API != null) {
-                throw new IllegalStateException();
-            }
-            API = this;
-        } else {
-            if (SPI != null) {
-                throw new IllegalStateException();
-            }
-            SPI = this;
-        }
-    }
-
-    protected TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
-        return API.attachEnv(vm, langClazz, stdOut, stdErr, stdIn);
-    }
-
-    protected Object eval(TruffleLanguage l, Source s) throws IOException {
-        return API.eval(l, s);
-    }
-
-    protected Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
-        return SPI.importSymbol(vm, queryingLang, globalName);
-    }
-
-    protected Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
-        return API.findExportedSymbol(l, globalName, onlyExplicit);
-    }
-
-    protected Object languageGlobal(TruffleLanguage l) {
-        return API.languageGlobal(l);
-    }
-
-    protected ToolSupportProvider getToolSupport(TruffleLanguage l) {
-        return API.getToolSupport(l);
-    }
-
-    protected DebugSupportProvider getDebugSupport(TruffleLanguage l) {
-        return API.getDebugSupport(l);
-    }
-
-    protected Object invoke(Object obj, Object[] args) throws IOException {
-        for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) {
-            return si.invoke(obj, args);
-        }
-        throw new IOException("No symbol invoker found!");
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is an implementation-specific class. Do not use or instantiate it. Instead, use
- * {@link TruffleRuntime#createAssumption()} to create an {@link Assumption}.
- */
-final class DefaultAssumption extends AbstractAssumption {
-
-    DefaultAssumption(String name) {
-        super(name);
-    }
-
-    @Override
-    public void check() throws InvalidAssumptionException {
-        if (!isValid) {
-            throw new InvalidAssumptionException();
-        }
-    }
-
-    @Override
-    public void invalidate() {
-        isValid = false;
-    }
-
-    @Override
-    public boolean isValid() {
-        return isValid;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is an implementation-specific class. Do not use or instantiate it. Instead, use
- * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}.
- */
-public class DefaultCallTarget implements RootCallTarget {
-
-    private final RootNode rootNode;
-
-    protected DefaultCallTarget(RootNode function) {
-        this.rootNode = function;
-        this.rootNode.adoptChildren();
-        this.rootNode.applyInstrumentation();
-    }
-
-    @Override
-    public String toString() {
-        return rootNode.toString();
-    }
-
-    public final RootNode getRootNode() {
-        return rootNode;
-    }
-
-    @Override
-    public Object call(Object... args) {
-        final VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
-        FrameInstance oldCurrentFrame = defaultTruffleRuntime().setCurrentFrame(new FrameInstance() {
-
-            public Frame getFrame(FrameAccess access, boolean slowPath) {
-                return frame;
-            }
-
-            public boolean isVirtualFrame() {
-                return false;
-            }
-
-            public Node getCallNode() {
-                return null;
-            }
-
-            public CallTarget getCallTarget() {
-                return DefaultCallTarget.this;
-            }
-        });
-        try {
-            return getRootNode().execute(frame);
-        } finally {
-            defaultTruffleRuntime().setCurrentFrame(oldCurrentFrame);
-        }
-    }
-
-    private static DefaultTruffleRuntime defaultTruffleRuntime() {
-        return (DefaultTruffleRuntime) Truffle.getRuntime();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCompilerOptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-
-public class DefaultCompilerOptions implements CompilerOptions {
-
-    public static DefaultCompilerOptions INSTANCE = new DefaultCompilerOptions();
-
-    public boolean supportsOption(String name) {
-        return false;
-    }
-
-    public void setOption(String name, Object value) {
-        throw new UnsupportedOperationException(String.format("Option %s is not supported by this runtime", name));
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is runtime specific API. Do not use in a guest language.
- */
-public final class DefaultDirectCallNode extends DirectCallNode {
-
-    private boolean inliningForced;
-
-    public DefaultDirectCallNode(CallTarget target) {
-        super(target);
-    }
-
-    @Override
-    public Object call(final VirtualFrame frame, Object[] arguments) {
-        final CallTarget currentCallTarget = defaultTruffleRuntime().getCurrentFrame().getCallTarget();
-        FrameInstance frameInstance = new FrameInstance() {
-
-            public Frame getFrame(FrameAccess access, boolean slowPath) {
-                return frame;
-            }
-
-            public boolean isVirtualFrame() {
-                return false;
-            }
-
-            public Node getCallNode() {
-                return DefaultDirectCallNode.this;
-            }
-
-            public CallTarget getCallTarget() {
-                return currentCallTarget;
-            }
-        };
-        defaultTruffleRuntime().pushFrame(frameInstance);
-        try {
-            return getCurrentCallTarget().call(arguments);
-        } finally {
-            defaultTruffleRuntime().popFrame();
-        }
-    }
-
-    @Override
-    public void forceInlining() {
-        inliningForced = true;
-    }
-
-    @Override
-    public boolean isInliningForced() {
-        return inliningForced;
-    }
-
-    @Override
-    public CallTarget getClonedCallTarget() {
-        return null;
-    }
-
-    @Override
-    public boolean cloneCallTarget() {
-        return false;
-    }
-
-    @Override
-    public boolean isCallTargetCloningAllowed() {
-        return false;
-    }
-
-    @Override
-    public boolean isInlinable() {
-        return false;
-    }
-
-    private static DefaultTruffleRuntime defaultTruffleRuntime() {
-        return (DefaultTruffleRuntime) Truffle.getRuntime();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * This is runtime specific API. Do not use in a guest language.
- */
-final class DefaultIndirectCallNode extends IndirectCallNode {
-    @Override
-    public Object call(final VirtualFrame frame, final CallTarget target, Object[] arguments) {
-        DefaultTruffleRuntime truffleRuntime = (DefaultTruffleRuntime) Truffle.getRuntime();
-        final CallTarget currentCallTarget = truffleRuntime.getCurrentFrame().getCallTarget();
-        FrameInstance frameInstance = new FrameInstance() {
-            public Frame getFrame(FrameAccess access, boolean slowPath) {
-                return frame;
-            }
-
-            public boolean isVirtualFrame() {
-                return false;
-            }
-
-            public Node getCallNode() {
-                return DefaultIndirectCallNode.this;
-            }
-
-            public CallTarget getCallTarget() {
-                return currentCallTarget;
-            }
-        };
-        truffleRuntime.pushFrame(frameInstance);
-        try {
-            return target.call(arguments);
-        } finally {
-            truffleRuntime.popFrame();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public final class DefaultLoopNode extends LoopNode {
-
-    @Child private RepeatingNode repeatNode;
-
-    public DefaultLoopNode(RepeatingNode repeatNode) {
-        this.repeatNode = repeatNode;
-    }
-
-    @Override
-    public RepeatingNode getRepeatingNode() {
-        return repeatNode;
-    }
-
-    @Override
-    public void executeLoop(VirtualFrame frame) {
-        while (repeatNode.executeRepeating(frame)) {
-            // Empty
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * This is an implementation-specific class. Do not use or instantiate it. Instead, use
- * {@link TruffleRuntime#createMaterializedFrame(Object[])} or {@link Frame#materialize()} to create
- * a {@link MaterializedFrame}.
- */
-final class DefaultMaterializedFrame implements MaterializedFrame {
-
-    private final DefaultVirtualFrame wrapped;
-
-    DefaultMaterializedFrame(DefaultVirtualFrame wrapped) {
-        this.wrapped = wrapped;
-    }
-
-    @Override
-    public Object[] getArguments() {
-        return wrapped.getArguments();
-    }
-
-    @Override
-    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getObject(slot);
-    }
-
-    @Override
-    public void setObject(FrameSlot slot, Object value) {
-        wrapped.setObject(slot, value);
-    }
-
-    @Override
-    public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getByte(slot);
-    }
-
-    @Override
-    public void setByte(FrameSlot slot, byte value) {
-        wrapped.setByte(slot, value);
-    }
-
-    @Override
-    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getBoolean(slot);
-    }
-
-    @Override
-    public void setBoolean(FrameSlot slot, boolean value) {
-        wrapped.setBoolean(slot, value);
-    }
-
-    @Override
-    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getInt(slot);
-    }
-
-    @Override
-    public void setInt(FrameSlot slot, int value) {
-        wrapped.setInt(slot, value);
-    }
-
-    @Override
-    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getLong(slot);
-    }
-
-    @Override
-    public void setLong(FrameSlot slot, long value) {
-        wrapped.setLong(slot, value);
-    }
-
-    @Override
-    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getFloat(slot);
-    }
-
-    @Override
-    public void setFloat(FrameSlot slot, float value) {
-        wrapped.setFloat(slot, value);
-    }
-
-    @Override
-    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
-        return wrapped.getDouble(slot);
-    }
-
-    @Override
-    public void setDouble(FrameSlot slot, double value) {
-        wrapped.setDouble(slot, value);
-    }
-
-    @Override
-    public Object getValue(FrameSlot slot) {
-        return wrapped.getValue(slot);
-    }
-
-    @Override
-    public MaterializedFrame materialize() {
-        return this;
-    }
-
-    @Override
-    public FrameDescriptor getFrameDescriptor() {
-        return wrapped.getFrameDescriptor();
-    }
-
-    @Override
-    public boolean isObject(FrameSlot slot) {
-        return wrapped.isObject(slot);
-    }
-
-    @Override
-    public boolean isByte(FrameSlot slot) {
-        return wrapped.isByte(slot);
-    }
-
-    @Override
-    public boolean isBoolean(FrameSlot slot) {
-        return wrapped.isBoolean(slot);
-    }
-
-    @Override
-    public boolean isInt(FrameSlot slot) {
-        return wrapped.isInt(slot);
-    }
-
-    @Override
-    public boolean isLong(FrameSlot slot) {
-        return wrapped.isLong(slot);
-    }
-
-    @Override
-    public boolean isFloat(FrameSlot slot) {
-        return wrapped.isFloat(slot);
-    }
-
-    @Override
-    public boolean isDouble(FrameSlot slot) {
-        return wrapped.isDouble(slot);
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.unsafe.*;
-
-/**
- * Default implementation of the Truffle runtime if the virtual machine does not provide a better
- * performing alternative.
- * <p>
- * This is an implementation-specific class. Do not use or instantiate it. Instead, use
- * {@link Truffle#getRuntime()} to retrieve the current {@link TruffleRuntime}.
- */
-public final class DefaultTruffleRuntime implements TruffleRuntime {
-
-    private final ThreadLocal<LinkedList<FrameInstance>> stackTraces = new ThreadLocal<>();
-    private final ThreadLocal<FrameInstance> currentFrames = new ThreadLocal<>();
-    private final Map<RootCallTarget, Void> callTargets = Collections.synchronizedMap(new WeakHashMap<RootCallTarget, Void>());
-
-    public DefaultTruffleRuntime() {
-    }
-
-    @Override
-    public String getName() {
-        return "Default Truffle Runtime";
-    }
-
-    @Override
-    public RootCallTarget createCallTarget(RootNode rootNode) {
-        DefaultCallTarget target = new DefaultCallTarget(rootNode);
-        rootNode.setCallTarget(target);
-        callTargets.put(target, null);
-        return target;
-    }
-
-    public DirectCallNode createDirectCallNode(CallTarget target) {
-        return new DefaultDirectCallNode(target);
-    }
-
-    public IndirectCallNode createIndirectCallNode() {
-        return new DefaultIndirectCallNode();
-    }
-
-    @Override
-    public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
-        return new DefaultVirtualFrame(frameDescriptor, arguments);
-    }
-
-    @Override
-    public MaterializedFrame createMaterializedFrame(Object[] arguments) {
-        return createMaterializedFrame(arguments, new FrameDescriptor());
-    }
-
-    @Override
-    public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
-        return new DefaultMaterializedFrame(new DefaultVirtualFrame(frameDescriptor, arguments));
-    }
-
-    @Override
-    public CompilerOptions createCompilerOptions() {
-        return new DefaultCompilerOptions();
-    }
-
-    @Override
-    public Assumption createAssumption() {
-        return createAssumption(null);
-    }
-
-    @Override
-    public Assumption createAssumption(String name) {
-        return new DefaultAssumption(name);
-    }
-
-    private LinkedList<FrameInstance> getThreadLocalStackTrace() {
-        LinkedList<FrameInstance> result = stackTraces.get();
-        if (result == null) {
-            result = new LinkedList<>();
-            stackTraces.set(result);
-        }
-        return result;
-    }
-
-    public FrameInstance setCurrentFrame(FrameInstance newValue) {
-        FrameInstance oldValue = currentFrames.get();
-        currentFrames.set(newValue);
-        return oldValue;
-    }
-
-    public void pushFrame(FrameInstance frame) {
-        getThreadLocalStackTrace().addFirst(frame);
-    }
-
-    public void popFrame() {
-        getThreadLocalStackTrace().removeFirst();
-    }
-
-    @Override
-    public <T> T iterateFrames(FrameInstanceVisitor<T> visitor) {
-        T result = null;
-        for (FrameInstance frameInstance : getThreadLocalStackTrace()) {
-            result = visitor.visitFrame(frameInstance);
-            if (result != null) {
-                return result;
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public FrameInstance getCallerFrame() {
-        return getThreadLocalStackTrace().peekFirst();
-    }
-
-    @Override
-    public Collection<RootCallTarget> getCallTargets() {
-        return Collections.unmodifiableSet(callTargets.keySet());
-    }
-
-    @Override
-    public FrameInstance getCurrentFrame() {
-        return currentFrames.get();
-    }
-
-    public <T> T getCapability(Class<T> capability) {
-        if (capability == UnsafeAccessFactory.class) {
-            return capability.cast(new UnsafeAccessFactoryImpl());
-        }
-        return null;
-    }
-
-    public void notifyTransferToInterpreter() {
-    }
-
-    public LoopNode createLoopNode(RepeatingNode repeating) {
-        if (!(repeating instanceof Node)) {
-            throw new IllegalArgumentException("Repeating node must be of type Node.");
-        }
-        return new DefaultLoopNode(repeating);
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * This is an implementation-specific class. Do not use or instantiate it. Instead, use
- * {@link TruffleRuntime#createVirtualFrame(Object[], FrameDescriptor)} to create a
- * {@link VirtualFrame}.
- */
-final class DefaultVirtualFrame implements VirtualFrame {
-
-    private final FrameDescriptor descriptor;
-    private final Object[] arguments;
-    private Object[] locals;
-    private byte[] tags;
-
-    DefaultVirtualFrame(FrameDescriptor descriptor, Object[] arguments) {
-        this.descriptor = descriptor;
-        this.arguments = arguments;
-        this.locals = new Object[descriptor.getSize()];
-        Arrays.fill(locals, descriptor.getDefaultValue());
-        this.tags = new byte[descriptor.getSize()];
-    }
-
-    @Override
-    public Object[] getArguments() {
-        return arguments;
-    }
-
-    @Override
-    public MaterializedFrame materialize() {
-        return new DefaultMaterializedFrame(this);
-    }
-
-    @Override
-    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Object);
-        return locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setObject(FrameSlot slot, Object value) {
-        verifySet(slot, FrameSlotKind.Object);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Byte);
-        return (byte) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setByte(FrameSlot slot, byte value) {
-        verifySet(slot, FrameSlotKind.Byte);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Boolean);
-        return (boolean) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setBoolean(FrameSlot slot, boolean value) {
-        verifySet(slot, FrameSlotKind.Boolean);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Int);
-        return (int) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setInt(FrameSlot slot, int value) {
-        verifySet(slot, FrameSlotKind.Int);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Long);
-        return (long) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setLong(FrameSlot slot, long value) {
-        verifySet(slot, FrameSlotKind.Long);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Float);
-        return (float) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setFloat(FrameSlot slot, float value) {
-        verifySet(slot, FrameSlotKind.Float);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, FrameSlotKind.Double);
-        return (double) locals[slot.getIndex()];
-    }
-
-    @Override
-    public void setDouble(FrameSlot slot, double value) {
-        verifySet(slot, FrameSlotKind.Double);
-        locals[slot.getIndex()] = value;
-    }
-
-    @Override
-    public FrameDescriptor getFrameDescriptor() {
-        return this.descriptor;
-    }
-
-    @Override
-    public Object getValue(FrameSlot slot) {
-        int slotIndex = getSlotIndexChecked(slot);
-        return locals[slotIndex];
-    }
-
-    private int getSlotIndexChecked(FrameSlot slot) {
-        int slotIndex = slot.getIndex();
-        if (slotIndex >= tags.length) {
-            if (!resize()) {
-                throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot));
-            }
-        }
-        return slotIndex;
-    }
-
-    private void verifySet(FrameSlot slot, FrameSlotKind accessKind) {
-        int slotIndex = getSlotIndexChecked(slot);
-        tags[slotIndex] = (byte) accessKind.ordinal();
-    }
-
-    private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
-        int slotIndex = getSlotIndexChecked(slot);
-        byte tag = tags[slotIndex];
-        if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) {
-            throw new FrameSlotTypeException();
-        }
-    }
-
-    private boolean resize() {
-        int oldSize = tags.length;
-        int newSize = descriptor.getSize();
-        if (newSize > oldSize) {
-            locals = Arrays.copyOf(locals, newSize);
-            Arrays.fill(locals, oldSize, newSize, descriptor.getDefaultValue());
-            tags = Arrays.copyOf(tags, newSize);
-            return true;
-        }
-        return false;
-    }
-
-    private byte getTag(FrameSlot slot) {
-        int slotIndex = getSlotIndexChecked(slot);
-        return tags[slotIndex];
-    }
-
-    @Override
-    public boolean isObject(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Object.ordinal();
-    }
-
-    @Override
-    public boolean isByte(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Byte.ordinal();
-    }
-
-    @Override
-    public boolean isBoolean(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Boolean.ordinal();
-    }
-
-    @Override
-    public boolean isInt(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Int.ordinal();
-    }
-
-    @Override
-    public boolean isLong(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Long.ordinal();
-    }
-
-    @Override
-    public boolean isFloat(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Float.ordinal();
-    }
-
-    @Override
-    public boolean isDouble(FrameSlot slot) {
-        return getTag(slot) == FrameSlotKind.Double.ordinal();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import java.io.*;
-
-/**
- * XXX: Temporary class to make unit tests pass without messing with Message implementations and
- * associated nodes too much.
- */
-public abstract class SymbolInvoker {
-    protected abstract Object invoke(Object symbol, Object... args) throws IOException;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.impl;
-
-import sun.misc.*;
-
-import com.oracle.truffle.api.unsafe.*;
-
-final class UnsafeAccessFactoryImpl implements UnsafeAccessFactory {
-    public UnsafeAccess createUnsafeAccess(final Unsafe unsafe) {
-        return new UnsafeAccessImpl(unsafe);
-    }
-
-    private static final class UnsafeAccessImpl implements UnsafeAccess {
-        private final Unsafe unsafe;
-
-        private UnsafeAccessImpl(Unsafe unsafe) {
-            this.unsafe = unsafe;
-        }
-
-        @SuppressWarnings("unchecked")
-        public <T> T uncheckedCast(Object value, Class<T> type, boolean condition, boolean nonNull) {
-            return (T) value;
-        }
-
-        public void putShort(Object receiver, long offset, short value, Object locationIdentity) {
-            unsafe.putShort(receiver, offset, value);
-        }
-
-        public void putObject(Object receiver, long offset, Object value, Object locationIdentity) {
-            unsafe.putObject(receiver, offset, value);
-        }
-
-        public void putLong(Object receiver, long offset, long value, Object locationIdentity) {
-            unsafe.putLong(receiver, offset, value);
-        }
-
-        public void putInt(Object receiver, long offset, int value, Object locationIdentity) {
-            unsafe.putInt(receiver, offset, value);
-        }
-
-        public void putFloat(Object receiver, long offset, float value, Object locationIdentity) {
-            unsafe.putFloat(receiver, offset, value);
-        }
-
-        public void putDouble(Object receiver, long offset, double value, Object locationIdentity) {
-            unsafe.putDouble(receiver, offset, value);
-        }
-
-        public void putByte(Object receiver, long offset, byte value, Object locationIdentity) {
-            unsafe.putByte(receiver, offset, value);
-        }
-
-        public void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity) {
-            unsafe.putBoolean(receiver, offset, value);
-        }
-
-        public short getShort(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getShort(receiver, offset);
-        }
-
-        public Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getObject(receiver, offset);
-        }
-
-        public long getLong(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getLong(receiver, offset);
-        }
-
-        public int getInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getInt(receiver, offset);
-        }
-
-        public float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getFloat(receiver, offset);
-        }
-
-        public double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getDouble(receiver, offset);
-        }
-
-        public byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getByte(receiver, offset);
-        }
-
-        public boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) {
-            return unsafe.getBoolean(receiver, offset);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import java.io.*;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Access to AST-based debugging support, which is could be language implementation specific in the
- * details chosen to be presented.
- * <p>
- * <strong>WARNING:</strong> this interface is under development and will change substantially.
- */
-public interface ASTPrinter {
-
-    /**
-     * Prints a textual AST display, one line per node, with nesting.
-     *
-     * @param p
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     *
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     * @param markNode a node to mark with a textual arrow prefix, if present.
-     */
-    String printTreeToString(Node node, int maxDepth, Node markNode);
-
-    /**
-     * Creates a textual AST display, one line per node, with nesting.
-     *
-     * @param node the root node of the display.
-     * @param maxDepth the maximum number of levels to print below the root
-     */
-    String printTreeToString(Node node, int maxDepth);
-
-    /**
-     * Creates a textual display describing a single (non-wrapper) node, including instrumentation
-     * status: if Probed, and any tags.
-     */
-    String printNodeWithInstrumentation(Node node);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Enables instrumentation by attaching {@linkplain Probe Probes} to some nodes in a (newly created,
- * not yet executed) AST.
- *
- * @see Probe
- * @see Probe#addProbeListener(ProbeListener)
- */
-public interface ASTProber {
-
-    /**
-     * Walk the AST starting at a node and enable instrumentation at selected nodes by attaching
-     * {@linkplain Probe Probes} to them. Ignore {@linkplain Node#isInstrumentable()
-     * non-instrumentable} nodes.
-     */
-    void probeAST(Node node);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Listener for receiving the result a client-provided {@linkplain AdvancedInstrumentRoot AST
- * fragment}, when executed by a
- * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- *
- * @see Instrument
- * @see AdvancedInstrumentRoot
- * @see AdvancedInstrumentRootFactory
- */
-public interface AdvancedInstrumentResultListener {
-
-    /**
-     * Notifies listener that a client-provided {@linkplain AdvancedInstrumentRoot AST fragment} has
-     * been executed by an
-     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
-     * Advanced Instrument} with the specified result, possibly {@code null}.
-     * <p>
-     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
-     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
-     *
-     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
-     *            attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @param result the result of this AST fragment's execution
-     */
-    void notifyResult(Node node, VirtualFrame vFrame, Object result);
-
-    /**
-     * Notifies listener that execution of client-provided {@linkplain AdvancedInstrumentRoot AST
-     * fragment} filed during execution by a @linkplain
-     * Instrument#create(AdvancedInstrumentRootFactory, String) Advanced Instrument}.
-     * <p>
-     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
-     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
-     *
-     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
-     *            attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @param ex the exception
-     */
-    void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Root of a client-provided AST fragment that can be executed efficiently, subject to full Truffle
- * optimization, by an
- * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- *
- * @see Instrument
- * @see AdvancedInstrumentRootFactory
- * @see AdvancedInstrumentResultListener
- */
-public abstract class AdvancedInstrumentRoot extends Node implements InstrumentationNode {
-
-    /**
-     * Executes this AST fragment on behalf of a client {@link Instrument}, just before the
-     * guest-language AST node to which the {@link Probe} holding the Instrument is executed.
-     *
-     * @param node the guest-language AST node to which the host Instrument's Probe is attached
-     * @param vFrame execution frame at the guest-language AST node
-     * @return the result of this AST fragment's execution
-     */
-    public abstract Object executeRoot(Node node, VirtualFrame vFrame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Creator of {@linkplain AdvancedInstrumentRoot AST fragments} suitable for efficient execution,
- * subject to full Truffle optimization, by an
- * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
- * Advanced Instrument}.
- *
- * @see Instrument
- * @see AdvancedInstrumentRoot
- */
-public interface AdvancedInstrumentRootFactory {
-
-    /**
-     * Provider of {@linkplain AdvancedInstrumentRoot AST fragment} instances to be executed by the
-     * Instrumentation Framework at a {@linkplain Probe Probed} site in a guest-language AST.
-     * <p>
-     * <strong>Notes:</strong>
-     * <ul>
-     * <li>Once the factory has produced an AST fragment at a particular {@linkplain Node AST Node},
-     * it will not be called again at that Node.</li>
-     * <li>In some use cases, for example to implement a breakpoint at a specific program location,
-     * the Probe argument will be the same for every call. Each Node argument will represent the
-     * same program location associated with the Probe, but in different clones of the AST.</li>
-     * <li>In other use cases, for example to implement a breakpoint at any Node with a particular
-     * {@linkplain SyntaxTag tag}, both the Probe and Node argument may differ. Implementations that
-     * are sensitive to the lexical context in which the AST fragment will be evaluated must take
-     * care to build a new, possibly different AST fragment for each request.</li>
-     * </ul>
-     *
-     * @param probe the Probe to which the Instrument requesting the AST fragment is attached
-     * @param node the guest-language AST location that is the context in which the requesting
-     *            Instrument must execute the AST fragment.
-     * @return a newly created AST fragment suitable for execution, via instrumentation, in the
-     *         execution context of the specified guest-language AST site.
-     */
-    AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,636 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-// TODO (mlvdv) these statics should not be global.  Move them to some kind of context.
-// TODO (mlvdv) migrate factory (together with Probe)? break out nested classes?
-
-/**
- * A <em>binding</em> between:
- * <ol>
- * <li>A {@link Probe}: a source of <em>execution events</em> taking place at a program location in
- * an executing Truffle AST, and</li>
- * <li>A <em>listener</em>: a consumer of execution events on behalf of an external client.
- * </ol>
- * <p>
- * Client-oriented documentation for the use of Instruments is available online at <a
- * HREF="https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events"
- * >https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events</a>
- * <p>
- * The implementation of Instruments is complicated by the requirement that Truffle be able to clone
- * ASTs at any time. In particular, any instrumentation-supporting Nodes that have been attached to
- * an AST must be cloned along with the AST: AST clones are not permitted to share Nodes.
- * <p>
- * AST cloning is intended to be as <em>transparent</em> as possible to clients. This is encouraged
- * by providing the {@link SimpleInstrumentListener} for clients that need know nothing more than
- * the properties associated with a Probe: it's {@link SourceSection} and any associated instances
- * of {@link SyntaxTag}.
- * <p>
- * AST cloning is <em>not transparent</em> to clients that use the
- * {@link StandardInstrumentListener}, since those event methods identify the concrete Node instance
- * (and thus the AST instance) where the event takes place.
- * <p>
- * <h4>Implementation Notes: the Life Cycle of an {@link Instrument} at a {@link Probe}</h4>
- * <p>
- * <ul>
- * <li>A new Instrument is created in permanent association with a client-provided
- * <em>listener.</em></li>
- *
- * <li>Multiple Instruments may share a single listener.</li>
- *
- * <li>An Instrument does nothing until it is {@linkplain Probe#attach(Instrument) attached} to a
- * Probe, at which time the Instrument begins routing execution events from the Probe's AST location
- * to the Instrument's listener.</li>
- *
- * <li>Neither Instruments nor Probes are {@link Node}s.</li>
- *
- * <li>A Probe has a single source-based location in an AST, but manages a separate
- * <em>instrumentation chain</em> of Nodes at the equivalent location in each clone of the AST.</li>
- * <li>When a probed AST is cloned, the instrumentation chain associated with each Probe is cloned
- * along with the rest of the AST.</li>
- *
- * <li>When a new Instrument (for example an instance of {@link SimpleInstrument} is attached to a
- * Probe, the Instrument inserts a new instance of its private Node type,
- * {@link SimpleInstrument.SimpleInstrumentNode}, into <em>each of the instrument chains</em>
- * managed by the Probe, i.e. one node instance per existing clone of the AST.</li>
- *
- * <li>If an Instrument is attached to a Probe in an AST that subsequently gets cloned, then the
- * Instrument's private Node type will be cloned along with the rest of the the AST.</li>
- * <li>Each Instrument's private Node type is a dynamic inner class whose only state is in the
- * shared (outer) Instrument instance; that state includes a reference to the Instrument's listener.
- * </li>
- *
- * <li>When an Instrument that has been attached to a Probe is {@linkplain #dispose() disposed}, the
- * Instrument searches every instrument chain associated with the Probe and removes the instance of
- * its private Node type.</li>
- *
- * <li>Attaching and disposing an Instrument at a Probe <em>deoptimizes</em> any compilations of the
- * AST.</li>
- *
- * </ul>
- *
- * @see Probe
- * @see TruffleEvents
- */
-public abstract class Instrument {
-
-    /**
-     * Creates a <em>Simple Instrument</em>: this Instrument routes execution events to a
-     * client-provided listener.
-     *
-     * @param listener a listener for execution events
-     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
-     * @return a new instrument, ready for attachment at a probe
-     */
-    public static Instrument create(SimpleInstrumentListener listener, String instrumentInfo) {
-        return new SimpleInstrument(listener, instrumentInfo);
-    }
-
-    /**
-     * Creates a <em>Standard Instrument</em>: this Instrument routes execution events, together
-     * with access to Truffle execution state, to a client-provided listener.
-     *
-     * @param standardListener a listener for execution events and execution state
-     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
-     * @return a new instrument, ready for attachment at a probe
-     */
-    public static Instrument create(StandardInstrumentListener standardListener, String instrumentInfo) {
-        return new StandardInstrument(standardListener, instrumentInfo);
-    }
-
-    /**
-     * Creates an <em>Advanced Instrument</em>: this Instrument executes efficiently, subject to
-     * full Truffle optimization, a client-provided AST fragment every time the Probed node is
-     * entered.
-     * <p>
-     * Any {@link RuntimeException} thrown by execution of the fragment is caught by the framework
-     * and reported to the listener; there is no other notification.
-     *
-     * @param resultListener optional client callback for results/failure notification
-     * @param rootFactory provider of AST fragments on behalf of the client
-     * @param requiredResultType optional requirement, any non-assignable result is reported to the
-     *            the listener, if any, as a failure
-     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
-     * @return a new instrument, ready for attachment at a probe
-     */
-    public static Instrument create(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
-        return new AdvancedInstrument(resultListener, rootFactory, requiredResultType, instrumentInfo);
-    }
-
-    // TODO (mlvdv) experimental
-    /**
-     * For implementation testing.
-     */
-    public static Instrument create(TruffleOptListener listener) {
-        return new TruffleOptInstrument(listener, null);
-    }
-
-    /**
-     * Has this instrument been disposed? stays true once set.
-     */
-    private boolean isDisposed = false;
-
-    protected Probe probe = null;
-
-    /**
-     * Optional documentation, mainly for debugging.
-     */
-    private final String instrumentInfo;
-
-    private Instrument(String instrumentInfo) {
-        this.instrumentInfo = instrumentInfo;
-    }
-
-    /**
-     * Gets the {@link Probe} to which this Instrument is currently attached: {@code null} if not
-     * yet attached to a Probe or if this Instrument has been {@linkplain #dispose() disposed}.
-     */
-    public Probe getProbe() {
-        return probe;
-    }
-
-    /**
-     * Removes this Instrument from the Probe to which it attached and renders this Instrument
-     * inert.
-     *
-     * @throws IllegalStateException if this instrument has already been disposed
-     */
-    public void dispose() throws IllegalStateException {
-        if (isDisposed) {
-            throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt");
-        }
-        if (probe != null) {
-            // It's attached
-            probe.disposeInstrument(this);
-            probe = null;
-        }
-        this.isDisposed = true;
-    }
-
-    /**
-     * For internal implementation only.
-     */
-    void setAttachedTo(Probe probe) {
-        this.probe = probe;
-    }
-
-    /**
-     * Has this instrument been disposed and rendered unusable?
-     */
-    boolean isDisposed() {
-        return isDisposed;
-    }
-
-    abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode);
-
-    /**
-     * Removes this instrument from an instrument chain.
-     */
-    abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode);
-
-    /**
-     * An instrument that propagates events to an instance of {@link SimpleInstrumentListener}.
-     */
-    private static final class SimpleInstrument extends Instrument {
-
-        /**
-         * Tool-supplied listener for events.
-         */
-        private final SimpleInstrumentListener simpleListener;
-
-        private SimpleInstrument(SimpleInstrumentListener simpleListener, String instrumentInfo) {
-            super(instrumentInfo);
-            this.simpleListener = simpleListener;
-        }
-
-        @Override
-        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
-            return new SimpleInstrumentNode(nextNode);
-        }
-
-        @Override
-        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
-            boolean found = false;
-            if (instrumentNode != null) {
-                if (instrumentNode.getInstrument() == this) {
-                    // Found the match at the head of the chain
-                    return instrumentNode.nextInstrumentNode;
-                }
-                // Match not at the head of the chain; remove it.
-                found = instrumentNode.removeFromChain(SimpleInstrument.this);
-            }
-            if (!found) {
-                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
-            }
-            return instrumentNode;
-        }
-
-        /**
-         * Node that implements a {@link SimpleInstrument} in a particular AST.
-         */
-        @NodeInfo(cost = NodeCost.NONE)
-        private final class SimpleInstrumentNode extends AbstractInstrumentNode {
-
-            private SimpleInstrumentNode(AbstractInstrumentNode nextNode) {
-                super(nextNode);
-            }
-
-            public void enter(Node node, VirtualFrame vFrame) {
-                SimpleInstrument.this.simpleListener.enter(SimpleInstrument.this.probe);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.enter(node, vFrame);
-                }
-            }
-
-            public void returnVoid(Node node, VirtualFrame vFrame) {
-                SimpleInstrument.this.simpleListener.returnVoid(SimpleInstrument.this.probe);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnVoid(node, vFrame);
-                }
-            }
-
-            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
-                SimpleInstrument.this.simpleListener.returnValue(SimpleInstrument.this.probe, result);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnValue(node, vFrame, result);
-                }
-            }
-
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
-                SimpleInstrument.this.simpleListener.returnExceptional(SimpleInstrument.this.probe, exception);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
-                }
-            }
-
-            public String instrumentationInfo() {
-                final String info = getInstrumentInfo();
-                return info != null ? info : simpleListener.getClass().getSimpleName();
-            }
-        }
-    }
-
-    /**
-     * An instrument that propagates events to an instance of {@link StandardInstrumentListener}.
-     */
-    private static final class StandardInstrument extends Instrument {
-
-        /**
-         * Tool-supplied listener for AST events.
-         */
-        private final StandardInstrumentListener standardListener;
-
-        private StandardInstrument(StandardInstrumentListener standardListener, String instrumentInfo) {
-            super(instrumentInfo);
-            this.standardListener = standardListener;
-        }
-
-        @Override
-        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
-            return new StandardInstrumentNode(nextNode);
-        }
-
-        @Override
-        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
-            boolean found = false;
-            if (instrumentNode != null) {
-                if (instrumentNode.getInstrument() == this) {
-                    // Found the match at the head of the chain
-                    return instrumentNode.nextInstrumentNode;
-                }
-                // Match not at the head of the chain; remove it.
-                found = instrumentNode.removeFromChain(StandardInstrument.this);
-            }
-            if (!found) {
-                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
-            }
-            return instrumentNode;
-        }
-
-        /**
-         * Node that implements a {@link StandardInstrument} in a particular AST.
-         */
-        @NodeInfo(cost = NodeCost.NONE)
-        private final class StandardInstrumentNode extends AbstractInstrumentNode {
-
-            private StandardInstrumentNode(AbstractInstrumentNode nextNode) {
-                super(nextNode);
-            }
-
-            public void enter(Node node, VirtualFrame vFrame) {
-                standardListener.enter(StandardInstrument.this.probe, node, vFrame);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.enter(node, vFrame);
-                }
-            }
-
-            public void returnVoid(Node node, VirtualFrame vFrame) {
-                standardListener.returnVoid(StandardInstrument.this.probe, node, vFrame);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnVoid(node, vFrame);
-                }
-            }
-
-            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
-                standardListener.returnValue(StandardInstrument.this.probe, node, vFrame, result);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnValue(node, vFrame, result);
-                }
-            }
-
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
-                standardListener.returnExceptional(StandardInstrument.this.probe, node, vFrame, exception);
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
-                }
-            }
-
-            public String instrumentationInfo() {
-                final String info = getInstrumentInfo();
-                return info != null ? info : standardListener.getClass().getSimpleName();
-            }
-        }
-    }
-
-    /**
-     * An instrument that allows clients to provide an AST fragment to be executed directly from
-     * within a Probe's <em>instrumentation chain</em>, and thus directly in the executing Truffle
-     * AST with potential for full optimization.
-     */
-    private static final class AdvancedInstrument extends Instrument {
-
-        private final AdvancedInstrumentResultListener resultListener;
-        private final AdvancedInstrumentRootFactory rootFactory;
-        private final Class<?> requiredResultType;
-
-        private AdvancedInstrument(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
-            super(instrumentInfo);
-            this.resultListener = resultListener;
-            this.rootFactory = rootFactory;
-            this.requiredResultType = requiredResultType;
-        }
-
-        @Override
-        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
-            return new AdvancedInstrumentNode(nextNode);
-        }
-
-        @Override
-        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
-            boolean found = false;
-            if (instrumentNode != null) {
-                if (instrumentNode.getInstrument() == this) {
-                    // Found the match at the head of the chain
-                    return instrumentNode.nextInstrumentNode;
-                }
-                // Match not at the head of the chain; remove it.
-                found = instrumentNode.removeFromChain(AdvancedInstrument.this);
-            }
-            if (!found) {
-                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
-            }
-            return instrumentNode;
-        }
-
-        /**
-         * Node that implements a {@link AdvancedInstrument} in a particular AST.
-         */
-        @NodeInfo(cost = NodeCost.NONE)
-        private final class AdvancedInstrumentNode extends AbstractInstrumentNode {
-
-            @Child private AdvancedInstrumentRoot instrumentRoot;
-
-            private AdvancedInstrumentNode(AbstractInstrumentNode nextNode) {
-                super(nextNode);
-            }
-
-            public void enter(Node node, VirtualFrame vFrame) {
-                if (instrumentRoot == null) {
-                    try {
-                        final AdvancedInstrumentRoot newInstrumentRoot = AdvancedInstrument.this.rootFactory.createInstrumentRoot(AdvancedInstrument.this.probe, node);
-                        if (newInstrumentRoot != null) {
-                            instrumentRoot = newInstrumentRoot;
-                            adoptChildren();
-                            AdvancedInstrument.this.probe.invalidateProbeUnchanged();
-                        }
-                    } catch (RuntimeException ex) {
-                        if (resultListener != null) {
-                            resultListener.notifyFailure(node, vFrame, ex);
-                        }
-                    }
-                }
-                if (instrumentRoot != null) {
-                    try {
-                        final Object result = instrumentRoot.executeRoot(node, vFrame);
-                        if (resultListener != null) {
-                            checkResultType(result);
-                            resultListener.notifyResult(node, vFrame, result);
-                        }
-                    } catch (RuntimeException ex) {
-                        if (resultListener != null) {
-                            resultListener.notifyFailure(node, vFrame, ex);
-                        }
-                    }
-                }
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.enter(node, vFrame);
-                }
-            }
-
-            private void checkResultType(Object result) {
-                if (requiredResultType == null) {
-                    return;
-                }
-                if (result == null) {
-                    throw new RuntimeException("Instrument result null: " + requiredResultType.getSimpleName() + " is required");
-                }
-                if (!(requiredResultType.isAssignableFrom(result.getClass()))) {
-                    throw new RuntimeException("Instrument result " + result.toString() + " not assignable to " + requiredResultType.getSimpleName());
-                }
-            }
-
-            public void returnVoid(Node node, VirtualFrame vFrame) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnVoid(node, vFrame);
-                }
-            }
-
-            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnValue(node, vFrame, result);
-                }
-            }
-
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
-                }
-            }
-
-            public String instrumentationInfo() {
-                final String info = getInstrumentInfo();
-                return info != null ? info : rootFactory.getClass().getSimpleName();
-            }
-        }
-    }
-
-    public interface TruffleOptListener {
-        void notifyIsCompiled(boolean isCompiled);
-    }
-
-    private static final class TruffleOptInstrument extends Instrument {
-
-        private final TruffleOptListener toolOptListener;
-
-        private TruffleOptInstrument(TruffleOptListener listener, String instrumentInfo) {
-            super(instrumentInfo);
-            this.toolOptListener = listener;
-        }
-
-        @Override
-        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
-            return new TruffleOptInstrumentNode(nextNode);
-        }
-
-        @Override
-        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
-            boolean found = false;
-            if (instrumentNode != null) {
-                if (instrumentNode.getInstrument() == this) {
-                    // Found the match at the head of the chain
-                    return instrumentNode.nextInstrumentNode;
-                }
-                // Match not at the head of the chain; remove it.
-                found = instrumentNode.removeFromChain(TruffleOptInstrument.this);
-            }
-            if (!found) {
-                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
-            }
-            return instrumentNode;
-        }
-
-        @NodeInfo(cost = NodeCost.NONE)
-        private final class TruffleOptInstrumentNode extends AbstractInstrumentNode {
-
-            private boolean isCompiled;
-
-            private TruffleOptInstrumentNode(AbstractInstrumentNode nextNode) {
-                super(nextNode);
-                this.isCompiled = CompilerDirectives.inCompiledCode();
-            }
-
-            public void enter(Node node, VirtualFrame vFrame) {
-                if (this.isCompiled != CompilerDirectives.inCompiledCode()) {
-                    this.isCompiled = CompilerDirectives.inCompiledCode();
-                    TruffleOptInstrument.this.toolOptListener.notifyIsCompiled(this.isCompiled);
-                }
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.enter(node, vFrame);
-                }
-            }
-
-            public void returnVoid(Node node, VirtualFrame vFrame) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnVoid(node, vFrame);
-                }
-            }
-
-            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnValue(node, vFrame, result);
-                }
-            }
-
-            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
-                if (nextInstrumentNode != null) {
-                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
-                }
-            }
-
-            public String instrumentationInfo() {
-                final String info = getInstrumentInfo();
-                return info != null ? info : toolOptListener.getClass().getSimpleName();
-            }
-        }
-    }
-
-    @NodeInfo(cost = NodeCost.NONE)
-    abstract class AbstractInstrumentNode extends Node implements TruffleEvents, InstrumentationNode {
-
-        @Child protected AbstractInstrumentNode nextInstrumentNode;
-
-        protected AbstractInstrumentNode(AbstractInstrumentNode nextNode) {
-            this.nextInstrumentNode = nextNode;
-        }
-
-        @Override
-        public boolean isInstrumentable() {
-            return false;
-        }
-
-        /**
-         * Gets the instrument that created this node.
-         */
-        private Instrument getInstrument() {
-            return Instrument.this;
-        }
-
-        /**
-         * Removes the node from this chain that was added by a particular instrument, assuming that
-         * the head of the chain is not the one to be replaced. This is awkward, but is required
-         * because {@link Node#replace(Node)} won't take a {@code null} argument. This doesn't work
-         * for the tail of the list, which would be replacing itself with null. So the replacement
-         * must be directed the parent of the node being removed.
-         */
-        private boolean removeFromChain(Instrument instrument) {
-            assert getInstrument() != instrument;
-            if (nextInstrumentNode == null) {
-                return false;
-            }
-            if (nextInstrumentNode.getInstrument() == instrument) {
-                // Next is the one to remove
-                if (nextInstrumentNode.nextInstrumentNode == null) {
-                    // Next is at the tail; just forget
-                    nextInstrumentNode = null;
-                } else {
-                    // Replace next with its successor
-                    nextInstrumentNode.replace(nextInstrumentNode.nextInstrumentNode);
-                }
-                return true;
-            }
-            return nextInstrumentNode.removeFromChain(instrument);
-        }
-
-        protected String getInstrumentInfo() {
-            return Instrument.this.instrumentInfo;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-public class InstrumentationException extends Exception {
-
-    public InstrumentationException(RuntimeException ex) {
-        super(ex);
-    }
-
-    private static final long serialVersionUID = 447857066220935502L;
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A marker interface for Truffle {@linkplain Node nodes} that internally implement the
- * <em>Instrumentation Framework</em>. Such nodes should not be part of any Guest Language execution
- * semantics, and should in general not be visible to ordinary Instrumentation clients.
- */
-public interface InstrumentationNode {
-
-    /**
-     * A short description of the particular role played by the node, intended to support debugging.
-     */
-    String instrumentationInfo();
-
-    /**
-     * Events that propagate through the {@linkplain InstrumentationNode implementation nodes} of
-     * the Instrumentation Framework, not visible in this form to Instrumentation clients.
-     */
-    interface TruffleEvents {
-
-        /**
-         * An AST node's execute method is about to be called.
-         */
-        void enter(Node node, VirtualFrame vFrame);
-
-        /**
-         * An AST Node's {@code void}-valued execute method has just returned.
-         */
-        void returnVoid(Node node, VirtualFrame vFrame);
-
-        /**
-         * An AST Node's execute method has just returned a value (boxed if primitive).
-         */
-        void returnValue(Node node, VirtualFrame vFrame, Object result);
-
-        /**
-         * An AST Node's execute method has just thrown an exception.
-         */
-        void returnExceptional(Node node, VirtualFrame vFrame, Exception exception);
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-/**
- * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language
- * program execution.
- * <p>
- * Tools share a common <em>life cycle</em>:
- * <ul>
- * <li>A newly created tool is inert until {@linkplain #install() installed}.</li>
- * <li>An installed tool becomes <em>enabled</em> and immediately begins installing
- * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from
- * those instruments</li>
- * <li>A tool may only be installed once.</li>
- * <li>It should be possible to install multiple instances of a tool, possibly (but not necessarily)
- * configured differently with respect to what data is being collected.</li>
- * <li>Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled}
- * arbitrarily.</li>
- * <li>A disabled tool:
- * <ul>
- * <li>Collects no data;</li>
- * <li>Retains existing AST instrumentation;</li>
- * <li>Continues to instrument newly created ASTs; and</li>
- * <li>Retains previously collected data.</li>
- * </ul>
- * </li>
- * <li>An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool
- * installed but with all previously collected data removed.</li>
- * <li>A {@linkplain #dispose() disposed} tool removes all instrumentation (but not
- * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data persists.</li>
- * </ul>
- * <p>
- * Tool-specific methods that access data collected by the tool should:
- * <ul>
- * <li>Return modification-safe representations of the data; and</li>
- * <li>Not change the state of the data.</li>
- * </ul>
- * <b>Note:</b><br>
- * Tool installation is currently <em>global</em> to the Truffle Execution environment. When
- * language-agnostic management of individual execution environments is added to the platform,
- * installation will be (optionally) specific to a single execution environment.
- */
-public abstract class InstrumentationTool {
-    // TODO (mlvdv) still thinking about the most appropriate name for this class of tools
-
-    private enum ToolState {
-
-        /** Not yet installed, inert. */
-        UNINSTALLED,
-
-        /** Installed, collecting data. */
-        ENABLED,
-
-        /** Installed, not collecting data. */
-        DISABLED,
-
-        /** Was installed, but now removed, inactive, and no longer usable. */
-        DISPOSED;
-    }
-
-    private ToolState toolState = ToolState.UNINSTALLED;
-
-    protected InstrumentationTool() {
-    }
-
-    /**
-     * Connect the tool to some part of the Truffle runtime, and enable data collection to start.
-     * Instrumentation will only be added to subsequently created ASTs.
-     *
-     * @throws IllegalStateException if the tool has previously been installed.
-     */
-    public final void install() {
-        checkUninstalled();
-        if (internalInstall()) {
-            toolState = ToolState.ENABLED;
-        }
-    }
-
-    /**
-     * @return whether the tool is currently collecting data.
-     */
-    public final boolean isEnabled() {
-        return toolState == ToolState.ENABLED;
-    }
-
-    /**
-     * Switches tool state between <em>enabled</em> (collecting data) and <em>disabled</em> (not
-     * collecting data, but keeping data already collected).
-     *
-     * @throws IllegalStateException if not yet installed or disposed.
-     */
-    public final void setEnabled(boolean isEnabled) {
-        checkInstalled();
-        internalSetEnabled(isEnabled);
-        toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED;
-    }
-
-    /**
-     * Clears any data already collected, but otherwise does not change the state of the tool.
-     *
-     * @throws IllegalStateException if not yet installed or disposed.
-     */
-    public final void reset() {
-        checkInstalled();
-        internalReset();
-    }
-
-    /**
-     * Makes the tool permanently <em>disabled</em>, removes instrumentation, but keeps data already
-     * collected.
-     *
-     * @throws IllegalStateException if not yet installed or disposed.
-     */
-    public final void dispose() {
-        checkInstalled();
-        internalDispose();
-        toolState = ToolState.DISPOSED;
-    }
-
-    /**
-     * @return whether the installation succeeded.
-     */
-    protected abstract boolean internalInstall();
-
-    /**
-     * No subclass action required.
-     *
-     * @param isEnabled
-     */
-    protected void internalSetEnabled(boolean isEnabled) {
-    }
-
-    protected abstract void internalReset();
-
-    protected abstract void internalDispose();
-
-    /**
-     * Ensure that the tool is currently installed.
-     *
-     * @throws IllegalStateException
-     */
-    private void checkInstalled() throws IllegalStateException {
-        if (toolState == ToolState.UNINSTALLED) {
-            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
-        }
-        if (toolState == ToolState.DISPOSED) {
-            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
-        }
-    }
-
-    /**
-     * Ensure that the tool has not yet been installed.
-     *
-     * @throws IllegalStateException
-     */
-    private void checkUninstalled() {
-        if (toolState != ToolState.UNINSTALLED) {
-            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of an execution context, such as a shell or eval.
- */
-public final class KillException extends ControlFlowException {
-
-    private static final long serialVersionUID = 3163641880088766957L;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,486 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import java.io.*;
-import java.lang.ref.*;
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-
-//TODO (mlvdv) these statics should not be global.  Move them to some kind of context.
-
-/**
- * A <em>binding</em> between:
- * <ol>
- * <li>A program location in an executing Truffle AST (corresponding to a {@link SourceSection}),
- * and</li>
- * <li>A dynamically managed collection of "attached" {@linkplain Instrument Instruments} that
- * receive event notifications on behalf of external clients.</li>
- * </ol>
- * <p>
- * Client-oriented documentation for the use of Probes is available online at <a
- * HREF="https://wiki.openjdk.java.net/display/Graal/Finding+Probes"
- * >https://wiki.openjdk.java.net/display/Graal/Finding+Probes</a>
- * <p>
- * <h4>Implementation notes:</h4>
- * <p>
- * <ul>
- * <li>A Probe must be permanently associated with a <em>program location</em>, defined by a
- * particular {@link SourceSection}, even though:
- * <ul>
- * <li>that location is represented in an AST as a {@link Node}, which might be replaced through
- * optimizations such as specialization, and</li>
- * <li>Truffle may <em>clone</em> the AST so that the location is actually represented by multiple
- * Nodes in multiple ASTs.</li>
- * </ul>
- * </li>
- *
- * <li>The effect of the binding is to intercept {@linkplain TruffleEvents execution events}
- * arriving at the "probed" AST Node and notify each attached {@link Instrument} before execution is
- * allowed to proceed to the child and again after execution completes.</li>
- *
- * <li>The method {@link Node#probe()} creates a Probe on an AST Node; redundant calls return the
- * same Probe.</li>
- *
- * <li>The "probing" of a Truffle AST must be done after the AST is complete (i.e. parent pointers
- * correctly assigned), but before any cloning or executions. This is done by creating an instance
- * of {@link ASTProber} and registering it via {@link #registerASTProber(ASTProber)}. Once
- * registered, it will be applied automatically to every newly created AST.</li>
- *
- * <li>The "probing" of an AST Node is implemented by insertion of a {@link ProbeNode.WrapperNode}
- * into the AST (as new parent of the Node being probed), together with an associated
- * {@link ProbeNode} that routes execution events at the probed Node to all the
- * {@linkplain Instrument Instruments} attached to the Probe's <em>instrument chain</em>.</li>
- *
- * <li>When Truffle clones an AST, any attached WrapperNodes and ProbeNodes are cloned as well,
- * together with their attached instrument chains. Each Probe instance intercepts cloning events and
- * keeps track of all AST copies.</li>
- *
- * <li>All attached {@link InstrumentationNode}s effectively become part of the running program:
- * <ul>
- * <li>Good News: instrumentation code implicitly benefits from every kind of Truffle optimization.</li>
- * <li>Bad News: instrumentation code must be implemented carefully to avoid interfering with any
- * Truffle optimizations.</li>
- * </ul>
- * </li>
- *
- * </ul>
- *
- * @see Instrument
- * @see ASTProber
- * @see ProbeListener
- * @see SyntaxTag
- */
-public final class Probe {
-
-    private static final boolean TRACE = false;
-    private static final String TRACE_PREFIX = "PROBE: ";
-    private static final PrintStream OUT = System.out;
-
-    private static void trace(String format, Object... args) {
-        if (TRACE) {
-            OUT.println(TRACE_PREFIX + String.format(format, args));
-        }
-    }
-
-    private static final List<ASTProber> astProbers = new ArrayList<>();
-
-    private static final List<ProbeListener> probeListeners = new ArrayList<>();
-
-    /**
-     * All Probes that have been created.
-     */
-    private static final List<WeakReference<Probe>> probes = new ArrayList<>();
-
-    /**
-     * A global trap that triggers notification just before executing any Node that is Probed with a
-     * matching tag.
-     */
-    @CompilationFinal private static SyntaxTagTrap beforeTagTrap = null;
-
-    /**
-     * A global trap that triggers notification just after executing any Node that is Probed with a
-     * matching tag.
-     */
-    @CompilationFinal private static SyntaxTagTrap afterTagTrap = null;
-
-    private static final class FindSourceVisitor implements NodeVisitor {
-
-        Source source = null;
-
-        public boolean visit(Node node) {
-            final SourceSection sourceSection = node.getSourceSection();
-            if (sourceSection != null) {
-                source = sourceSection.getSource();
-                return false;
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Walks an AST, looking for the first node with an assigned {@link SourceSection} and returning
-     * the {@link Source}.
-     */
-    private static Source findSource(Node node) {
-        final FindSourceVisitor visitor = new FindSourceVisitor();
-        node.accept(visitor);
-        return visitor.source;
-    }
-
-    /**
-     * Enables instrumentation at selected nodes in all subsequently constructed ASTs.
-     */
-    public static void registerASTProber(ASTProber prober) {
-        astProbers.add(prober);
-    }
-
-    public static void unregisterASTProber(ASTProber prober) {
-        astProbers.remove(prober);
-    }
-
-    /**
-     * Enables instrumentation in a newly created AST by applying all registered instances of
-     * {@link ASTProber}.
-     */
-    public static void applyASTProbers(Node node) {
-
-        String name = "<?>";
-        final Source source = findSource(node);
-        if (source != null) {
-            name = source.getShortName();
-        } else {
-            final SourceSection sourceSection = node.getEncapsulatingSourceSection();
-            if (sourceSection != null) {
-                name = sourceSection.getShortDescription();
-            }
-        }
-        trace("START %s", name);
-        for (ProbeListener listener : probeListeners) {
-            listener.startASTProbing(source);
-        }
-        for (ASTProber prober : astProbers) {
-            prober.probeAST(node);
-        }
-        for (ProbeListener listener : probeListeners) {
-            listener.endASTProbing(source);
-        }
-        trace("FINISHED %s", name);
-    }
-
-    /**
-     * Adds a {@link ProbeListener} to receive events.
-     */
-    public static void addProbeListener(ProbeListener listener) {
-        assert listener != null;
-        probeListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link ProbeListener}. Ignored if listener not found.
-     */
-    public static void removeProbeListener(ProbeListener listener) {
-        probeListeners.remove(listener);
-    }
-
-    /**
-     * Returns all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole collection of
-     * probes if the specified tag is {@code null}.
-     *
-     * @return A collection of probes containing the given tag.
-     */
-    public static Collection<Probe> findProbesTaggedAs(SyntaxTag tag) {
-        final List<Probe> taggedProbes = new ArrayList<>();
-        for (WeakReference<Probe> ref : probes) {
-            Probe probe = ref.get();
-            if (probe != null) {
-                if (tag == null || probe.isTaggedAs(tag)) {
-                    taggedProbes.add(ref.get());
-                }
-            }
-        }
-        return taggedProbes;
-    }
-
-    // TODO (mlvdv) generalize to permit multiple "before traps" without a performance hit?
-    /**
-     * Sets the current "<em>before</em> tag trap"; there can be no more than one in effect.
-     * <ul>
-     * <li>The before-trap triggers a callback just <strong><em>before</em></strong> execution
-     * reaches <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created)
-     * with the specified {@link SyntaxTag}.</li>
-     * <li>Setting the before-trap to {@code null} clears an existing before-trap.</li>
-     * <li>Setting a non{@code -null} before-trap when one is already set clears the previously set
-     * before-trap.</li>
-     * </ul>
-     *
-     * @param newBeforeTagTrap The new "before" {@link SyntaxTagTrap} to set.
-     */
-    public static void setBeforeTagTrap(SyntaxTagTrap newBeforeTagTrap) {
-        beforeTagTrap = newBeforeTagTrap;
-        for (WeakReference<Probe> ref : probes) {
-            final Probe probe = ref.get();
-            if (probe != null) {
-                probe.notifyTrapsChanged();
-            }
-        }
-    }
-
-    // TODO (mlvdv) generalize to permit multiple "after traps" without a performance hit?
-    /**
-     * Sets the current "<em>after</em> tag trap"; there can be no more than one in effect.
-     * <ul>
-     * <li>The after-trap triggers a callback just <strong><em>after</em></strong> execution leaves
-     * <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) with
-     * the specified {@link SyntaxTag}.</li>
-     * <li>Setting the after-trap to {@code null} clears an existing after-trap.</li>
-     * <li>Setting a non{@code -null} after-trap when one is already set clears the previously set
-     * after-trap.</li>
-     * </ul>
-     *
-     * @param newAfterTagTrap The new "after" {@link SyntaxTagTrap} to set.
-     */
-    public static void setAfterTagTrap(SyntaxTagTrap newAfterTagTrap) {
-        afterTagTrap = newAfterTagTrap;
-        for (WeakReference<Probe> ref : probes) {
-            final Probe probe = ref.get();
-            if (probe != null) {
-                probe.notifyTrapsChanged();
-            }
-        }
-    }
-
-    private final SourceSection sourceSection;
-    private final ArrayList<SyntaxTag> tags = new ArrayList<>();
-    private final List<WeakReference<ProbeNode>> probeNodeClones = new ArrayList<>();
-
-    /*
-     * Invalidated whenever something changes in the Probe and its Instrument chain, so need deopt
-     */
-    private final CyclicAssumption probeStateUnchangedCyclic = new CyclicAssumption("Probe state unchanged");
-
-    /*
-     * The assumption that nothing had changed in this probe, the last time anybody checked (when
-     * there may have been a deopt). Every time a check fails, gets replaced by a new unchanged
-     * assumption.
-     */
-    @CompilationFinal private Assumption probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption();
-
-    // Must invalidate whenever changed
-    @CompilationFinal private boolean isBeforeTrapActive = false;
-
-    // Must invalidate whenever changed
-    @CompilationFinal private boolean isAfterTrapActive = false;
-
-    /**
-     * Intended for use only by {@link ProbeNode}.
-     */
-    Probe(ProbeNode probeNode, SourceSection sourceSection) {
-        this.sourceSection = sourceSection;
-        probes.add(new WeakReference<>(this));
-        registerProbeNodeClone(probeNode);
-        if (TRACE) {
-            final String location = this.sourceSection == null ? "<unknown>" : sourceSection.getShortDescription();
-            trace("ADDED %s %s %s", "Probe@", location, getTagsDescription());
-        }
-        for (ProbeListener listener : probeListeners) {
-            listener.newProbeInserted(this);
-        }
-    }
-
-    /**
-     * Is this node tagged as belonging to a particular human-sensible category of language
-     * constructs?
-     */
-    public boolean isTaggedAs(SyntaxTag tag) {
-        assert tag != null;
-        return tags.contains(tag);
-    }
-
-    /**
-     * In which user-sensible categories has this node been tagged (<em>empty set</em> if none).
-     */
-    public Collection<SyntaxTag> getSyntaxTags() {
-        return Collections.unmodifiableCollection(tags);
-    }
-
-    /**
-     * Adds a {@linkplain SyntaxTag tag} to the set of tags associated with this {@link Probe};
-     * {@code no-op} if already in the set.
-     */
-    public void tagAs(SyntaxTag tag, Object tagValue) {
-        assert tag != null;
-        if (!tags.contains(tag)) {
-            tags.add(tag);
-            for (ProbeListener listener : probeListeners) {
-                listener.probeTaggedAs(this, tag, tagValue);
-            }
-
-            // Update the status of this Probe with respect to global tag traps
-            boolean tagTrapsChanged = false;
-            if (beforeTagTrap != null && tag == beforeTagTrap.getTag()) {
-                this.isBeforeTrapActive = true;
-                tagTrapsChanged = true;
-            }
-            if (afterTagTrap != null && tag == afterTagTrap.getTag()) {
-                this.isAfterTrapActive = true;
-                tagTrapsChanged = true;
-            }
-            if (tagTrapsChanged) {
-                invalidateProbeUnchanged();
-            }
-            if (TRACE) {
-                trace("TAGGED as %s: %s", tag, getShortDescription());
-            }
-        }
-    }
-
-    /**
-     * Adds instrumentation at this Probe.
-     *
-     * @param instrument an instrument not yet attached to a probe
-     * @throws IllegalStateException if the instrument has ever been attached before
-     */
-    public void attach(Instrument instrument) throws IllegalStateException {
-        if (instrument.isDisposed()) {
-            throw new IllegalStateException("Attempt to attach disposed instrument");
-        }
-        if (instrument.getProbe() != null) {
-            throw new IllegalStateException("Attampt to attach an already attached instrument");
-        }
-        instrument.setAttachedTo(this);
-        for (WeakReference<ProbeNode> ref : probeNodeClones) {
-            final ProbeNode probeNode = ref.get();
-            if (probeNode != null) {
-                probeNode.addInstrument(instrument);
-            }
-        }
-        invalidateProbeUnchanged();
-    }
-
-    /**
-     * Gets the {@link SourceSection} associated with the Guest Language AST node being
-     * instrumented, possibly {@code null}.
-     */
-    public SourceSection getProbedSourceSection() {
-        return sourceSection;
-    }
-
-    public String getShortDescription() {
-        final String location = sourceSection == null ? "<unknown>" : sourceSection.getShortDescription();
-        return "Probe@" + location + getTagsDescription();
-    }
-
-    /**
-     * Internal method for removing and rendering inert a specific instrument previously attached at
-     * this Probe.
-     *
-     * @param instrument an instrument already attached
-     * @throws IllegalStateException if instrument not attached at this Probe
-     * @see Instrument#dispose()
-     */
-    void disposeInstrument(Instrument instrument) throws IllegalStateException {
-        for (WeakReference<ProbeNode> ref : probeNodeClones) {
-            final ProbeNode probeNode = ref.get();
-            if (probeNode != null) {
-                probeNode.removeInstrument(instrument);
-            }
-        }
-        invalidateProbeUnchanged();
-    }
-
-    /**
-     * Receives notification that a new clone of the instrument chain associated with this
-     * {@link Probe} has been created as a side-effect of AST cloning.
-     */
-    void registerProbeNodeClone(ProbeNode probeNode) {
-        probeNodeClones.add(new WeakReference<>(probeNode));
-    }
-
-    /**
-     * Gets the currently active <strong><em>before</em></strong> {@linkplain SyntaxTagTrap Tag
-     * Trap} at this Probe. Non{@code -null} if the global
-     * {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this Probe
-     * holds the {@link SyntaxTag} specified in the trap.
-     */
-    SyntaxTagTrap getBeforeTrap() {
-        checkProbeUnchanged();
-        return isBeforeTrapActive ? beforeTagTrap : null;
-    }
-
-    /**
-     * Gets the currently active <strong><em>after</em></strong> {@linkplain SyntaxTagTrap Tag Trap}
-     * at this Probe. Non{@code -null} if the global
-     * {@linkplain Probe#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this Probe
-     * holds the {@link SyntaxTag} specified in the trap.
-     */
-    SyntaxTagTrap getAfterTrap() {
-        checkProbeUnchanged();
-        return isAfterTrapActive ? afterTagTrap : null;
-    }
-
-    /**
-     * To be called wherever in the Probe/Instrument chain there are dependencies on the probe
-     * state's @CompilatonFinal fields.
-     */
-    void checkProbeUnchanged() {
-        try {
-            probeStateUnchangedAssumption.check();
-        } catch (InvalidAssumptionException ex) {
-            // Failure creates an implicit deoptimization
-            // Get the assumption associated with the new probe state
-            this.probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption();
-        }
-    }
-
-    void invalidateProbeUnchanged() {
-        probeStateUnchangedCyclic.invalidate();
-    }
-
-    private void notifyTrapsChanged() {
-        this.isBeforeTrapActive = beforeTagTrap != null && this.isTaggedAs(beforeTagTrap.getTag());
-        this.isAfterTrapActive = afterTagTrap != null && this.isTaggedAs(afterTagTrap.getTag());
-        invalidateProbeUnchanged();
-    }
-
-    private String getTagsDescription() {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        String prefix = "";
-        for (SyntaxTag tag : tags) {
-            sb.append(prefix);
-            prefix = ",";
-            sb.append(tag.toString());
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.instrument.ProbeFailure.Reason;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An exception thrown when {@link Node#probe()} fails because of an implementation failure.
- * <p>
- * Language and tool implementations should ensure that clients of tools never see this exception.
- */
-public class ProbeException extends RuntimeException {
-    static final long serialVersionUID = 1L;
-    private final ProbeFailure failure;
-
-    public ProbeException(Reason reason, Node parent, Node child, Object wrapper) {
-        this.failure = new ProbeFailure(reason, parent, child, wrapper);
-    }
-
-    public ProbeFailure getFailure() {
-        return failure;
-    }
-
-    @Override
-    public String toString() {
-        return failure.getMessage();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Description of a failed attempt to instrument an AST node.
- */
-public final class ProbeFailure {
-
-    public enum Reason {
-
-        /**
-         * Node to be probed has no parent.
-         */
-        NO_PARENT("Node to be probed has no parent"),
-
-        /**
-         * The node to be probed is a wrapper.
-         */
-        WRAPPER_NODE("The node to be probed is a wrapper"),
-
-        /**
-         * The node to be probed returned {@link Node#isInstrumentable()}{@code == false}.
-         */
-        NOT_INSTRUMENTABLE("The node to be project is \"not instrumentable\""),
-
-        /**
-         * No wrapper could be created that is also a {@link Node}.
-         */
-        NO_WRAPPER("No wrapper could be created"),
-
-        /**
-         * Wrapper not assignable to the parent's child field.
-         */
-        WRAPPER_TYPE("Wrapper not assignable to parent's child field");
-
-        final String message;
-
-        private Reason(String message) {
-            this.message = message;
-        }
-
-        public String getMessage() {
-            return message;
-        }
-    }
-
-    private final Reason reason;
-    private final Node parent;
-    private final Node child;
-    private final Object wrapper;
-
-    /**
-     * Description of an internal failure of {@link Node#probe()}.
-     *
-     * @param reason what caused the failure
-     * @param parent the parent, if known, of the child being probed
-     * @param child this child being probed
-     * @param wrapper the {@link WrapperNode} created to implement the probe
-     */
-    public ProbeFailure(Reason reason, Node parent, Node child, Object wrapper) {
-        this.reason = reason;
-        this.parent = parent;
-        this.child = child;
-        this.wrapper = wrapper;
-    }
-
-    /**
-     * @return a short explanation of the failure
-     */
-    public Reason getReason() {
-        return reason;
-    }
-
-    /**
-     * @return the parent, if any, of the node being probed
-     */
-    public Node getParent() {
-        return parent;
-    }
-
-    /**
-     * @return the node being probed
-     */
-    public Node getChild() {
-        return child;
-    }
-
-    /**
-     * @return the {@link WrapperNode} created for the probe attempt
-     */
-    public Object getWrapper() {
-        return wrapper;
-    }
-
-    public String getMessage() {
-        final StringBuilder sb = new StringBuilder(reason.message + ": ");
-        if (parent != null) {
-            sb.append("parent=" + parent.getClass().getSimpleName() + " ");
-            if (child != null) {
-                sb.append("child=" + child.getClass().getSimpleName() + " ");
-                final NodeFieldAccessor field = NodeUtil.findChildField(parent, child);
-                if (field != null) {
-                    sb.append("field=" + field.getName() + " ");
-                }
-            }
-        }
-        if (wrapper != null) {
-            sb.append("wrapper=" + wrapper.getClass().getSimpleName());
-        }
-        return sb.toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * An observer of events related to {@link Probe}s: creating and tagging.
- */
-public interface ProbeListener {
-
-    /**
-     * Notifies that all registered {@link ASTProber}s are about to be applied to a newly
-     * constructed AST.
-     *
-     * @param source source code from which the AST was constructed
-     */
-    void startASTProbing(Source source);
-
-    /**
-     * Notifies that a {@link Probe} has been newly attached to an AST via {@link Node#probe()}.
-     * <p>
-     * There can be no more than one {@link Probe} at a node; this notification will only be
-     * delivered the first time {@linkplain Node#probe() probe()} is called at a particular AST
-     * node. There will also be no notification when the AST to which the Probe is attached is
-     * cloned.
-     */
-    void newProbeInserted(Probe probe);
-
-    /**
-     * Notifies that a {@link SyntaxTag} has been newly added to the set of tags associated with a
-     * {@link Probe} via {@link Probe#tagAs(SyntaxTag, Object)}.
-     * <p>
-     * The {@linkplain SyntaxTag tags} at a {@link Probe} are a <em>set</em>; this notification will
-     * only be delivered the first time a particular {@linkplain SyntaxTag tag} is added at a
-     * {@link Probe}.
-     * <p>
-     * An optional value supplied with {@linkplain Probe#tagAs(SyntaxTag, Object) tagAs(SyntaxTag,
-     * Object)} is reported to all listeners, but not stored. As a consequence, the optional value
-     * will have no effect at all if the tag had already been added.
-     *
-     * @param probe where a tag has been added
-     * @param tag the tag that has been newly added (subsequent additions of the tag are
-     *            unreported).
-     * @param tagValue an optional value associated with the tag for the purposes of reporting.
-     */
-    void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue);
-
-    /**
-     * Notifies that the application of all registered {@link ASTProber}s to a newly constructed AST
-     * has completed.
-     *
-     * @param source source code from which the AST was constructed
-     */
-    void endASTProbing(Source source);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.Instrument.AbstractInstrumentNode;
-import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Implementation class & interface for enabling the attachment of {@linkplain Probe Probes} to
- * Truffle ASTs.
- * <p>
- * A {@link ProbeNode} is the head of a chain of nodes acting on behalf of {@linkplain Instrument
- * instruments}. It is attached to an AST as a child of a guest-language-specific
- * {@link WrapperNode} node.
- * <p>
- * When Truffle clones an AST, the chain, including all attached {@linkplain Instrument instruments}
- * will be cloned along with the {@link WrapperNode} to which it is attached. An instance of
- * {@link Probe} represents abstractly the instrumentation at a particular location in a Guest
- * Language AST, tracks the clones of the chain, and keeps the instrumentation attached to the
- * clones consistent.
- */
-@NodeInfo(cost = NodeCost.NONE)
-public final class ProbeNode extends Node implements TruffleEvents, InstrumentationNode {
-
-    /**
-     * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument
-     * instrumentation} at a particular Guest Language (GL) node. Implementations must extend
-     * {@link Node} and should override {@link Node#isInstrumentable()} to return {@code false}.
-     * <p>
-     * The implementation must be GL-specific. A wrapper <em>decorates</em> a GL AST node (the
-     * wrapper's <em>child</em>) by acting as a transparent <em>proxy</em> with respect to the GL's
-     * execution semantics.
-     * <p>
-     * Instrumentation at the wrapped node is implemented by an instance of {@link ProbeNode}
-     * attached as a second child of the {@link WrapperNode}.
-     * <p>
-     * A wrapper is obliged to notify its attached {@link ProbeNode} when execution events occur at
-     * the wrapped AST node during program execution.
-     * <p>
-     * When a GL AST is cloned, the {@link WrapperNode}, its {@link ProbeNode} and any
-     * {@linkplain Instrument instrumentation} are also cloned; they are in effect part of the GL
-     * AST. An instance of {@link Probe} represents abstractly the instrumentation at a particular
-     * location in a GL AST; it tracks all the copies of the Wrapper and attached instrumentation,
-     * and acts as a single point of access for tools.
-     * <p>
-     * This interface is not intended to be visible as part of the API for tools (instrumentation
-     * clients).
-     * <p>
-     * Implementation guidelines:
-     * <ol>
-     * <li>Each GL implementation should include a WrapperNode implementation; usually only one is
-     * needed.</li>
-     * <li>The wrapper type should descend from the <em>GL-specific node class</em>.</li>
-     * <li>Must have a field: {@code @Child private <GL>Node child;}</li>
-     * <li>Must have a field: {@code @Child private ProbeNode probeNode;}</li>
-     * <li>The wrapper must act as a <em>proxy</em> for its child, which means implementing every
-     * possible <em>execute-</em> method that gets called on guest language AST node types by their
-     * parents, and passing along each call to its child.</li>
-     * <li>Method {@code Probe getProbe()} should be implemented as {@code probeNode.getProbe();}
-     * <li>Method {@code insertProbe(ProbeNode)} should be implemented as
-     * {@code this.probeNode=insert(newProbeNode);}</li>
-     * <li>Most importantly, Wrappers must be implemented so that Truffle optimization will reduce
-     * their runtime overhead to zero when there are no attached {@link Instrument}s.</li>
-     * </ol>
-     * <p>
-     *
-     * @see Instrument
-     */
-    public interface WrapperNode extends InstrumentationNode {
-
-        /**
-         * Gets the node being "wrapped", i.e. the AST node for which
-         * {@linkplain InstrumentationNode.TruffleEvents execution events} will be reported through
-         * the Instrumentation Framework.
-         */
-        Node getChild();
-
-        /**
-         * Gets the {@link Probe} responsible for installing this wrapper.
-         */
-        Probe getProbe();
-
-        /**
-         * Implementation support for completing a newly created wrapper node.
-         */
-        void insertProbe(ProbeNode probeNode);
-    }
-
-    /**
-     * Create a new {@link Probe} associated with, and attached to, a Guest Language specific
-     * instance of {@link WrapperNode}.
-     */
-    public static Probe insertProbe(WrapperNode wrapper) {
-        final SourceSection sourceSection = wrapper.getChild().getSourceSection();
-        final ProbeNode probeNode = new ProbeNode(); // private constructor
-        probeNode.probe = new Probe(probeNode, sourceSection);  // package private access
-        wrapper.insertProbe(probeNode);
-        return probeNode.probe;
-    }
-
-    // Never changed once set.
-    @CompilationFinal Probe probe = null;
-    /**
-     * First {@link AbstractInstrumentNode} node in chain; {@code null} of no instruments in chain.
-     */
-    @Child protected AbstractInstrumentNode firstInstrumentNode;
-
-    @Override
-    public boolean isInstrumentable() {
-        return false;
-    }
-
-    @Override
-    public Node copy() {
-        Node node = super.copy();
-        probe.registerProbeNodeClone((ProbeNode) node);
-        return node;
-    }
-
-    /**
-     * @return the {@link Probe} permanently associated with this {@link ProbeNode}.
-     */
-    public Probe getProbe() {
-        return probe;
-    }
-
-    public void enter(Node node, VirtualFrame vFrame) {
-        this.probe.checkProbeUnchanged();
-        final SyntaxTagTrap beforeTagTrap = probe.getBeforeTrap();
-        if (beforeTagTrap != null) {
-            beforeTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
-        }
-        if (firstInstrumentNode != null) {
-            firstInstrumentNode.enter(node, vFrame);
-        }
-    }
-
-    public void returnVoid(Node node, VirtualFrame vFrame) {
-        this.probe.checkProbeUnchanged();
-        if (firstInstrumentNode != null) {
-            firstInstrumentNode.returnVoid(node, vFrame);
-        }
-        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
-        if (afterTagTrap != null) {
-            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
-        }
-    }
-
-    public void returnValue(Node node, VirtualFrame vFrame, Object result) {
-        this.probe.checkProbeUnchanged();
-        if (firstInstrumentNode != null) {
-            firstInstrumentNode.returnValue(node, vFrame, result);
-        }
-        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
-        if (afterTagTrap != null) {
-            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
-        }
-    }
-
-    public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
-        this.probe.checkProbeUnchanged();
-        if (firstInstrumentNode != null) {
-            firstInstrumentNode.returnExceptional(node, vFrame, exception);
-        }
-        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
-        if (afterTagTrap != null) {
-            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
-        }
-    }
-
-    public String instrumentationInfo() {
-        return "Standard probe";
-    }
-
-    /**
-     * Gets the guest-language AST node to which this Probe is attached.
-     */
-    Node getProbedNode() {
-        return ((WrapperNode) this.getParent()).getChild();
-    }
-
-    /**
-     * Adds an {@link AbstractInstrumentNode} to this chain.
-     */
-    @TruffleBoundary
-    void addInstrument(Instrument instrument) {
-        assert instrument.getProbe() == probe;
-        // The existing chain of nodes may be empty
-        // Attach the modified chain.
-        firstInstrumentNode = insert(instrument.addToChain(firstInstrumentNode));
-    }
-
-    /**
-     * Removes an instrument from this chain of instruments.
-     *
-     * @throws RuntimeException if no matching instrument is found,
-     */
-    @TruffleBoundary
-    void removeInstrument(Instrument instrument) {
-        assert instrument.getProbe() == probe;
-        final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrumentNode);
-        if (modifiedChain == null) {
-            firstInstrumentNode = null;
-        } else {
-            firstInstrumentNode = insert(modifiedChain);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Controls breaking out of all executions and ending Truffle execution.
- */
-public final class QuitException extends ControlFlowException {
-
-    private static final long serialVersionUID = -4301115629772778413L;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.source.*;
-
-/**
- * A receiver of Truffle execution events that can act on behalf of an external client.
- * <p>
- * The {@link Probe} instance provides access to the {@link SourceSection} associated with the
- * event, as well as any {@link SyntaxTag}s that have been applied at that program's location.
- * <p>
- * This is the simplest kind of listener, suitable for clients that need no other information about
- * the program's execution state at the time of the event. Clients that require access to the AST
- * execution state should use {@link StandardInstrumentListener}.
- * <p>
- * Clients are free, of course, to record additional information in the listener implementation that
- * carries additional information about the context and reason for the particular {@link Instrument}
- * that is to be created from the listener.
- */
-public interface SimpleInstrumentListener {
-
-    /**
-     * Receive notification that a program location is about to be executed.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void enter(Probe probe);
-
-    /**
-     * Receive notification that a program location's {@code void}-valued execution has just
-     * completed.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnVoid(Probe probe);
-
-    /**
-     * Receive notification that a program location's execution has just completed and returned a
-     * value (boxed if primitive).
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnValue(Probe probe, Object result);
-
-    /**
-     * Receive notification that a program location's execution has just thrown an exception.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnExceptional(Probe probe, Exception exception);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * A receiver of Truffle execution events that can act on behalf of an external client.
- * <p>
- * The {@link Probe} argument provides access to the {@link SourceSection} associated with the
- * event, as well as any {@link SyntaxTag}s that have been applied at that AST node.
- * <p>
- * This listener is designed for clients that also require access to the AST execution state at the
- * time of the event. Clients that do not require access to the AST execution state should use the
- * {@link SimpleInstrumentListener}.
- * <p>
- * Clients are free, of course, to record additional information in the listener implementation that
- * carries additional information about the context and reason for the particular {@link Instrument}
- * that is to be created from the listener.
- */
-public interface StandardInstrumentListener {
-
-    /**
-     * Receive notification that an AST node's execute method is about to be called.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void enter(Probe probe, Node node, VirtualFrame vFrame);
-
-    /**
-     * Receive notification that an AST Node's {@code void}-valued execute method has just returned.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnVoid(Probe probe, Node node, VirtualFrame vFrame);
-
-    /**
-     * Receive notification that an AST Node's execute method has just returned a value (boxed if
-     * primitive).
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result);
-
-    /**
-     * Receive notification that an AST Node's execute method has just thrown an exception.
-     * <p>
-     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
-     */
-    void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-/**
- * A somewhat language-agnostic set of user-sensible syntactic categories, suitable for conventional
- * imperative languages, and is being developed incrementally.
- * <p>
- * The need for alternative sets of tags is likely to arise, perhaps for other families of languages
- * (for example for mostly expression-oriented languages) or even for specific languages.
- *
- * @see Probe
- */
-public enum StandardSyntaxTag implements SyntaxTag {
-
-    /**
-     * Marker for a variable assignment.
-     */
-    ASSIGNMENT("assignment", "a variable assignment"),
-
-    /**
-     * Marker for a call site.
-     */
-    CALL("call", "a method/procedure call site"),
-
-    /**
-     * Marker for a location where a guest language exception is about to be thrown.
-     */
-    THROW("throw", "creator of an exception"),
-
-    /**
-     * Marker for a location where ordinary "stepping" should halt.
-     */
-    STATEMENT("statement", "basic unit of the language, suitable for \"stepping\" in a debugger"),
-
-    /**
-     * Marker for the start of the body of a method.
-     */
-    START_METHOD("start-method", "start of the body of a method"),
-
-    /**
-     * Marker for the start of the body of a loop.
-     */
-    START_LOOP("start-loop", "start of the body of a loop"),
-
-    /**
-     * Marker that is attached to some arbitrary locations that appear often-enough in an AST so
-     * that a location with this tag is regularly executed. Could be the start of method and loop
-     * bodies. May be used to implement some kind of safepoint functionality.
-     */
-    PERIODIC("periodic", "arbitrary locations that appear often-enough in an AST so that a location with this tag is regularly executed");
-
-    private final String name;
-    private final String description;
-
-    private StandardSyntaxTag(String name, String description) {
-        this.name = name;
-        this.description = description;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTag.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-/**
- * Program element "tags", presumed to be singletons (best implemented as enums) that define
- * user-visible behavior for debugging and other simple tools. These categories should correspond to
- * program structures, for example "statement" and "assignment", that are meaningful
- * ("human-sensible") to guest language programmers.
- * <p>
- * An untagged Truffle node should be understood as an artifact of the guest language implementation
- * and should not be visible to guest language programmers. Nodes may also have more than one tag,
- * for example a variable assignment that is also a statement. Finally, the assignment of tags to
- * nodes could depending on the use-case of whatever tool is using them.
- *
- * @see Probe
- * @see StandardSyntaxTag
- */
-public interface SyntaxTag {
-
-    /**
-     * Human-friendly name of guest language program elements belonging to the category, e.g.
-     * "statement".
-     */
-    String name();
-
-    /**
-     * Criteria and example uses for the tag.
-     */
-    String getDescription();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A trap that can be set to interrupt execution at probed nodes carrying a specific tag.
- *
- * @see Probe
- */
-public abstract class SyntaxTagTrap {
-
-    private final SyntaxTag tag;
-
-    protected SyntaxTagTrap(SyntaxTag tag) {
-        this.tag = tag;
-    }
-
-    public final SyntaxTag getTag() {
-        return tag;
-    }
-
-    /**
-     * Notifies that execution is halted at a node with the specified tag.
-     */
-    public abstract void tagTrappedAt(Node node, MaterializedFrame frame);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-/**
- * Access to language-specific information and execution services for external tools.
- */
-public interface ToolSupportProvider {
-
-    /**
-     * Gets visualization services for language-specific information.
-     */
-    Visualizer getVisualizer();
-
-    /**
-     * Enables AST probing on all subsequently created ASTs (sources parsed).
-     *
-     * @param astProber optional AST prober to enable; the default for the language used if
-     *            {@code null}
-     */
-    void enableASTProbing(ASTProber astProber);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Visualization services for the benefit of instrumentation-based tools, possibly specialized for
- * each guest language and possibly specialized for relevant information from the underlying Truffle
- * implementation.
- * <p>
- * <strong>Disclaimer:</strong> experimental interface under development.
- */
-public interface Visualizer {
-
-    // TODO (mlvdv) "Visualizer" is misleading: rename.
-    /**
-     * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest
-     * language implementation.
-     */
-    ASTPrinter getASTPrinter();
-
-    /**
-     * A short description of a source location in terms of source + line number.
-     */
-    String displaySourceLocation(Node node);
-
-    /**
-     * Describes the name of the method containing a node.
-     */
-    String displayMethodName(Node node);
-
-    /**
-     * The name of the method.
-     */
-    String displayCallTargetName(CallTarget callTarget);
-
-    /**
-     * Converts a value in the guest language to a display string. If
-     * 
-     * @param trim if {@code > 0}, them limit size of String to either the value of trim or the
-     *            number of characters in the first line, whichever is lower.
-     */
-    String displayValue(Object value, int trim);
-
-    /**
-     * Converts a slot identifier in the guest language to a display string.
-     */
-    String displayIdentifier(FrameSlot slot);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument.impl;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-import com.oracle.truffle.api.source.*;
-
-/**
- * A language-agnostic for printing out various pieces of a Truffle AST.
- */
-public class DefaultASTPrinter implements ASTPrinter {
-
-    public DefaultASTPrinter() {
-    }
-
-    public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) {
-        printTree(p, node, maxDepth, markNode, 1);
-        p.println();
-        p.flush();
-    }
-
-    public String printTreeToString(Node node, int maxDepth, Node markNode) {
-        StringWriter out = new StringWriter();
-        printTree(new PrintWriter(out), node, maxDepth, markNode);
-        return out.toString();
-    }
-
-    public String printTreeToString(Node node, int maxDepth) {
-        return printTreeToString(node, maxDepth, null);
-    }
-
-    public String printNodeWithInstrumentation(Node node) {
-        if (node == null) {
-            return "null";
-        }
-        final StringBuilder sb = new StringBuilder();
-        sb.append(nodeName(node));
-        sb.append("(");
-        if (node instanceof InstrumentationNode) {
-            sb.append(instrumentInfo((InstrumentationNode) node));
-        }
-        sb.append(sourceInfo(node));
-        sb.append(NodeUtil.printSyntaxTags(node));
-        sb.append(")");
-        final Node parent = node.getParent();
-        if (parent instanceof WrapperNode) {
-            final WrapperNode wrapper = (WrapperNode) parent;
-            sb.append(" Probed");
-            sb.append(NodeUtil.printSyntaxTags(wrapper));
-        }
-        return sb.toString();
-    }
-
-    protected void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
-        if (node == null) {
-            p.print("null");
-            return;
-        }
-
-        p.print(nodeName(node));
-
-        p.print("(");
-
-        if (node instanceof InstrumentationNode) {
-            p.print(instrumentInfo((InstrumentationNode) node));
-        }
-
-        p.print(sourceInfo(node));
-
-        p.print(NodeUtil.printSyntaxTags(node));
-
-        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
-
-        for (NodeFieldAccessor field : NodeClass.get(node).getFields()) {
-            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
-                childFields.add(field);
-            } else if (field.getKind() == NodeFieldKind.DATA) {
-                // p.print(sep);
-                // sep = ", ";
-                //
-                // final String fieldName = field.getName();
-                // switch (fieldName) {
-                //
-                // }
-                // p.print(fieldName);
-                // p.print(" = ");
-                // p.print(field.loadValue(node));
-            }
-        }
-        p.print(")");
-
-        if (level <= maxDepth) {
-
-            if (childFields.size() != 0) {
-                p.print(" {");
-                for (NodeFieldAccessor field : childFields) {
-
-                    Object value = field.loadValue(node);
-                    if (value == null) {
-                        printNewLine(p, level);
-                        p.print(field.getName());
-                        p.print(" = null ");
-                    } else if (field.getKind() == NodeFieldKind.CHILD) {
-                        printChild(p, maxDepth, markNode, level, field, value);
-                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
-                        printChildren(p, maxDepth, markNode, level, field, value);
-                    } else {
-                        printNewLine(p, level);
-                        p.print(field.getName());
-                    }
-                }
-                printNewLine(p, level - 1);
-                p.print("}");
-            }
-        }
-    }
-
-    protected void printChildren(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
-        printNewLine(p, level);
-        p.print(field.getName());
-        Node[] children = (Node[]) value;
-        p.print(" = [");
-        String sep = "";
-        for (Node child : children) {
-            p.print(sep);
-            sep = ", ";
-            printTree(p, child, maxDepth, markNode, level + 1);
-        }
-        p.print("]");
-    }
-
-    protected void printChild(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
-        final Node valueNode = (Node) value;
-        printNewLine(p, level, valueNode == markNode);
-        p.print(field.getName());
-        p.print(" = ");
-        printTree(p, valueNode, maxDepth, markNode, level + 1);
-    }
-
-    protected static void printNewLine(PrintWriter p, int level, boolean mark) {
-        p.println();
-        for (int i = 0; i < level; i++) {
-            if (mark && i == 0) {
-                p.print(" -->");
-            } else {
-                p.print("    ");
-            }
-        }
-    }
-
-    protected static void printNewLine(PrintWriter p, int level) {
-        printNewLine(p, level, false);
-    }
-
-    protected static String nodeName(Node node) {
-        return node.getClass().getSimpleName();
-    }
-
-    protected static String sourceInfo(Node node) {
-        final SourceSection src = node.getSourceSection();
-        if (src != null) {
-            if (src instanceof NullSourceSection) {
-                final NullSourceSection nullSection = (NullSourceSection) src;
-                return nullSection.getShortDescription();
-            } else {
-                return src.getSource().getName() + ":" + src.getStartLine();
-            }
-        }
-        return "";
-    }
-
-    protected static String instrumentInfo(InstrumentationNode node) {
-        final String info = node.instrumentationInfo();
-        return info == null ? "" : info;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultProbeListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument.impl;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-
-public abstract class DefaultProbeListener implements ProbeListener {
-
-    public void startASTProbing(Source source) {
-    }
-
-    public void newProbeInserted(Probe probe) {
-    }
-
-    public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-    }
-
-    public void endASTProbing(Source source) {
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument.impl;
-
-import com.oracle.truffle.api.instrument.*;
-
-/**
- * A listener for Truffle execution events that provides a no-op implementation of every event.
- */
-public class DefaultSimpleInstrumentListener implements SimpleInstrumentListener {
-
-    public void enter(Probe probe) {
-    }
-
-    public void returnVoid(Probe probe) {
-    }
-
-    public void returnValue(Probe probe, Object result) {
-    }
-
-    public void returnExceptional(Probe probe, Exception exception) {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument.impl;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A listener for AST {@linkplain StandardInstrumentListener execution events} that provides a no-op
- * implementation of every event.
- */
-public class DefaultStandardInstrumentListener implements StandardInstrumentListener {
-
-    public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-    }
-
-    public void returnVoid(Probe probe, Node node, VirtualFrame vFrame) {
-    }
-
-    public void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) {
-    }
-
-    public void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.instrument.impl;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-public class DefaultVisualizer implements Visualizer {
-
-    private final ASTPrinter astPrinter;
-
-    public DefaultVisualizer() {
-        this.astPrinter = new DefaultASTPrinter();
-    }
-
-    public ASTPrinter getASTPrinter() {
-        return astPrinter;
-    }
-
-    public String displaySourceLocation(Node node) {
-        if (node == null) {
-            return "<unknown>";
-        }
-        SourceSection section = node.getSourceSection();
-        boolean estimated = false;
-        if (section == null) {
-            section = node.getEncapsulatingSourceSection();
-            estimated = true;
-        }
-        if (section == null) {
-            return "<error: source location>";
-        }
-        return section.getShortDescription() + (estimated ? "~" : "");
-    }
-
-    public String displayMethodName(Node node) {
-        if (node == null) {
-            return null;
-        }
-        RootNode root = node.getRootNode();
-        if (root == null) {
-            return "unknown";
-        }
-        return root.getCallTarget().toString();
-    }
-
-    public String displayCallTargetName(CallTarget callTarget) {
-        return callTarget.toString();
-    }
-
-    public String displayValue(Object value, int trim) {
-        return trim(value.toString(), trim);
-    }
-
-    public String displayIdentifier(FrameSlot slot) {
-        return slot.getIdentifier().toString();
-    }
-
-    /**
-     * Trims text if {@code trim > 0} to the shorter of {@code trim} or the length of the first line
-     * of test. Identity if {@code trim <= 0}.
-     */
-    protected String trim(String text, int trim) {
-        if (trim == 0) {
-            return text;
-        }
-        final String[] lines = text.split("\n");
-        String result = lines[0];
-        if (lines.length == 1) {
-            if (result.length() <= trim) {
-                return result;
-            }
-            if (trim <= 3) {
-                return result.substring(0, Math.min(result.length() - 1, trim - 1));
-            } else {
-                return result.substring(0, trim - 4) + "...";
-            }
-        }
-        return (result.length() < trim - 3 ? result : result.substring(0, trim - 4)) + "...";
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-/**
- * An exception thrown to model control flow in a Truffle interpreter. The Truffle optimizer has
- * special knowledge of this exception class for performance optimizations.
- */
-public class ControlFlowException extends RuntimeException {
-
-    private static final long serialVersionUID = 3676602078425211386L;
-
-    /**
-     * Creates an exception thrown to model control flow.
-     */
-    public ControlFlowException() {
-        /*
-         * We use the super constructor that initializes the cause to null. Without that, the cause
-         * would be this exception itself. This helps escape analysis: it avoids the circle of an
-         * object pointing to itself.
-         */
-        super((Throwable) null);
-    }
-
-    /**
-     * For performance reasons, this exception does not record any stack trace information.
-     */
-    @SuppressWarnings("sync-override")
-    @Override
-    public final Throwable fillInStackTrace() {
-        return null;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Represents a direct call to a {@link CallTarget}. Direct calls are calls for which the
- * {@link CallTarget} remains the same for each consecutive call. This part of the Truffle API
- * enables the runtime system to perform additional optimizations on direct calls.
- *
- * Optimizations that can be applied to a {@link DirectCallNode} are inlining and call site
- * sensitive AST duplication. Inlining inlines this call site into the call graph of the parent
- * {@link CallTarget}. Call site sensitive AST duplication duplicates the {@link CallTarget} in an
- * uninitialized state to collect call site sensitive profiling information.
- *
- * Please note: This class is not intended to be subclassed by guest language implementations.
- *
- * @see IndirectCallNode for calls with a non-constant target
- * @see TruffleRuntime#createDirectCallNode(CallTarget)
- * @see #forceInlining()
- * @see #cloneCallTarget()
- */
-public abstract class DirectCallNode extends Node {
-
-    protected final CallTarget callTarget;
-
-    protected DirectCallNode(CallTarget callTarget) {
-        this.callTarget = callTarget;
-    }
-
-    /**
-     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
-     *
-     * @param arguments the arguments that should be passed to the callee
-     * @return the return result of the call
-     */
-    public abstract Object call(VirtualFrame frame, Object[] arguments);
-
-    /**
-     * Returns the originally supplied {@link CallTarget} when this call node was created. Please
-     * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is
-     * called. For that use {@link #getCurrentCallTarget()} instead.
-     *
-     * @return the {@link CallTarget} provided.
-     */
-    public CallTarget getCallTarget() {
-        return callTarget;
-    }
-
-    /**
-     * Returns <code>true</code> if the underlying runtime system supports inlining for the
-     * {@link CallTarget} in this {@link DirectCallNode}.
-     *
-     * @return true if inlining is supported.
-     */
-    public abstract boolean isInlinable();
-
-    /**
-     * Returns <code>true</code> if the {@link CallTarget} is forced to be inlined. A
-     * {@link DirectCallNode} can either be inlined manually by invoking {@link #forceInlining()} or
-     * by the runtime system which may at any point decide to inline.
-     *
-     * @return true if this method was inlined else false.
-     */
-    public abstract boolean isInliningForced();
-
-    /**
-     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
-     * runtime system does not support inlining or it is already inlined this method has no effect.
-     * The runtime system may decide to not inline calls which were forced to inline.
-     */
-    public abstract void forceInlining();
-
-    /**
-     * Returns true if the runtime system has decided to inline this call-site. If the
-     * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the
-     * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the
-     * runtime system supports inlining. The runtime system may also decide to not inline calls
-     * which were forced to inline.
-     *
-     * @deprecated we do not expose this information any longer. returns always false.
-     */
-    @SuppressWarnings("static-method")
-    @Deprecated
-    public final boolean isInlined() {
-        return false;
-    }
-
-    /**
-     * Returns <code>true</code> if the runtime system supports cloning and the {@link RootNode}
-     * returns <code>true</code> in {@link RootNode#isCloningAllowed()}.
-     *
-     * @return <code>true</code> if the target is allowed to be cloned.
-     */
-    public abstract boolean isCallTargetCloningAllowed();
-
-    /**
-     * Clones the {@link CallTarget} instance returned by {@link #getCallTarget()} in an
-     * uninitialized state for this {@link DirectCallNode}. This can be sensible to gather call site
-     * sensitive profiling information for this {@link DirectCallNode}. If
-     * {@link #isCallTargetCloningAllowed()} returns <code>false</code> this method has no effect
-     * and returns <code>false</code>.
-     */
-    public abstract boolean cloneCallTarget();
-
-    /**
-     * Returns <code>true</code> if the target of the {@link DirectCallNode} was cloned by the
-     * runtime system or by the guest language implementation.
-     *
-     * @return if the target was split
-     */
-    public final boolean isCallTargetCloned() {
-        return getClonedCallTarget() != null;
-    }
-
-    /**
-     * Returns the split {@link CallTarget} if this call site's {@link CallTarget} is cloned.
-     *
-     * @return the split {@link CallTarget}
-     */
-    public abstract CallTarget getClonedCallTarget();
-
-    /**
-     * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the
-     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
-     * {@link #getClonedCallTarget()}.
-     *
-     * @return the used {@link CallTarget} when node is called
-     */
-    public CallTarget getCurrentCallTarget() {
-        CallTarget split = getClonedCallTarget();
-        if (split != null) {
-            return split;
-        } else {
-            return getCallTarget();
-        }
-    }
-
-    /**
-     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
-     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
-     * {@link RootNode} this method returns <code>null</code>.
-     *
-     * @see #getCurrentCallTarget()
-     * @return the root node of the used call target
-     */
-    public final RootNode getCurrentRootNode() {
-        CallTarget target = getCurrentCallTarget();
-        if (target instanceof RootCallTarget) {
-            return ((RootCallTarget) target).getRootNode();
-        }
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(target=%s)", getClass().getSimpleName(), getCurrentCallTarget());
-    }
-
-    public static DirectCallNode create(CallTarget target) {
-        return Truffle.getRuntime().createDirectCallNode(target);
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.lang.annotation.*;
-
-/**
- * Specifies for a method that the loops with constant number of invocations should be fully
- * unrolled.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface ExplodeLoop {
-    boolean merge() default false;
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,420 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.net.*;
-import java.util.*;
-
-import javax.xml.parsers.*;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.*;
-import javax.xml.transform.stream.*;
-
-import org.w3c.dom.*;
-
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-
-/**
- * Utility class for creating output for the ideal graph visualizer.
- */
-public class GraphPrintVisitor {
-
-    public static final String GraphVisualizerAddress = "127.0.0.1";
-    public static final int GraphVisualizerPort = 4444;
-
-    private Document dom;
-    private Map<Object, Element> nodeMap;
-    private List<Element> edgeList;
-    private Map<Object, Element> prevNodeMap;
-    private int id;
-    private Element graphDocument;
-    private Element groupElement;
-    private Element graphElement;
-    private Element nodesElement;
-    private Element edgesElement;
-
-    public GraphPrintVisitor() {
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        try {
-            DocumentBuilder db = dbf.newDocumentBuilder();
-
-            dom = db.newDocument();
-        } catch (ParserConfigurationException ex) {
-            throw new RuntimeException(ex);
-        }
-
-        graphDocument = dom.createElement("graphDocument");
-        dom.appendChild(graphDocument);
-    }
-
-    public GraphPrintVisitor beginGroup(String groupName) {
-        groupElement = dom.createElement("group");
-        graphDocument.appendChild(groupElement);
-        Element properties = dom.createElement("properties");
-        groupElement.appendChild(properties);
-
-        if (!groupName.isEmpty()) {
-            // set group name
-            Element propName = dom.createElement("p");
-            propName.setAttribute("name", "name");
-            propName.setTextContent(groupName);
-            properties.appendChild(propName);
-        }
-
-        // forget old nodes
-        nodeMap = prevNodeMap = null;
-        edgeList = null;
-
-        return this;
-    }
-
-    public GraphPrintVisitor beginGraph(String graphName) {
-        if (null == groupElement) {
-            beginGroup("");
-        } else if (null != prevNodeMap) {
-            // TODO: difference (create removeNode,removeEdge elements)
-        }
-
-        graphElement = dom.createElement("graph");
-        groupElement.appendChild(graphElement);
-        Element properties = dom.createElement("properties");
-        graphElement.appendChild(properties);
-        nodesElement = dom.createElement("nodes");
-        graphElement.appendChild(nodesElement);
-        edgesElement = dom.createElement("edges");
-        graphElement.appendChild(edgesElement);
-
-        // set graph name
-        Element propName = dom.createElement("p");
-        propName.setAttribute("name", "name");
-        propName.setTextContent(graphName);
-        properties.appendChild(propName);
-
-        // save old nodes
-        prevNodeMap = nodeMap;
-        nodeMap = new IdentityHashMap<>();
-        edgeList = new ArrayList<>();
-
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        if (null != dom) {
-            try {
-                Transformer tr = TransformerFactory.newInstance().newTransformer();
-                tr.setOutputProperty(OutputKeys.INDENT, "yes");
-                tr.setOutputProperty(OutputKeys.METHOD, "xml");
-                tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-                StringWriter strWriter = new StringWriter();
-                tr.transform(new DOMSource(dom), new StreamResult(strWriter));
-                return strWriter.toString();
-            } catch (TransformerException e) {
-                e.printStackTrace();
-            }
-        }
-        return "";
-    }
-
-    public void printToFile(File f) {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.INDENT, "yes");
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-            tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f)));
-        } catch (TransformerException | FileNotFoundException e) {
-            e.printStackTrace();
-        }
-    }
-
-    public void printToSysout() {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.INDENT, "yes");
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
-
-            tr.transform(new DOMSource(dom), new StreamResult(System.out));
-        } catch (TransformerException e) {
-            e.printStackTrace();
-        }
-    }
-
-    public void printToNetwork(boolean ignoreErrors) {
-        try {
-            Transformer tr = TransformerFactory.newInstance().newTransformer();
-            tr.setOutputProperty(OutputKeys.METHOD, "xml");
-
-            Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort);
-            BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
-            tr.transform(new DOMSource(dom), new StreamResult(stream));
-        } catch (TransformerException | IOException e) {
-            if (!ignoreErrors) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    private String nextId() {
-        return String.valueOf(id++);
-    }
-
-    private String oldOrNextId(Object node) {
-        if (null != prevNodeMap && prevNodeMap.containsKey(node)) {
-            Element nodeElem = prevNodeMap.get(node);
-            return nodeElem.getAttribute("id");
-        } else {
-            return nextId();
-        }
-    }
-
-    protected Element getElementByObject(Object op) {
-        return nodeMap.get(op);
-    }
-
-    protected void createElementForNode(Object node) {
-        boolean exists = nodeMap.containsKey(node);
-        if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) {
-            Element nodeElem = dom.createElement("node");
-            nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId());
-            nodeMap.put(node, nodeElem);
-            Element properties = dom.createElement("properties");
-            nodeElem.appendChild(properties);
-            nodesElement.appendChild(nodeElem);
-
-            setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
-            NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
-            if (nodeInfo != null) {
-                setNodeProperty(node, "cost", nodeInfo.cost());
-                if (!nodeInfo.shortName().isEmpty()) {
-                    setNodeProperty(node, "shortName", nodeInfo.shortName());
-                }
-            }
-            setNodeProperty(node, "class", node.getClass().getSimpleName());
-            if (node instanceof Node) {
-                readNodeProperties((Node) node);
-                copyDebugProperties((Node) node);
-            }
-        }
-    }
-
-    private Element getPropertyElement(Object node, String propertyName) {
-        Element nodeElem = getElementByObject(node);
-        Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0);
-        if (propertiesElem == null) {
-            return null;
-        }
-
-        NodeList propList = propertiesElem.getElementsByTagName("p");
-        for (int i = 0; i < propList.getLength(); i++) {
-            Element p = (Element) propList.item(i);
-            if (propertyName.equals(p.getAttribute("name"))) {
-                return p;
-            }
-        }
-        return null;
-    }
-
-    protected void setNodeProperty(Object node, String propertyName, Object value) {
-        Element nodeElem = getElementByObject(node);
-        Element propElem = getPropertyElement(node, propertyName); // if property exists, replace
-                                                                   // its value
-        if (null == propElem) { // if property doesn't exist, create one
-            propElem = dom.createElement("p");
-            propElem.setAttribute("name", propertyName);
-            nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem);
-        }
-        propElem.setTextContent(String.valueOf(value));
-    }
-
-    private void copyDebugProperties(Node node) {
-        Map<String, Object> debugProperties = node.getDebugProperties();
-        for (Map.Entry<String, Object> property : debugProperties.entrySet()) {
-            setNodeProperty(node, property.getKey(), property.getValue());
-        }
-    }
-
-    private void readNodeProperties(Node node) {
-        NodeFieldAccessor[] fields = node.getNodeClass().getFields();
-        for (NodeFieldAccessor field : fields) {
-            if (field.getKind() == NodeFieldKind.DATA) {
-                String key = field.getName();
-                if (getPropertyElement(node, key) == null) {
-                    Object value = field.loadValue(node);
-                    setNodeProperty(node, key, value);
-                }
-            }
-        }
-    }
-
-    protected void connectNodes(Object a, Object b, String label) {
-        if (nodeMap.get(a) == null || nodeMap.get(b) == null) {
-            return;
-        }
-
-        String fromId = nodeMap.get(a).getAttribute("id");
-        String toId = nodeMap.get(b).getAttribute("id");
-
-        // count existing to-edges
-        int count = 0;
-        for (Element e : edgeList) {
-            if (e.getAttribute("to").equals(toId)) {
-                ++count;
-            }
-        }
-
-        Element edgeElem = dom.createElement("edge");
-        edgeElem.setAttribute("from", fromId);
-        edgeElem.setAttribute("to", toId);
-        edgeElem.setAttribute("index", String.valueOf(count));
-        if (label != null) {
-            edgeElem.setAttribute("label", label);
-        }
-        edgesElement.appendChild(edgeElem);
-        edgeList.add(edgeElem);
-    }
-
-    public GraphPrintVisitor visit(Object node) {
-        if (null == graphElement) {
-            beginGraph("truffle tree");
-        }
-
-        // if node is visited once again, skip
-        if (getElementByObject(node) != null && NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) == null) {
-            return this;
-        }
-
-        // respect node's custom handler
-        if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) {
-            Class<? extends GraphPrintHandler> customHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler();
-            try {
-                GraphPrintHandler customHandler = customHandlerClass.newInstance();
-                customHandler.visit(node, new GraphPrintAdapter());
-            } catch (InstantiationException | IllegalAccessException e) {
-                assert false : e;
-            }
-        } else if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) {
-            // ignore
-        } else {
-            // default handler
-            createElementForNode(node);
-
-            if (node instanceof Node) {
-                for (Map.Entry<String, Node> child : findNamedNodeChildren((Node) node).entrySet()) {
-                    visit(child.getValue());
-                    connectNodes(node, child.getValue(), child.getKey());
-                }
-            }
-        }
-
-        return this;
-    }
-
-    private static LinkedHashMap<String, Node> findNamedNodeChildren(Node node) {
-        LinkedHashMap<String, Node> nodes = new LinkedHashMap<>();
-        NodeClass nodeClass = node.getNodeClass();
-
-        for (NodeFieldAccessor field : nodeClass.getFields()) {
-            NodeFieldKind kind = field.getKind();
-            if (kind == NodeFieldKind.CHILD || kind == NodeFieldKind.CHILDREN) {
-                Object value = field.loadValue(node);
-                if (value != null) {
-                    if (kind == NodeFieldKind.CHILD) {
-                        nodes.put(field.getName(), (Node) value);
-                    } else if (kind == NodeFieldKind.CHILDREN) {
-                        Object[] children = (Object[]) value;
-                        for (int i = 0; i < children.length; i++) {
-                            if (children[i] != null) {
-                                nodes.put(field.getName() + "[" + i + "]", (Node) children[i]);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        return nodes;
-    }
-
-    public class GraphPrintAdapter {
-
-        public void createElementForNode(Object node) {
-            GraphPrintVisitor.this.createElementForNode(node);
-        }
-
-        public void visit(Object node) {
-            GraphPrintVisitor.this.visit(node);
-        }
-
-        public void connectNodes(Object node, Object child) {
-            GraphPrintVisitor.this.connectNodes(node, child, null);
-        }
-
-        public void setNodeProperty(Object node, String propertyName, Object value) {
-            GraphPrintVisitor.this.setNodeProperty(node, propertyName, value);
-        }
-    }
-
-    public interface GraphPrintHandler {
-
-        void visit(Object node, GraphPrintAdapter gPrinter);
-    }
-
-    public interface ChildSupplier {
-
-        /** Supplies an additional child if available. */
-        Object startNode(Object callNode);
-
-        void endNode(Object callNode);
-
-    }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.TYPE)
-    public @interface CustomGraphPrintHandler {
-
-        Class<? extends GraphPrintHandler> handler();
-    }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.TYPE)
-    public @interface NullGraphPrintHandler {
-    }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.TYPE)
-    public @interface GraphDuplicate {
-    }
-
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.FIELD)
-    public @interface HiddenField {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Represents an indirect call to a {@link CallTarget}. Indirect calls are calls for which the
- * {@link CallTarget} may change dynamically for each consecutive call. This part of the Truffle API
- * enables the runtime system to perform additional optimizations on indirect calls.
- *
- * Please note: This class is not intended to be sub classed by guest language implementations.
- *
- * @see DirectCallNode for faster calls with a constantly known {@link CallTarget}.
- */
-public abstract class IndirectCallNode extends Node {
-
-    /**
-     * Performs an indirect call to the given {@link CallTarget} target with the provided arguments.
-     *
-     * @param frame the caller frame
-     * @param target the {@link CallTarget} to call
-     * @param arguments the arguments to provide
-     * @return the return value of the call
-     */
-    public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments);
-
-    public static IndirectCallNode create() {
-        return Truffle.getRuntime().createIndirectCallNode();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InvalidAssumptionException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-/**
- * An exception that should be thrown if an assumption is checked and the check fails. The Truffle
- * optimizer has special knowledge of this exception class and will never compile a catch block that
- * catches this exception type.
- */
-public final class InvalidAssumptionException extends SlowPathException {
-
-    private static final long serialVersionUID = -6801338218909717979L;
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Experimental API: may change significantly without notice.
- */
-public abstract class LoopNode extends Node {
-
-    public abstract void executeLoop(VirtualFrame frame);
-
-    public abstract RepeatingNode getRepeatingNode();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,588 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.lang.annotation.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-
-/**
- * Abstract base class for all Truffle nodes.
- */
-public abstract class Node implements NodeInterface, Cloneable {
-
-    private final NodeClass nodeClass;
-    @CompilationFinal private Node parent;
-    @CompilationFinal private SourceSection sourceSection;
-
-    /**
-     * Marks array fields that are children of this node.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    public @interface Children {
-    }
-
-    /**
-     * Marks fields that represent child nodes of this node.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target({ElementType.FIELD})
-    public @interface Child {
-    }
-
-    protected Node() {
-        this(null);
-    }
-
-    protected Node(SourceSection sourceSection) {
-        CompilerAsserts.neverPartOfCompilation();
-        this.sourceSection = sourceSection;
-        this.nodeClass = NodeClass.get(getClass());
-        if (TruffleOptions.TraceASTJSON) {
-            JSONHelper.dumpNewNode(this);
-        }
-    }
-
-    /**
-     * Assigns a link to a guest language source section to this node.
-     *
-     * @param section the object representing a section in guest language source code
-     */
-    public final void assignSourceSection(SourceSection section) {
-        if (sourceSection != null) {
-            // Patch this test during the transition to constructor-based
-            // source attribution, which would otherwise trigger this
-            // exception. This method will eventually be deprecated.
-            if (getSourceSection() != section) {
-                throw new IllegalStateException("Source section is already assigned. Old: " + getSourceSection() + ", new: " + section);
-            }
-        }
-        this.sourceSection = section;
-    }
-
-    NodeClass getNodeClass() {
-        return nodeClass;
-    }
-
-    /**
-     * Returns a rough estimate for the cost of this {@link Node}. This estimate can be used by
-     * runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method
-     * is intended to be overridden by subclasses. The default implementation returns the value of
-     * {@link NodeInfo#cost()} of the {@link NodeInfo} annotation declared at the subclass. If no
-     * {@link NodeInfo} annotation is declared the method returns {@link NodeCost#MONOMORPHIC} as a
-     * default value.
-     */
-    public NodeCost getCost() {
-        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
-        if (info != null) {
-            return info.cost();
-        }
-        return NodeCost.MONOMORPHIC;
-    }
-
-    /**
-     * Clears any previously assigned guest language source code from this node.
-     */
-    public final void clearSourceSection() {
-        this.sourceSection = null;
-    }
-
-    /**
-     * Retrieves the segment of guest language source code that is represented by this Node.
-     *
-     * @return the source code represented by this Node
-     */
-    public final SourceSection getSourceSection() {
-        return sourceSection;
-    }
-
-    /**
-     * Retrieves the segment of guest language source code that is represented by this Node, if
-     * present; otherwise retrieves the segment represented by the nearest AST ancestor that has
-     * this information.
-     *
-     * @return an approximation of the source code represented by this Node
-     */
-    @ExplodeLoop
-    public final SourceSection getEncapsulatingSourceSection() {
-        Node current = this;
-        while (current != null) {
-            if (current.sourceSection != null) {
-                return current.sourceSection;
-            }
-            current = current.parent;
-        }
-        return null;
-    }
-
-    /**
-     * Method that updates the link to the parent in the array of specified new child nodes to this
-     * node.
-     *
-     * @param newChildren the array of new children whose parent should be updated
-     * @return the array of new children
-     */
-    protected final <T extends Node> T[] insert(final T[] newChildren) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        assert newChildren != null;
-        for (Node newChild : newChildren) {
-            adoptHelper(newChild);
-        }
-        return newChildren;
-    }
-
-    /**
-     * Method that updates the link to the parent in the specified new child node to this node.
-     *
-     * @param newChild the new child whose parent should be updated
-     * @return the new child
-     */
-    protected final <T extends Node> T insert(final T newChild) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        assert newChild != null;
-        adoptHelper(newChild);
-        return newChild;
-    }
-
-    public final void adoptChildren() {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        adoptHelper();
-    }
-
-    private void adoptHelper(final Node newChild) {
-        assert newChild != null;
-        if (newChild == this) {
-            throw new IllegalStateException("The parent of a node can never be the node itself.");
-        }
-        newChild.parent = this;
-        if (TruffleOptions.TraceASTJSON) {
-            JSONHelper.dumpNewChild(this, newChild);
-        }
-        newChild.adoptHelper();
-    }
-
-    private void adoptHelper() {
-        Iterable<Node> children = this.getChildren();
-        for (Node child : children) {
-            if (child != null && child.getParent() != this) {
-                this.adoptHelper(child);
-            }
-        }
-    }
-
-    private void adoptUnadoptedHelper(final Node newChild) {
-        assert newChild != null;
-        if (newChild == this) {
-            throw new IllegalStateException("The parent of a node can never be the node itself.");
-        }
-        newChild.parent = this;
-        newChild.adoptUnadoptedHelper();
-    }
-
-    private void adoptUnadoptedHelper() {
-        Iterable<Node> children = this.getChildren();
-        for (Node child : children) {
-            if (child != null && child.getParent() == null) {
-                this.adoptUnadoptedHelper(child);
-            }
-        }
-    }
-
-    /**
-     * Returns properties of this node interesting for debugging and can be overwritten by
-     * subclasses to add their own custom properties.
-     *
-     * @return the properties as a key/value hash map
-     */
-    public Map<String, Object> getDebugProperties() {
-        Map<String, Object> properties = new HashMap<>();
-        return properties;
-    }
-
-    /**
-     * The current parent node of this node.
-     *
-     * @return the parent node
-     */
-    public final Node getParent() {
-        return parent;
-    }
-
-    /**
-     * Replaces this node with another node. If there is a source section (see
-     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
-     *
-     * @param newNode the new node that is the replacement
-     * @param reason a description of the reason for the replacement
-     * @return the new node
-     */
-    public final <T extends Node> T replace(final T newNode, final CharSequence reason) {
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        atomic(new Runnable() {
-            public void run() {
-                replaceHelper(newNode, reason);
-            }
-        });
-        return newNode;
-    }
-
-    /**
-     * Replaces this node with another node. If there is a source section (see
-     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
-     *
-     * @param newNode the new node that is the replacement
-     * @return the new node
-     */
-    public final <T extends Node> T replace(T newNode) {
-        return replace(newNode, "");
-    }
-
-    final void replaceHelper(Node newNode, CharSequence reason) {
-        CompilerAsserts.neverPartOfCompilation();
-        assert inAtomicBlock();
-        if (this.getParent() == null) {
-            throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
-        }
-        if (sourceSection != null && newNode.getSourceSection() == null) {
-            // Pass on the source section to the new node.
-            newNode.assignSourceSection(sourceSection);
-        }
-        // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
-        // will always find the root node
-        newNode.parent = this.parent;
-        if (NodeUtil.replaceChild(this.parent, this, newNode)) {
-            this.parent.adoptHelper(newNode);
-        } else {
-            this.parent.adoptUnadoptedHelper(newNode);
-        }
-        reportReplace(this, newNode, reason);
-        onReplace(newNode, reason);
-    }
-
-    /**
-     * Checks if this node can be replaced by another node: tree structure & type.
-     */
-    public final boolean isSafelyReplaceableBy(Node newNode) {
-        return NodeUtil.isReplacementSafe(getParent(), this, newNode);
-    }
-
-    private void reportReplace(Node oldNode, Node newNode, CharSequence reason) {
-        Node node = this;
-        while (node != null) {
-            boolean consumed = false;
-            if (node instanceof ReplaceObserver) {
-                consumed = ((ReplaceObserver) node).nodeReplaced(oldNode, newNode, reason);
-            } else if (node instanceof RootNode) {
-                CallTarget target = ((RootNode) node).getCallTarget();
-                if (target instanceof ReplaceObserver) {
-                    consumed = ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason);
-                }
-            }
-            if (consumed) {
-                break;
-            }
-            node = node.getParent();
-        }
-        if (TruffleOptions.TraceRewrites) {
-            NodeUtil.traceRewrite(this, newNode, reason);
-        }
-        if (TruffleOptions.TraceASTJSON) {
-            JSONHelper.dumpReplaceChild(this, newNode, reason);
-        }
-    }
-
-    /**
-     * Intended to be implemented by subclasses of {@link Node} to receive a notification when the
-     * node is rewritten. This method is invoked before the actual replace has happened.
-     *
-     * @param newNode the replacement node
-     * @param reason the reason the replace supplied
-     */
-    protected void onReplace(Node newNode, CharSequence reason) {
-        // empty default
-    }
-
-    /**
-     * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all
-     * child nodes.
-     *
-     * @param nodeVisitor the visitor
-     */
-    public final void accept(NodeVisitor nodeVisitor) {
-        if (nodeVisitor.visit(this)) {
-            NodeUtil.forEachChildRecursive(this, nodeVisitor);
-        }
-    }
-
-    /**
-     * Iterator over the children of this node.
-     *
-     * @return the iterator
-     */
-    public final Iterable<Node> getChildren() {
-        return new Iterable<Node>() {
-            public Iterator<Node> iterator() {
-                return getNodeClass().makeIterator(Node.this);
-            }
-        };
-    }
-
-    /**
-     * Creates a shallow copy of this node.
-     *
-     * @return the new copy
-     */
-    public Node copy() {
-        try {
-            return (Node) super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    /**
-     * Creates a deep copy of this node.
-     *
-     * @return the new deep copy
-     */
-    public Node deepCopy() {
-        return NodeUtil.deepCopyImpl(this);
-    }
-
-    /**
-     * This method must never be called. It enforces that {@link Object#clone} is not directly
-     * called by subclasses. Use the {@link #copy()} method instead.
-     */
-    @Override
-    @Deprecated
-    protected final Object clone() throws CloneNotSupportedException {
-        throw new IllegalStateException("This method should never be called, use the copy method instead!");
-    }
-
-    /**
-     * Get the root node of the tree a node belongs to.
-     *
-     * @return the {@link RootNode} or {@code null} if there is none.
-     */
-    public final RootNode getRootNode() {
-        Node rootNode = this;
-        while (rootNode.getParent() != null) {
-            assert !(rootNode instanceof RootNode) : "root node must not have a parent";
-            rootNode = rootNode.getParent();
-        }
-        if (rootNode instanceof RootNode) {
-            return (RootNode) rootNode;
-        }
-        return null;
-    }
-
-    /**
-     * Any node for which this is {@code true} can be "instrumented" by installing a {@link Probe}
-     * that intercepts execution events at the node and routes them to any {@link Instrument}s that
-     * have been attached to the {@link Probe}. Only one {@link Probe} may be installed at each
-     * node; subsequent calls return the one already installed.
-     * <p>
-     * <b>Note:</b> instrumentation requires a appropriate {@link WrapperNode}, which must be
-     * provided by {@link #createWrapperNode()}.
-     *
-     * @see Instrument
-     */
-    public boolean isInstrumentable() {
-        return false;
-    }
-
-    /**
-     * For any node that {@link #isInstrumentable()}, this method must return a {@link Node} that:
-     * <ol>
-     * <li>implements {@link WrapperNode}</li>
-     * <li>has {@code this} as it's child, and</li>
-     * <li>whose type is safe for replacement of {@code this} in the parent.</li>
-     * </ol>
-     *
-     * @return an appropriately typed {@link WrapperNode} if {@link #isInstrumentable()}.
-     */
-    public WrapperNode createWrapperNode() {
-        return null;
-    }
-
-    /**
-     * Enables {@linkplain Instrument instrumentation} of a node, where the node is presumed to be
-     * part of a well-formed Truffle AST that is not being executed. If this node has not already
-     * been probed, modifies the AST by inserting a {@linkplain WrapperNode wrapper node} between
-     * the node and its parent; the wrapper node must be provided by implementations of
-     * {@link #createWrapperNode()}. No more than one {@link Probe} may be associated with a node,
-     * so a {@linkplain WrapperNode wrapper} may not wrap another {@linkplain WrapperNode wrapper}.
-     *
-     * @return a (possibly newly created) {@link Probe} associated with this node.
-     * @throws ProbeException (unchecked) when a probe cannot be created, leaving the AST unchanged
-     */
-    public final Probe probe() {
-
-        if (this instanceof WrapperNode) {
-            throw new ProbeException(ProbeFailure.Reason.WRAPPER_NODE, null, this, null);
-        }
-
-        if (parent == null) {
-            throw new ProbeException(ProbeFailure.Reason.NO_PARENT, null, this, null);
-        }
-
-        if (parent instanceof WrapperNode) {
-            return ((WrapperNode) parent).getProbe();
-        }
-
-        if (!isInstrumentable()) {
-            throw new ProbeException(ProbeFailure.Reason.NOT_INSTRUMENTABLE, parent, this, null);
-        }
-
-        // Create a new wrapper/probe with this node as its child.
-        final WrapperNode wrapper = createWrapperNode();
-
-        if (wrapper == null || !(wrapper instanceof Node)) {
-            throw new ProbeException(ProbeFailure.Reason.NO_WRAPPER, parent, this, wrapper);
-        }
-
-        final Node wrapperNode = (Node) wrapper;
-
-        if (!this.isSafelyReplaceableBy(wrapperNode)) {
-            throw new ProbeException(ProbeFailure.Reason.WRAPPER_TYPE, parent, this, wrapper);
-        }
-
-        // Connect it to a Probe
-        final Probe probe = ProbeNode.insertProbe(wrapper);
-
-        // Replace this node in the AST with the wrapper
-        this.replace(wrapperNode);
-
-        return probe;
-    }
-
-    /**
-     * Converts this node to a textual representation useful for debugging.
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
-        Map<String, Object> properties = getDebugProperties();
-        boolean hasProperties = false;
-        for (Map.Entry<String, Object> entry : properties.entrySet()) {
-            sb.append(hasProperties ? "," : "<");
-            hasProperties = true;
-            sb.append(entry.getKey()).append("=").append(entry.getValue());
-        }
-        if (hasProperties) {
-            sb.append(">");
-        }
-        sb.append("@").append(Integer.toHexString(hashCode()));
-        return sb.toString();
-    }
-
-    public final void atomic(Runnable closure) {
-        RootNode rootNode = getRootNode();
-        synchronized (rootNode != null ? rootNode : GIL) {
-            assert enterAtomic();
-            try {
-                closure.run();
-            } finally {
-                assert exitAtomic();
-            }
-        }
-    }
-
-    public final <T> T atomic(Callable<T> closure) {
-        try {
-            RootNode rootNode = getRootNode();
-            synchronized (rootNode != null ? rootNode : GIL) {
-                assert enterAtomic();
-                try {
-                    return closure.call();
-                } finally {
-                    assert exitAtomic();
-                }
-            }
-        } catch (RuntimeException | Error e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Returns a user-readable description of the purpose of the Node, or "" if no description is
-     * available.
-     */
-    public String getDescription() {
-        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
-        if (info != null) {
-            return info.description();
-        }
-        return "";
-    }
-
-    /**
-     * Returns a string representing the language this node has been implemented for. If the
-     * language is unknown, returns "".
-     */
-    public String getLanguage() {
-        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
-        if (info != null && info.language() != null && info.language().length() > 0) {
-            return info.language();
-        }
-        if (parent != null) {
-            return parent.getLanguage();
-        }
-        return "";
-    }
-
-    private static final Object GIL = new Object();
-
-    private static final ThreadLocal<Integer> IN_ATOMIC_BLOCK = new ThreadLocal<Integer>() {
-        @Override
-        protected Integer initialValue() {
-            return 0;
-        }
-    };
-
-    private static boolean inAtomicBlock() {
-        return IN_ATOMIC_BLOCK.get() > 0;
-    }
-
-    private static boolean enterAtomic() {
-        IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() + 1);
-        return true;
-    }
-
-    private static boolean exitAtomic() {
-        IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() - 1);
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.lang.reflect.*;
-import java.security.*;
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-
-/**
- * Information about a {@link Node} class. A single instance of this class is allocated for every
- * subclass of {@link Node} that is used.
- */
-public final class NodeClass {
-    private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
-        @SuppressWarnings("unchecked")
-        @Override
-        protected NodeClass computeValue(final Class<?> clazz) {
-            assert Node.class.isAssignableFrom(clazz);
-            return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
-                public NodeClass run() {
-                    return new NodeClass((Class<? extends Node>) clazz);
-                }
-            });
-        }
-    };
-
-    // The comprehensive list of all fields.
-    private final NodeFieldAccessor[] fields;
-    // Separate arrays for the frequently accessed fields.
-    private final NodeFieldAccessor parentField;
-    private final NodeFieldAccessor nodeClassField;
-    private final NodeFieldAccessor[] childFields;
-    private final NodeFieldAccessor[] childrenFields;
-    private final NodeFieldAccessor[] cloneableFields;
-
-    private final Class<? extends Node> clazz;
-
-    public static NodeClass get(Class<? extends Node> clazz) {
-        return nodeClasses.get(clazz);
-    }
-
-    public static NodeClass get(Node clazz) {
-        return clazz.getNodeClass();
-    }
-
-    public NodeClass(Class<? extends Node> clazz) {
-        List<NodeFieldAccessor> fieldsList = new ArrayList<>();
-        NodeFieldAccessor parentFieldTmp = null;
-        NodeFieldAccessor nodeClassFieldTmp = null;
-        List<NodeFieldAccessor> childFieldList = new ArrayList<>();
-        List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
-        List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
-
-        for (Field field : NodeUtil.getAllFields(clazz)) {
-            if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
-                continue;
-            }
-
-            NodeFieldAccessor nodeField;
-            if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
-                assert Node.class.isAssignableFrom(field.getType());
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
-                parentFieldTmp = nodeField;
-            } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) {
-                assert NodeClass.class.isAssignableFrom(field.getType());
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field);
-                nodeClassFieldTmp = nodeField;
-            } else if (field.getAnnotation(Child.class) != null) {
-                checkChildField(field);
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field);
-                childFieldList.add(nodeField);
-            } else if (field.getAnnotation(Children.class) != null) {
-                checkChildrenField(field);
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILDREN, field);
-                childrenFieldList.add(nodeField);
-            } else {
-                nodeField = NodeFieldAccessor.create(NodeFieldKind.DATA, field);
-                if (NodeCloneable.class.isAssignableFrom(field.getType())) {
-                    cloneableFieldList.add(nodeField);
-                }
-            }
-            fieldsList.add(nodeField);
-        }
-
-        if (parentFieldTmp == null) {
-            throw new AssertionError("parent field not found");
-        }
-
-        this.fields = fieldsList.toArray(new NodeFieldAccessor[fieldsList.size()]);
-        this.nodeClassField = nodeClassFieldTmp;
-        this.parentField = parentFieldTmp;
-        this.childFields = childFieldList.toArray(new NodeFieldAccessor[childFieldList.size()]);
-        this.childrenFields = childrenFieldList.toArray(new NodeFieldAccessor[childrenFieldList.size()]);
-        this.cloneableFields = cloneableFieldList.toArray(new NodeFieldAccessor[cloneableFieldList.size()]);
-        this.clazz = clazz;
-    }
-
-    public NodeFieldAccessor getNodeClassField() {
-        return nodeClassField;
-    }
-
-    public NodeFieldAccessor[] getCloneableFields() {
-        return cloneableFields;
-    }
-
-    private static boolean isNodeType(Class<?> clazz) {
-        return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
-    }
-
-    private static void checkChildField(Field field) {
-        if (!isNodeType(field.getType())) {
-            throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
-        }
-        if (Modifier.isFinal(field.getModifiers())) {
-            throw new AssertionError("@Child field must not be final (" + field + ")");
-        }
-    }
-
-    private static void checkChildrenField(Field field) {
-        if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
-            throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
-        }
-        if (!Modifier.isFinal(field.getModifiers())) {
-            throw new AssertionError("@Children field must be final (" + field + ")");
-        }
-    }
-
-    public NodeFieldAccessor[] getFields() {
-        return fields;
-    }
-
-    public NodeFieldAccessor getParentField() {
-        return parentField;
-    }
-
-    public NodeFieldAccessor[] getChildFields() {
-        return childFields;
-    }
-
-    public NodeFieldAccessor[] getChildrenFields() {
-        return childrenFields;
-    }
-
-    @Override
-    public int hashCode() {
-        return clazz.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof NodeClass) {
-            NodeClass other = (NodeClass) obj;
-            return clazz.equals(other.clazz);
-        }
-        return false;
-    }
-
-    public Iterator<Node> makeIterator(Node node) {
-        assert clazz.isInstance(node);
-        return new NodeIterator(this, node);
-    }
-
-    private static final class NodeIterator implements Iterator<Node> {
-        private final NodeFieldAccessor[] childFields;
-        private final NodeFieldAccessor[] childrenFields;
-        private final Node node;
-        private final int childrenCount;
-        private int index;
-
-        protected NodeIterator(NodeClass nodeClass, Node node) {
-            this.childFields = nodeClass.getChildFields();
-            this.childrenFields = nodeClass.getChildrenFields();
-            this.node = node;
-            this.childrenCount = childrenCount();
-            this.index = 0;
-        }
-
-        private int childrenCount() {
-            int nodeCount = childFields.length;
-            for (NodeFieldAccessor childrenField : childrenFields) {
-                Object[] children = ((Object[]) childrenField.getObject(node));
-                if (children != null) {
-                    nodeCount += children.length;
-                }
-            }
-            return nodeCount;
-        }
-
-        private Node nodeAt(int idx) {
-            int nodeCount = childFields.length;
-            if (idx < nodeCount) {
-                return (Node) childFields[idx].getObject(node);
-            } else {
-                for (NodeFieldAccessor childrenField : childrenFields) {
-                    Object[] nodeArray = (Object[]) childrenField.getObject(node);
-                    if (idx < nodeCount + nodeArray.length) {
-                        return (Node) nodeArray[idx - nodeCount];
-                    }
-                    nodeCount += nodeArray.length;
-                }
-            }
-            return null;
-        }
-
-        private void forward() {
-            if (index < childrenCount) {
-                index++;
-            }
-        }
-
-        public boolean hasNext() {
-            return index < childrenCount;
-        }
-
-        public Node next() {
-            try {
-                return nodeAt(index);
-            } finally {
-                forward();
-            }
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCloneable.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-/**
- * Declarative base class for node fields that are to be cloned together with the containing node.
- */
-public abstract class NodeCloneable implements Cloneable {
-    @Override
-    protected Object clone() {
-        try {
-            return super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new AssertionError();
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Represents a rough estimate for the cost of a {@link Node}. This estimate can be used by runtime
- * systems or guest languages to implement heuristics based on Truffle ASTs.
- *
- * @see Node#getCost()
- */
-public enum NodeCost {
-
-    /**
-     * This node has literally no costs and should be ignored for heuristics. This is particularly
-     * useful for wrapper and profiling nodes which should not influence the heuristics.
-     */
-    NONE,
-
-    /**
-     * This node has a {@link CompilerDirectives#transferToInterpreter()} or
-     * {@link CompilerDirectives#transferToInterpreterAndInvalidate()} as its first unconditional
-     * statement.
-     */
-    UNINITIALIZED,
-
-    /**
-     * This node represents a specialized monomorphic version of an operation.
-     */
-    MONOMORPHIC,
-
-    /**
-     * This node represents a polymorphic version of an operation. For multiple chained polymorphic
-     * nodes the first may return {@link #MONOMORPHIC} and all additional nodes should return
-     * {@link #POLYMORPHIC}.
-     */
-    POLYMORPHIC,
-
-    /**
-     * This node represents a megamorphic version of an operation. This value should only be used if
-     * the operation implementation supports monomorphism and polymorphism otherwise
-     * {@link #MONOMORPHIC} should be used instead.
-     */
-    MEGAMORPHIC;
-
-    public boolean isTrivial() {
-        return this == NONE || this == UNINITIALIZED;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.lang.reflect.*;
-
-import sun.misc.*;
-
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
-
-/**
- * Information about a field in a {@link Node} class.
- */
-public abstract class NodeFieldAccessor {
-
-    public static enum NodeFieldKind {
-        /** The reference to the {@link NodeClass}. */
-        NODE_CLASS,
-        /** The single {@link Node#getParent() parent} field. */
-        PARENT,
-        /** A field annotated with {@link Child}. */
-        CHILD,
-        /** A field annotated with {@link Children}. */
-        CHILDREN,
-        /** A normal non-child data field of the node. */
-        DATA
-    }
-
-    private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe");
-
-    private final NodeFieldKind kind;
-    private final String name;
-    protected final Class<?> type;
-    protected final long offset;
-
-    protected NodeFieldAccessor(NodeFieldKind kind, Field field) {
-        this.kind = kind;
-        this.type = field.getType();
-        this.name = field.getName();
-        this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field);
-    }
-
-    protected static NodeFieldAccessor create(NodeFieldKind kind, Field field) {
-        if (USE_UNSAFE) {
-            return new UnsafeNodeField(kind, field);
-        } else {
-            return new ReflectionNodeField(kind, field);
-        }
-    }
-
-    public NodeFieldKind getKind() {
-        return kind;
-    }
-
-    public Class<?> getType() {
-        return type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public long getOffset() {
-        return offset;
-    }
-
-    public abstract void putObject(Node receiver, Object value);
-
-    public abstract Object getObject(Node receiver);
-
-    public abstract Object loadValue(Node node);
-
-    @Override
-    public int hashCode() {
-        return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof NodeFieldAccessor) {
-            NodeFieldAccessor other = (NodeFieldAccessor) obj;
-            return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
-        }
-        return false;
-    }
-
-    private static final Unsafe unsafe = getUnsafe();
-
-    private static Unsafe getUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-    private static final FieldOffsetProvider unsafeFieldOffsetProvider = new FieldOffsetProvider() {
-
-        @Override
-        public long objectFieldOffset(Field field) {
-            return unsafe.objectFieldOffset(field);
-        }
-
-        @Override
-        public int getTypeSize(Class<?> clazz) {
-            if (!clazz.isPrimitive()) {
-                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
-            } else if (clazz == int.class) {
-                return Unsafe.ARRAY_INT_INDEX_SCALE;
-            } else {
-                throw new UnsupportedOperationException("unsupported field type: " + clazz);
-            }
-        }
-    };
-
-    private static final class UnsafeNodeField extends NodeFieldAccessor {
-
-        protected UnsafeNodeField(NodeFieldKind kind, Field field) {
-            super(kind, field);
-        }
-
-        @Override
-        public void putObject(Node receiver, Object value) {
-            if (!type.isPrimitive() && value == null || type.isInstance(value)) {
-                unsafe.putObject(receiver, offset, value);
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        @Override
-        public Object getObject(Node receiver) {
-            if (!type.isPrimitive()) {
-                return unsafe.getObject(receiver, offset);
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        @Override
-        public Object loadValue(Node node) {
-            if (type == boolean.class) {
-                return unsafe.getBoolean(node, offset);
-            } else if (type == byte.class) {
-                return unsafe.getByte(node, offset);
-            } else if (type == short.class) {
-                return unsafe.getShort(node, offset);
-            } else if (type == char.class) {
-                return unsafe.getChar(node, offset);
-            } else if (type == int.class) {
-                return unsafe.getInt(node, offset);
-            } else if (type == long.class) {
-                return unsafe.getLong(node, offset);
-            } else if (type == float.class) {
-                return unsafe.getFloat(node, offset);
-            } else if (type == double.class) {
-                return unsafe.getDouble(node, offset);
-            } else {
-                return unsafe.getObject(node, offset);
-            }
-        }
-    }
-
-    private static final class ReflectionNodeField extends NodeFieldAccessor {
-        private final Field field;
-
-        protected ReflectionNodeField(NodeFieldKind kind, Field field) {
-            super(kind, field);
-            this.field = field;
-            field.setAccessible(true);
-        }
-
-        @Override
-        public void putObject(Node receiver, Object value) {
-            assert !type.isPrimitive() && value == null || type.isInstance(value);
-            try {
-                field.set(receiver, value);
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-
-        @Override
-        public Object getObject(Node receiver) {
-            assert !type.isPrimitive();
-            try {
-                return field.get(receiver);
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-
-        @Override
-        public Object loadValue(Node node) {
-            try {
-                if (type == boolean.class) {
-                    return field.getBoolean(node);
-                } else if (type == byte.class) {
-                    return field.getByte(node);
-                } else if (type == short.class) {
-                    return field.getShort(node);
-                } else if (type == char.class) {
-                    return field.getChar(node);
-                } else if (type == int.class) {
-                    return field.getInt(node);
-                } else if (type == long.class) {
-                    return field.getLong(node);
-                } else if (type == float.class) {
-                    return field.getFloat(node);
-                } else if (type == double.class) {
-                    return field.getDouble(node);
-                } else {
-                    return field.get(node);
-                }
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.lang.annotation.*;
-
-/**
- * Annotation for providing additional information on nodes.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface NodeInfo {
-
-    /**
-     * Short name representing the node that can be used for debugging.
-     *
-     * @return the short name
-     */
-    String shortName() default "";
-
-    /**
-     * Provides a rough estimate for the cost of the annotated {@link Node}. This estimate can be
-     * used by runtime systems or guest languages to implement heuristics based on Truffle ASTs.
-     *
-     * @see Node#getCost()
-     * @see NodeCost
-     */
-    NodeCost cost() default NodeCost.MONOMORPHIC;
-
-    /**
-     * A human readable explanation of the purpose of the annotated {@link Node}. Can be used e.g.
-     * for debugging or visualization purposes.
-     *
-     * @return the description
-     */
-    String description() default "";
-
-    /**
-     * A description, providing a user-readable explanation of the source language of the annotated
-     * {@link Node}. Can be used e.g. for debugging or visualization purposes. Typically this
-     * information is set only in an abstract base node for the language implementation.
-     *
-     * @return the description
-     */
-    String language() default "";
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInterface.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-/**
- * Common base interface for all Truffle nodes.
- *
- * @see Node
- */
-public interface NodeInterface {
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,841 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import sun.misc.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Utility class that manages the special access methods for node instances.
- */
-public final class NodeUtil {
-
-    /**
-     * Interface that allows the customization of field offsets used for {@link Unsafe} field
-     * accesses.
-     */
-    public interface FieldOffsetProvider {
-
-        long objectFieldOffset(Field field);
-
-        int getTypeSize(Class<?> clazz);
-    }
-
-    static Iterator<Node> makeIterator(Node node) {
-        return node.getNodeClass().makeIterator(node);
-    }
-
-    public static Iterator<Node> makeRecursiveIterator(Node node) {
-        return new RecursiveNodeIterator(node);
-    }
-
-    private static final class RecursiveNodeIterator implements Iterator<Node> {
-        private final List<Iterator<Node>> iteratorStack = new ArrayList<>();
-
-        public RecursiveNodeIterator(final Node node) {
-            iteratorStack.add(new Iterator<Node>() {
-
-                private boolean visited;
-
-                public void remove() {
-                    throw new UnsupportedOperationException();
-                }
-
-                public Node next() {
-                    if (visited) {
-                        throw new NoSuchElementException();
-                    }
-                    visited = true;
-                    return node;
-                }
-
-                public boolean hasNext() {
-                    return !visited;
-                }
-            });
-        }
-
-        public boolean hasNext() {
-            return peekIterator() != null;
-        }
-
-        public Node next() {
-            Iterator<Node> iterator = peekIterator();
-            if (iterator == null) {
-                throw new NoSuchElementException();
-            }
-
-            Node node = iterator.next();
-            if (node != null) {
-                Iterator<Node> childIterator = makeIterator(node);
-                if (childIterator.hasNext()) {
-                    iteratorStack.add(childIterator);
-                }
-            }
-            return node;
-        }
-
-        private Iterator<Node> peekIterator() {
-            int tos = iteratorStack.size() - 1;
-            while (tos >= 0) {
-                Iterator<Node> iterable = iteratorStack.get(tos);
-                if (iterable.hasNext()) {
-                    return iterable;
-                } else {
-                    iteratorStack.remove(tos--);
-                }
-            }
-            return null;
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T extends Node> T cloneNode(T orig) {
-        return (T) orig.deepCopy();
-    }
-
-    static Node deepCopyImpl(Node orig) {
-        final Node clone = orig.copy();
-        NodeClass nodeClass = clone.getNodeClass();
-
-        nodeClass.getParentField().putObject(clone, null);
-
-        for (NodeFieldAccessor childField : nodeClass.getChildFields()) {
-            Node child = (Node) childField.getObject(orig);
-            if (child != null) {
-                Node clonedChild = child.deepCopy();
-                nodeClass.getParentField().putObject(clonedChild, clone);
-                childField.putObject(clone, clonedChild);
-            }
-        }
-        for (NodeFieldAccessor childrenField : nodeClass.getChildrenFields()) {
-            Object[] children = (Object[]) childrenField.getObject(orig);
-            if (children != null) {
-                Object[] clonedChildren = (Object[]) Array.newInstance(children.getClass().getComponentType(), children.length);
-                for (int i = 0; i < children.length; i++) {
-                    if (children[i] != null) {
-                        Node clonedChild = ((Node) children[i]).deepCopy();
-                        clonedChildren[i] = clonedChild;
-                        nodeClass.getParentField().putObject(clonedChild, clone);
-                    }
-                }
-                childrenField.putObject(clone, clonedChildren);
-            }
-        }
-        for (NodeFieldAccessor cloneableField : nodeClass.getCloneableFields()) {
-            Object cloneable = cloneableField.getObject(clone);
-            if (cloneable != null && cloneable == cloneableField.getObject(orig)) {
-                cloneableField.putObject(clone, ((NodeCloneable) cloneable).clone());
-            }
-        }
-        return clone;
-    }
-
-    public static List<Node> findNodeChildren(Node node) {
-        List<Node> nodes = new ArrayList<>();
-        NodeClass nodeClass = node.getNodeClass();
-
-        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
-            Object child = nodeField.getObject(node);
-            if (child != null) {
-                nodes.add((Node) child);
-            }
-        }
-        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
-            Object[] children = (Object[]) nodeField.getObject(node);
-            if (children != null) {
-                for (Object child : children) {
-                    if (child != null) {
-                        nodes.add((Node) child);
-                    }
-                }
-            }
-        }
-
-        return nodes;
-    }
-
-    public static <T extends Node> T nonAtomicReplace(Node oldNode, T newNode, CharSequence reason) {
-        oldNode.replaceHelper(newNode, reason);
-        return newNode;
-    }
-
-    public static boolean replaceChild(Node parent, Node oldChild, Node newChild) {
-        NodeClass nodeClass = parent.getNodeClass();
-
-        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
-            if (nodeField.getObject(parent) == oldChild) {
-                assert assertAssignable(nodeField, newChild);
-                nodeField.putObject(parent, newChild);
-                return true;
-            }
-        }
-
-        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
-            Object arrayObject = nodeField.getObject(parent);
-            if (arrayObject != null) {
-                Object[] array = (Object[]) arrayObject;
-                for (int i = 0; i < array.length; i++) {
-                    if (array[i] == oldChild) {
-                        assert assertAssignable(nodeField, newChild);
-                        array[i] = newChild;
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private static boolean assertAssignable(NodeFieldAccessor field, Object newValue) {
-        if (newValue == null) {
-            return true;
-        }
-        if (field.getKind() == NodeFieldKind.CHILD) {
-            if (field.getType().isAssignableFrom(newValue.getClass())) {
-                return true;
-            } else {
-                assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
-                return false;
-            }
-        } else if (field.getKind() == NodeFieldKind.CHILDREN) {
-            if (field.getType().getComponentType().isAssignableFrom(newValue.getClass())) {
-                return true;
-            } else {
-                assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
-                return false;
-            }
-        }
-        throw new IllegalArgumentException();
-    }
-
-    /**
-     * Finds the field in a parent node, if any, that holds a specified child node.
-     *
-     * @return the field (possibly an array) holding the child, {@code null} if not found.
-     */
-    public static NodeFieldAccessor findChildField(Node parent, Node child) {
-        assert child != null;
-        NodeClass parentNodeClass = parent.getNodeClass();
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
-            if (field.getObject(parent) == child) {
-                return field;
-            }
-        }
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
-            Object arrayObject = field.getObject(parent);
-            if (arrayObject != null) {
-                Object[] array = (Object[]) arrayObject;
-                for (int i = 0; i < array.length; i++) {
-                    if (array[i] == child) {
-                        return field;
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Determines whether a proposed child replacement would be safe: structurally and type.
-     */
-    public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) {
-        assert newChild != null;
-        if (parent != null) {
-            final NodeFieldAccessor field = findChildField(parent, oldChild);
-            if (field != null) {
-                switch (field.getKind()) {
-                    case CHILD:
-                        return field.getType().isAssignableFrom(newChild.getClass());
-                    case CHILDREN:
-                        return field.getType().getComponentType().isAssignableFrom(newChild.getClass());
-                    default:
-                        throw new IllegalStateException();
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Executes a closure for every non-null child of the parent node.
-     *
-     * @return {@code true} if all children were visited, {@code false} otherwise
-     */
-    public static boolean forEachChild(Node parent, NodeVisitor visitor) {
-        Objects.requireNonNull(visitor);
-        NodeClass parentNodeClass = parent.getNodeClass();
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
-            Object child = field.getObject(parent);
-            if (child != null) {
-                if (!visitor.visit((Node) child)) {
-                    return false;
-                }
-            }
-        }
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
-            Object arrayObject = field.getObject(parent);
-            if (arrayObject != null) {
-                Object[] array = (Object[]) arrayObject;
-                for (int i = 0; i < array.length; i++) {
-                    Object child = array[i];
-                    if (child != null) {
-                        if (!visitor.visit((Node) child)) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-
-        return true;
-    }
-
-    static boolean forEachChildRecursive(Node parent, NodeVisitor visitor) {
-        NodeClass parentNodeClass = parent.getNodeClass();
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
-            if (!visitChild((Node) field.getObject(parent), visitor)) {
-                return false;
-            }
-        }
-
-        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
-            Object arrayObject = field.getObject(parent);
-            if (arrayObject == null) {
-                continue;
-            }
-            Object[] array = (Object[]) arrayObject;
-            for (int i = 0; i < array.length; i++) {
-                if (!visitChild((Node) array[i], visitor)) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    private static boolean visitChild(Node child, NodeVisitor visitor) {
-        if (child == null) {
-            return true;
-        }
-        if (!visitor.visit(child)) {
-            return false;
-        }
-        if (!forEachChildRecursive(child, visitor)) {
-            return false;
-        }
-        return true;
-    }
-
-    /** Returns all declared fields in the class hierarchy. */
-    static Field[] getAllFields(Class<? extends Object> clazz) {
-        Field[] declaredFields = clazz.getDeclaredFields();
-        if (clazz.getSuperclass() != null) {
-            return concat(getAllFields(clazz.getSuperclass()), declaredFields);
-        }
-        return declaredFields;
-    }
-
-    public static <T> T[] concat(T[] first, T[] second) {
-        T[] result = Arrays.copyOf(first, first.length + second.length);
-        System.arraycopy(second, 0, result, first.length, second.length);
-        return result;
-    }
-
-    /**
-     * Get the nth parent of a node, where the 0th parent is the node itself. Returns null if there
-     * are less than n ancestors.
-     */
-    public static Node getNthParent(Node node, int n) {
-        Node parent = node;
-
-        for (int i = 0; i < n; i++) {
-            parent = parent.getParent();
-
-            if (parent == null) {
-                return null;
-            }
-        }
-
-        return parent;
-    }
-
-    /** find annotation in class/interface hierarchy. */
-    public static <T extends Annotation> T findAnnotation(Class<?> clazz, Class<T> annotationClass) {
-        if (clazz.getAnnotation(annotationClass) != null) {
-            return clazz.getAnnotation(annotationClass);
-        } else {
-            for (Class<?> intf : clazz.getInterfaces()) {
-                if (intf.getAnnotation(annotationClass) != null) {
-                    return intf.getAnnotation(annotationClass);
-                }
-            }
-            if (clazz.getSuperclass() != null) {
-                return findAnnotation(clazz.getSuperclass(), annotationClass);
-            }
-        }
-        return null;
-    }
-
-    public static <T> T findParent(Node start, Class<T> clazz) {
-        Node parent = start.getParent();
-        if (parent == null) {
-            return null;
-        } else if (clazz.isInstance(parent)) {
-            return clazz.cast(parent);
-        } else {
-            return findParent(parent, clazz);
-        }
-    }
-
-    public static <T> List<T> findAllParents(Node start, Class<T> clazz) {
-        List<T> parents = new ArrayList<>();
-        T parent = findParent(start, clazz);
-        while (parent != null) {
-            parents.add(parent);
-            parent = findParent((Node) parent, clazz);
-        }
-        return parents;
-    }
-
-    public static List<Node> collectNodes(Node parent, Node child) {
-        List<Node> nodes = new ArrayList<>();
-        Node current = child;
-        while (current != null) {
-            nodes.add(current);
-            if (current == parent) {
-                return nodes;
-            }
-            current = current.getParent();
-        }
-        throw new IllegalArgumentException("Node " + parent + " is not a parent of " + child + ".");
-    }
-
-    public static <T> T findFirstNodeInstance(Node root, Class<T> clazz) {
-        if (clazz.isInstance(root)) {
-            return clazz.cast(root);
-        }
-        for (Node child : root.getChildren()) {
-            T node = findFirstNodeInstance(child, clazz);
-            if (node != null) {
-                return node;
-            }
-        }
-        return null;
-    }
-
-    public static <T> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
-        final List<T> nodeList = new ArrayList<>();
-        root.accept(new NodeVisitor() {
-            public boolean visit(Node node) {
-                if (clazz.isInstance(node)) {
-                    nodeList.add(clazz.cast(node));
-                }
-                return true;
-            }
-        });
-        return nodeList;
-    }
-
-    public static int countNodes(Node root) {
-        return countNodes(root, NodeCountFilter.NO_FILTER);
-    }
-
-    public static int countNodes(Node root, NodeCountFilter filter) {
-        NodeCounter counter = new NodeCounter(filter);
-        root.accept(counter);
-        return counter.count;
-    }
-
-    public interface NodeCountFilter {
-
-        NodeCountFilter NO_FILTER = new NodeCountFilter() {
-
-            public boolean isCounted(Node node) {
-                return true;
-            }
-        };
-
-        boolean isCounted(Node node);
-
-    }
-
-    public static String printCompactTreeToString(Node node) {
-        StringWriter out = new StringWriter();
-        printCompactTree(new PrintWriter(out), null, node, 1);
-        return out.toString();
-    }
-
-    public static void printCompactTree(OutputStream out, Node node) {
-        printCompactTree(new PrintWriter(out), null, node, 1);
-    }
-
-    private static void printCompactTree(PrintWriter p, Node parent, Node node, int level) {
-        if (node == null) {
-            return;
-        }
-        for (int i = 0; i < level; i++) {
-            p.print("  ");
-        }
-        if (parent == null) {
-            p.println(nodeName(node));
-        } else {
-            p.print(getNodeFieldName(parent, node, "unknownField"));
-            p.print(" = ");
-            p.println(nodeName(node));
-        }
-
-        for (Node child : node.getChildren()) {
-            printCompactTree(p, node, child, level + 1);
-        }
-        p.flush();
-    }
-
-    public static String printSourceAttributionTree(Node node) {
-        StringWriter out = new StringWriter();
-        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
-        return out.toString();
-    }
-
-    public static void printSourceAttributionTree(OutputStream out, Node node) {
-        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
-    }
-
-    public static void printSourceAttributionTree(PrintWriter out, Node node) {
-        printSourceAttributionTree(out, null, node, 1);
-    }
-
-    private static void printSourceAttributionTree(PrintWriter p, Node parent, Node node, int level) {
-        if (node == null) {
-            return;
-        }
-        if (parent == null) {
-            // Add some preliminary information before starting with the root node
-            final SourceSection sourceSection = node.getSourceSection();
-            if (sourceSection != null) {
-                final String txt = sourceSection.getSource().getCode();
-                p.println("Full source len=(" + txt.length() + ")  ___" + txt + "___");
-                p.println("AST source attribution:");
-            }
-        }
-        final StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < level; i++) {
-            sb.append("| ");
-        }
-
-        if (parent != null) {
-            sb.append(getNodeFieldName(parent, node, ""));
-        }
-
-        sb.append("  (" + node.getClass().getSimpleName() + ")  ");
-
-        sb.append(printSyntaxTags(node));
-
-        sb.append(displaySourceAttribution(node));
-        p.println(sb.toString());
-
-        for (Node child : node.getChildren()) {
-            printSourceAttributionTree(p, node, child, level + 1);
-        }
-        p.flush();
-    }
-
-    private static String getNodeFieldName(Node parent, Node node, String defaultName) {
-        NodeFieldAccessor[] fields = parent.getNodeClass().getFields();
-        for (NodeFieldAccessor field : fields) {
-            Object value = field.loadValue(parent);
-            if (field.getKind() == NodeFieldKind.CHILD && value == node) {
-                return field.getName();
-            } else if (field.getKind() == NodeFieldKind.CHILDREN) {
-                int index = 0;
-                for (Object arrayNode : (Object[]) value) {
-                    if (arrayNode == node) {
-                        return field.getName() + "[" + index + "]";
-                    }
-                    index++;
-                }
-            }
-        }
-        return defaultName;
-    }
-
-    /**
-     * Returns a string listing the {@linkplain SyntaxTag syntax tags}, if any, associated with a
-     * node:
-     * <ul>
-     * <li>"[{@linkplain StandardSyntaxTag#STATEMENT STATEMENT},
-     * {@linkplain StandardSyntaxTag#ASSIGNMENT ASSIGNMENT}]" if tags have been applied;</li>
-     * <li>"[]" if the node supports tags, but none are present; and</li>
-     * <li>"" if the node does not support tags.</li>
-     * </ul>
-     */
-    public static String printSyntaxTags(final Object node) {
-        if (node instanceof WrapperNode) {
-            final Probe probe = ((WrapperNode) node).getProbe();
-            final Collection<SyntaxTag> syntaxTags = probe.getSyntaxTags();
-            final StringBuilder sb = new StringBuilder();
-            String prefix = "";
-            sb.append("[");
-            for (SyntaxTag tag : syntaxTags) {
-                sb.append(prefix);
-                prefix = ",";
-                sb.append(tag.toString());
-            }
-            sb.append("]");
-            return sb.toString();
-        }
-        return "";
-    }
-
-    /**
-     * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This
-     * print method does not check for cycles in the node structure.
-     *
-     * @param out the stream to print to.
-     * @param node the root node to write
-     */
-    public static void printTree(OutputStream out, Node node) {
-        printTree(new PrintWriter(out), node);
-    }
-
-    public static String printTreeToString(Node node) {
-        StringWriter out = new StringWriter();
-        printTree(new PrintWriter(out), node);
-        return out.toString();
-    }
-
-    public static void printTree(PrintWriter p, Node node) {
-        printTree(p, node, 1);
-        p.println();
-        p.flush();
-    }
-
-    private static void printTree(PrintWriter p, Node node, int level) {
-        if (node == null) {
-            p.print("null");
-            return;
-        }
-
-        p.print(nodeName(node));
-
-        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
-        String sep = "";
-        p.print("(");
-        for (NodeFieldAccessor field : NodeClass.get(node).getFields()) {
-            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
-                childFields.add(field);
-            } else if (field.getKind() == NodeFieldKind.DATA) {
-                p.print(sep);
-                sep = ", ";
-
-                p.print(field.getName());
-                p.print(" = ");
-                p.print(field.loadValue(node));
-            }
-        }
-        p.print(")");
-
-        if (childFields.size() != 0) {
-            p.print(" {");
-            for (NodeFieldAccessor field : childFields) {
-                printNewLine(p, level);
-                p.print(field.getName());
-
-                Object value = field.loadValue(node);
-                if (value == null) {
-                    p.print(" = null ");
-                } else if (field.getKind() == NodeFieldKind.CHILD) {
-                    p.print(" = ");
-                    printTree(p, (Node) value, level + 1);
-                } else if (field.getKind() == NodeFieldKind.CHILDREN) {
-                    printChildren(p, level, value);
-                }
-            }
-            printNewLine(p, level - 1);
-            p.print("}");
-        }
-    }
-
-    private static void printChildren(PrintWriter p, int level, Object value) {
-        String sep;
-        Object[] children = (Object[]) value;
-        p.print(" = [");
-        sep = "";
-        for (Object child : children) {
-            p.print(sep);
-            sep = ", ";
-            printTree(p, (Node) child, level + 1);
-        }
-        p.print("]");
-    }
-
-    private static void printNewLine(PrintWriter p, int level) {
-        p.println();
-        for (int i = 0; i < level; i++) {
-            p.print("    ");
-        }
-    }
-
-    private static String nodeName(Node node) {
-        return node.getClass().getSimpleName();
-    }
-
-    private static String displaySourceAttribution(Node node) {
-        final SourceSection section = node.getSourceSection();
-        if (section instanceof NullSourceSection) {
-            return "source: " + section.getShortDescription();
-        }
-        if (section != null) {
-            final String srcText = section.getCode();
-            final StringBuilder sb = new StringBuilder();
-            sb.append("source:");
-            sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")");
-            sb.append(" line=" + section.getLineLocation().getLineNumber());
-            sb.append(" len=" + srcText.length());
-            sb.append(" text=\"" + srcText + "\"");
-            return sb.toString();
-        }
-        return "";
-    }
-
-    public static boolean verify(Node root) {
-        Iterable<Node> children = root.getChildren();
-        for (Node child : children) {
-            if (child != null) {
-                if (child.getParent() != root) {
-                    throw new AssertionError(toStringWithClass(child) + ": actual parent=" + toStringWithClass(child.getParent()) + " expected parent=" + toStringWithClass(root));
-                }
-                verify(child);
-            }
-        }
-        return true;
-    }
-
-    private static String toStringWithClass(Object obj) {
-        return obj == null ? "null" : obj + "(" + obj.getClass().getName() + ")";
-    }
-
-    static void traceRewrite(Node oldNode, Node newNode, CharSequence reason) {
-        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
-            if (filterByKind(oldNode, TruffleOptions.TraceRewritesFilterFromCost)) {
-                return;
-            }
-        }
-
-        if (TruffleOptions.TraceRewritesFilterToCost != null) {
-            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
-                return;
-            }
-        }
-
-        String filter = TruffleOptions.TraceRewritesFilterClass;
-        Class<? extends Node> from = oldNode.getClass();
-        Class<? extends Node> to = newNode.getClass();
-        if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
-            return;
-        }
-
-        final SourceSection reportedSourceSection = oldNode.getEncapsulatingSourceSection();
-
-        PrintStream out = System.out;
-        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", oldNode.toString(), formatNodeInfo(oldNode), formatNodeInfo(newNode),
-                        reason != null && reason.length() > 0 ? reason : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
-    }
-
-    private static String formatNodeInfo(Node node) {
-        String cost = "?";
-        switch (node.getCost()) {
-            case NONE:
-                cost = "G";
-                break;
-            case MONOMORPHIC:
-                cost = "M";
-                break;
-            case POLYMORPHIC:
-                cost = "P";
-                break;
-            case MEGAMORPHIC:
-                cost = "G";
-                break;
-            default:
-                cost = "?";
-                break;
-        }
-        return cost + " " + node.getClass().getSimpleName();
-    }
-
-    private static boolean filterByKind(Node node, NodeCost cost) {
-        return node.getCost() == cost;
-    }
-
-    private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
-        Class<?> currentFrom = from;
-        while (currentFrom != null) {
-            if (currentFrom.getName().contains(filter)) {
-                return false;
-            }
-            currentFrom = currentFrom.getSuperclass();
-        }
-        return true;
-    }
-
-    private static final class NodeCounter implements NodeVisitor {
-
-        public int count;
-        private final NodeCountFilter filter;
-
-        public NodeCounter(NodeCountFilter filter) {
-            this.filter = filter;
-        }
-
-        public boolean visit(Node node) {
-            if (filter.isCounted(node)) {
-                count++;
-            }
-            return true;
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-/**
- * Visitor for trees of nodes.
- */
-public interface NodeVisitor {
-
-    /**
-     * This visitor method is called for every node in the tree. Its return value determines if the
-     * children of this node should be excluded in the iteration.
-     *
-     * @param node the node that is currently visited
-     * @return {@code true} if the children should be visited too, {@code false} otherwise
-     */
-    boolean visit(Node node);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.frame.*;
-
-/**
- * Experimental API: may change significantly without notice.
- */
-public interface RepeatingNode extends NodeInterface {
-
-    boolean executeRepeating(VirtualFrame frame);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a
- * root node can be used to create a call target using
- * {@link TruffleRuntime#createCallTarget(RootNode)}.
- */
-public abstract class RootNode extends Node {
-
-    private RootCallTarget callTarget;
-    @CompilationFinal private FrameDescriptor frameDescriptor;
-
-    protected RootNode() {
-        this(null, null);
-    }
-
-    protected RootNode(SourceSection sourceSection) {
-        this(sourceSection, null);
-    }
-
-    protected RootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor) {
-        super(sourceSection);
-        if (frameDescriptor == null) {
-            this.frameDescriptor = new FrameDescriptor();
-        } else {
-            this.frameDescriptor = frameDescriptor;
-        }
-    }
-
-    @Override
-    public Node copy() {
-        RootNode root = (RootNode) super.copy();
-        root.frameDescriptor = frameDescriptor;
-        return root;
-    }
-
-    /**
-     * Returns <code>true</code> if this {@link RootNode} is allowed to be cloned. The runtime
-     * system might decide to create deep copies of the {@link RootNode} in order to gather context
-     * sensitive profiling feedback. The default implementation returns <code>false</code>. Guest
-     * language specific implementations may want to return <code>true</code> here to indicate that
-     * gathering call site specific profiling information might make sense for this {@link RootNode}
-     * .
-     *
-     * @return <code>true</code> if cloning is allowed else <code>false</code>.
-     */
-    public boolean isCloningAllowed() {
-        return false;
-    }
-
-    /**
-     * Reports the execution count of a loop that is a child of this node. The optimization
-     * heuristics can use the loop count to guide compilation and inlining.
-     */
-    public final void reportLoopCount(int count) {
-        if (getCallTarget() instanceof LoopCountReceiver) {
-            ((LoopCountReceiver) getCallTarget()).reportLoopCount(count);
-        }
-    }
-
-    /**
-     * Executes this function using the specified frame and returns the result value.
-     *
-     * @param frame the frame of the currently executing guest language method
-     * @return the value of the execution
-     */
-    public abstract Object execute(VirtualFrame frame);
-
-    public final RootCallTarget getCallTarget() {
-        return callTarget;
-    }
-
-    public final FrameDescriptor getFrameDescriptor() {
-        return frameDescriptor;
-    }
-
-    public final void setCallTarget(RootCallTarget callTarget) {
-        this.callTarget = callTarget;
-    }
-
-    /**
-     * Returns the {@link ExecutionContext} associated with this <code>RootNode</code>. This allows
-     * the correct <code>ExecutionContext</code> to be determined for a <code>RootNode</code> (and
-     * so also for a {@link RootCallTarget} and a {@link FrameInstance} obtained from the call
-     * stack) without prior knowledge of the language it has come from.
-     *
-     * Used for instance to determine the language of a <code>RootNode<code>:
-     *
-     * <pre>
-     * <code>
-     * rootNode.getExecutionContext().getLanguageShortName();
-     * </code> </pre>
-     *
-     * Returns <code>null</code> by default.
-     */
-    public ExecutionContext getExecutionContext() {
-        return null;
-    }
-
-    /**
-     * Get compiler options specific to this <code>RootNode</code>.
-     */
-    public CompilerOptions getCompilerOptions() {
-        final ExecutionContext context = getExecutionContext();
-
-        if (context == null) {
-            return DefaultCompilerOptions.INSTANCE;
-        } else {
-            return context.getCompilerOptions();
-        }
-    }
-
-    /**
-     * Apply all registered instances of {@link ASTProber} to the AST, if any, held by this root
-     * node. This can only be done once the AST is complete, notably once all parent pointers are
-     * correctly assigned. But it also must be done before any AST cloning or execution.
-     * <p>
-     * If this is not done, then the AST will not be subject to debugging or any other
-     * instrumentation-supported tooling.
-     * <p>
-     * Implementations should ensure that instrumentation is never applied more than once to an AST,
-     * as this is not guaranteed to be error-free.
-     *
-     * @see Probe#registerASTProber(com.oracle.truffle.api.instrument.ASTProber)
-     */
-    public void applyInstrumentation() {
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-
-/**
- * An exception thrown to enter a slow path. The Truffle optimizer has special knowledge of this
- * exception class and will never compile a catch block that catches this exception type.
- */
-public class SlowPathException extends Exception {
-
-    private static final long serialVersionUID = 3676602078425211386L;
-
-    /**
-     * Creates an exception thrown to enter a slow path.
-     */
-    public SlowPathException() {
-        CompilerDirectives.transferToInterpreter();
-    }
-
-    /**
-     * Creates an exception thrown to enter a slow path.
-     */
-    public SlowPathException(String message, Throwable cause) {
-        super(message, cause);
-        CompilerDirectives.transferToInterpreter();
-    }
-
-    /**
-     * Creates an exception thrown to enter a slow path.
-     */
-    public SlowPathException(String message) {
-        super(message);
-        CompilerDirectives.transferToInterpreter();
-    }
-
-    /**
-     * Creates an exception thrown to enter a slow path.
-     */
-    public SlowPathException(Throwable cause) {
-        super(cause);
-        CompilerDirectives.transferToInterpreter();
-    }
-
-    /**
-     * For performance reasons, this exception does not record any stack trace information.
-     */
-    @SuppressWarnings("sync-override")
-    @Override
-    public Throwable fillInStackTrace() {
-        return null;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes;
-
-import com.oracle.truffle.api.*;
-
-/**
- * An exception that should be thrown if the return value cannot be represented as a value of the
- * return type. The Truffle optimizer has special knowledge of this exception class and will never
- * compile a catch block that catches this exception type.
- */
-public final class UnexpectedResultException extends SlowPathException {
-
-    private static final long serialVersionUID = 3676602078425211386L;
-    private final Object result;
-
-    /**
-     * Creates the exception with the alternative result that cannot be represented as a value of
-     * the return type.
-     *
-     * @param result the alternative result
-     */
-    public UnexpectedResultException(Object result) {
-        CompilerDirectives.transferToInterpreter();
-        this.result = result;
-    }
-
-    /**
-     * @return the unexpected result
-     */
-    public Object getResult() {
-        return result;
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,375 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes.serial;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import sun.misc.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Experimental API. May change without notice.
- */
-public final class PostOrderDeserializer {
-
-    private static final Unsafe unsafe = loadUnsafe();
-
-    private final SerializerConstantPool cp;
-
-    private final HierarchicalStack stack = new HierarchicalStack();
-
-    /**
-     * Constructs a new serializer using a custom {@link SerializerConstantPool} implementation. For
-     * the {@link SerializerConstantPool} implementation at least the following methods must be
-     * implemented:
-     * <ul>
-     * <li>{@link SerializerConstantPool#getInt(int)}</li>
-     * <li>{@link SerializerConstantPool#getClass(int)}</li>
-     * </ul>
-     */
-    public PostOrderDeserializer(SerializerConstantPool cp) {
-        this.cp = cp;
-    }
-
-    /**
-     * Deserializes the byte stream and returns the deserialized Truffle AST node.
-     *
-     * @param bytes the trimmed byte array containing the serialized data
-     * @param expectedType the expected root node type. Throws an exception if the root node is not
-     *            assignable from this type.
-     * @return the deserialized Truffle AST represented by the root Node.
-     *
-     * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not
-     *             supported by the constant pool implementation.
-     */
-    @SuppressWarnings("unchecked")
-    public <T extends Node> T deserialize(byte[] bytes, Class<T> expectedType) throws UnsupportedConstantPoolTypeException {
-        VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(bytes);
-
-        while (buffer.hasRemaining()) {
-            int classCPI = buffer.get();
-            if (classCPI == VariableLengthIntBuffer.NULL) {
-                pushNode(null);
-            } else {
-                Class<?> clazz = cp.getClass(classCPI);
-                if (clazz.isArray()) {
-                    int lengthCPI = buffer.get();
-                    if (lengthCPI == VariableLengthIntBuffer.NULL) {
-                        pushArray(null);
-                    } else {
-                        pushArray((Node[]) Array.newInstance(clazz.getComponentType(), cp.getInt(lengthCPI)));
-                    }
-                } else {
-                    pushNode(invokeDeserialize(buffer, clazz.asSubclass(Node.class)));
-                }
-            }
-        }
-        T returnNode = (T) popNode(null, expectedType);
-
-        assert stack.dynamicStack.isEmpty();
-
-        return returnNode;
-    }
-
-    private void pushNode(Node node) {
-        stack.push(node);
-    }
-
-    private void pushArray(Node[] array) {
-        stack.pushStack(array);
-    }
-
-    private Node[] popArray(Node parent, Class<?> expectedType) {
-        Node[] array = (Node[]) stack.popStack();
-        if (array != null) {
-            assertType(array, expectedType);
-            for (int i = 0; i < array.length; i++) {
-                updateParent(parent, array[i]);
-            }
-        }
-        return array;
-    }
-
-    private Node popNode(Node parent, Class<?> expectedType) {
-        Object o = stack.pop();
-        assertType(o, expectedType);
-        updateParent(parent, (Node) o);
-        return (Node) o;
-    }
-
-    private static void assertType(Object o, Class<?> expectedType) {
-        if (o != null && !expectedType.isAssignableFrom(o.getClass())) {
-            throw new AssertionError("Expected element type '" + expectedType.getName() + "' but was '" + o.getClass().getName() + "'.");
-        }
-    }
-
-    private Node invokeDeserialize(VariableLengthIntBuffer buffer, Class<? extends Node> nodeClass) throws UnsupportedConstantPoolTypeException {
-        if (nodeClass == null) {
-            return null;
-        }
-
-        Object object;
-        try {
-            object = unsafe.allocateInstance(nodeClass);
-        } catch (InstantiationException e) {
-            throw new RuntimeException("Unable to allocate truffle node " + nodeClass, e);
-        }
-        if (!(object instanceof Node)) {
-            throw new RuntimeException("Class is not a truffle node " + nodeClass);
-        }
-
-        Node node = (Node) object;
-
-        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
-        deserializeChildrenFields(node, nodeFields);
-        deserializeChildFields(node, nodeFields);
-        deserializeDataFields(buffer, node, nodeFields);
-
-        return node;
-    }
-
-    private void deserializeDataFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
-        for (int i = 0; i < nodeFields.length; i++) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.DATA) {
-                Class<?> fieldClass = field.getType();
-                long offset = field.getOffset();
-
-                // source sections are not serialized
-                // TODO add support for source sections
-                if (field.getType().isAssignableFrom(SourceSection.class)) {
-                    continue;
-                }
-
-                int cpi = buffer.get();
-                if (cpi == VariableLengthIntBuffer.NULL) {
-                    deserializeDataFieldsLengthNull(nodeInstance, fieldClass, offset);
-                } else {
-                    deserializeDataFieldsDefault(nodeInstance, fieldClass, offset, cpi);
-                }
-            }
-        }
-    }
-
-    private void deserializeDataFieldsDefault(Node nodeInstance, Class<?> fieldClass, long offset, int cpi) {
-        if (fieldClass == int.class) {
-            unsafe.putInt(nodeInstance, offset, cp.getInt(cpi));
-        } else if (fieldClass == long.class) {
-            unsafe.putLong(nodeInstance, offset, cp.getLong(cpi));
-        } else if (fieldClass == float.class) {
-            unsafe.putFloat(nodeInstance, offset, cp.getFloat(cpi));
-        } else if (fieldClass == double.class) {
-            unsafe.putDouble(nodeInstance, offset, cp.getDouble(cpi));
-        } else if (fieldClass == byte.class) {
-            unsafe.putByte(nodeInstance, offset, (byte) cp.getInt(cpi));
-        } else if (fieldClass == short.class) {
-            unsafe.putShort(nodeInstance, offset, (short) cp.getInt(cpi));
-        } else if (fieldClass == char.class) {
-            unsafe.putChar(nodeInstance, offset, (char) cp.getInt(cpi));
-        } else if (fieldClass == boolean.class) {
-            unsafe.putBoolean(nodeInstance, offset, cp.getInt(cpi) == 1 ? true : false);
-        } else if (fieldClass == Integer.class) {
-            unsafe.putObject(nodeInstance, offset, cp.getInt(cpi));
-        } else if (fieldClass == Long.class) {
-            unsafe.putObject(nodeInstance, offset, cp.getLong(cpi));
-        } else if (fieldClass == Float.class) {
-            unsafe.putObject(nodeInstance, offset, cp.getFloat(cpi));
-        } else if (fieldClass == Double.class) {
-            unsafe.putObject(nodeInstance, offset, cp.getDouble(cpi));
-        } else if (fieldClass == Byte.class) {
-            unsafe.putObject(nodeInstance, offset, (byte) cp.getInt(cpi));
-        } else if (fieldClass == Short.class) {
-            unsafe.putObject(nodeInstance, offset, (short) cp.getInt(cpi));
-        } else if (fieldClass == Character.class) {
-            unsafe.putObject(nodeInstance, offset, (char) cp.getInt(cpi));
-        } else if (fieldClass == Boolean.class) {
-            unsafe.putObject(nodeInstance, offset, cp.getInt(cpi) == 1 ? Boolean.TRUE : Boolean.FALSE);
-        } else {
-            unsafe.putObject(nodeInstance, offset, cp.getObject(fieldClass, cpi));
-        }
-    }
-
-    private static void deserializeDataFieldsLengthNull(Node nodeInstance, Class<?> fieldClass, long offset) {
-        if (fieldClass == int.class) {
-            unsafe.putInt(nodeInstance, offset, 0);
-        } else if (fieldClass == long.class) {
-            unsafe.putLong(nodeInstance, offset, 0L);
-        } else if (fieldClass == float.class) {
-            unsafe.putFloat(nodeInstance, offset, 0.0F);
-        } else if (fieldClass == double.class) {
-            unsafe.putDouble(nodeInstance, offset, 0.0D);
-        } else if (fieldClass == byte.class) {
-            unsafe.putByte(nodeInstance, offset, (byte) 0);
-        } else if (fieldClass == short.class) {
-            unsafe.putShort(nodeInstance, offset, (short) 0);
-        } else if (fieldClass == char.class) {
-            unsafe.putChar(nodeInstance, offset, (char) 0);
-        } else if (fieldClass == boolean.class) {
-            unsafe.putBoolean(nodeInstance, offset, false);
-        } else {
-            unsafe.putObject(nodeInstance, offset, null);
-        }
-    }
-
-    private void deserializeChildFields(Node parent, NodeFieldAccessor[] nodeFields) {
-        for (int i = nodeFields.length - 1; i >= 0; i--) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.CHILD) {
-                unsafe.putObject(parent, field.getOffset(), popNode(parent, field.getType()));
-            }
-        }
-    }
-
-    private void deserializeChildrenFields(Node parent, NodeFieldAccessor[] nodeFields) {
-        for (int i = nodeFields.length - 1; i >= 0; i--) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.CHILDREN) {
-                unsafe.putObject(parent, field.getOffset(), popArray(parent, field.getType()));
-            }
-        }
-    }
-
-    private static Node updateParent(Node parent, Node child) {
-        if (child != null) {
-            NodeClass nodeClass = NodeClass.get(child.getClass());
-            nodeClass.getNodeClassField().putObject(child, nodeClass);
-            nodeClass.getParentField().putObject(child, parent);
-        }
-        return child;
-    }
-
-    private static Unsafe loadUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-    private static class HierarchicalStack {
-
-        private static final Object NULL_STACK = new Object();
-
-        private final List<Object> dynamicStack = new ArrayList<>();
-
-        void pushStack(Object[] array) {
-            if (array == null) {
-                dynamicStack.add(NULL_STACK);
-            } else {
-                dynamicStack.add(new FixedSizeNodeStack(array));
-            }
-        }
-
-        private FixedSizeNodeStack getTosStack() {
-            if (dynamicStack.isEmpty()) {
-                return null;
-            }
-            Object peekTos = dynamicStack.get(dynamicStack.size() - 1);
-            if (peekTos != null && peekTos.getClass() == FixedSizeNodeStack.class) {
-                return (FixedSizeNodeStack) peekTos;
-            }
-            return null;
-        }
-
-        Object[] popStack() {
-            Object tos = dynamicStack.remove(dynamicStack.size() - 1);
-            if (tos == NULL_STACK) {
-                return null;
-            }
-            return ((FixedSizeNodeStack) tos).getArray();
-        }
-
-        void push(Object o) {
-            FixedSizeNodeStack tosStack = getTosStack();
-            if (tosStack != null && !tosStack.isFull()) {
-                tosStack.push(o);
-            } else {
-                dynamicStack.add(o);
-            }
-        }
-
-        Object pop() {
-            FixedSizeNodeStack tosStack = getTosStack();
-            Object value;
-            if (tosStack != null) {
-                assert !tosStack.isEmpty();
-                value = tosStack.pop();
-            } else {
-                value = dynamicStack.remove(dynamicStack.size() - 1);
-            }
-            assert value != NULL_STACK;
-            return value;
-        }
-
-    }
-
-    private static class FixedSizeNodeStack {
-
-        private final Object[] array;
-
-        private int tos;
-
-        FixedSizeNodeStack(Object[] array) {
-            this.array = array;
-        }
-
-        boolean isFull() {
-            return tos == array.length;
-        }
-
-        boolean isEmpty() {
-            return tos == 0;
-        }
-
-        private void push(Object node) {
-            if (tos >= array.length) {
-                throw new ArrayIndexOutOfBoundsException();
-            }
-            unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (tos++), node);
-        }
-
-        private Object pop() {
-            if (tos <= 0) {
-                throw new ArrayIndexOutOfBoundsException();
-            }
-            return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (--tos));
-        }
-
-        private Object[] getArray() {
-            return array;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes.serial;
-
-import java.lang.reflect.*;
-import java.nio.*;
-
-import sun.misc.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Experimental API. May change without notice.
- */
-public final class PostOrderSerializer {
-
-    private static final Unsafe unsafe = loadUnsafe();
-
-    private final SerializerConstantPool cp;
-
-    /**
-     * Constructs a new deserializer using a custom {@link SerializerConstantPool} implementation.
-     * For the {@link SerializerConstantPool} implementation at least the following methods must be
-     * implemented:
-     * <ul>
-     * <li>{@link SerializerConstantPool#putInt(int)}</li>
-     * <li>{@link SerializerConstantPool#putClass(Class)}</li>
-     * </ul>
-     */
-    public PostOrderSerializer(SerializerConstantPool cp) {
-        this.cp = cp;
-    }
-
-    /**
-     * Serializes the node AST and returns the serialized data as byte array.
-     *
-     * @param node the root node that represents the Truffle AST that should be serialized.
-     * @return a trimmed byte array that contains the serialized data.
-     *
-     * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not
-     *             supported by the constant pool implementation.
-     */
-    public byte[] serialize(Node node) throws UnsupportedConstantPoolTypeException {
-        VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
-        serialize(buffer, node);
-        return buffer.getBytes();
-    }
-
-    private void serialize(VariableLengthIntBuffer buffer, Node node) throws UnsupportedConstantPoolTypeException {
-        if (node == null) {
-            buffer.put(VariableLengthIntBuffer.NULL);
-            return;
-        }
-        Class<? extends Node> nodeClass = node.getClass();
-
-        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
-        serializeChildFields(buffer, node, nodeFields);
-        serializeChildrenFields(buffer, node, nodeFields);
-        buffer.put(cp.putClass(node.getClass()));
-        serializeDataFields(buffer, node, nodeFields);
-    }
-
-    private void serializeDataFields(VariableLengthIntBuffer buffer, Node node, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
-        for (int i = 0; i < nodeFields.length; i++) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.DATA) {
-                Class<?> fieldClass = field.getType();
-                long offset = field.getOffset();
-                int cpi;
-
-                if (field.getType().isAssignableFrom(SourceSection.class)) {
-                    continue;
-                }
-
-                if (fieldClass == int.class) {
-                    cpi = cp.putInt(unsafe.getInt(node, offset));
-                } else if (fieldClass == long.class) {
-                    cpi = cp.putLong(unsafe.getLong(node, offset));
-                } else if (fieldClass == float.class) {
-                    cpi = cp.putFloat(unsafe.getFloat(node, offset));
-                } else if (fieldClass == double.class) {
-                    cpi = cp.putDouble(unsafe.getDouble(node, offset));
-                } else if (fieldClass == byte.class) {
-                    cpi = cp.putInt(unsafe.getByte(node, offset));
-                } else if (fieldClass == short.class) {
-                    cpi = cp.putInt(unsafe.getShort(node, offset));
-                } else if (fieldClass == char.class) {
-                    cpi = cp.putInt(unsafe.getChar(node, offset));
-                } else if (fieldClass == boolean.class) {
-                    cpi = cp.putInt(unsafe.getBoolean(node, offset) ? 1 : 0);
-                } else {
-                    cpi = serializeDataFieldsObject(node, fieldClass, offset);
-                }
-
-                buffer.put(cpi);
-            }
-        }
-    }
-
-    private int serializeDataFieldsObject(Node node, Class<?> fieldClass, long offset) {
-        Object value = unsafe.getObject(node, offset);
-        if (value == null) {
-            return VariableLengthIntBuffer.NULL;
-        } else if (fieldClass == Integer.class) {
-            return cp.putInt((Integer) value);
-        } else if (fieldClass == Long.class) {
-            return cp.putLong((Long) value);
-        } else if (fieldClass == Float.class) {
-            return cp.putFloat((Float) value);
-        } else if (fieldClass == Double.class) {
-            return cp.putDouble((Double) value);
-        } else if (fieldClass == Byte.class) {
-            return cp.putInt((Byte) value);
-        } else if (fieldClass == Short.class) {
-            return cp.putInt((Short) value);
-        } else if (fieldClass == Character.class) {
-            return cp.putInt((Character) value);
-        } else if (fieldClass == Boolean.class) {
-            return cp.putInt((Boolean) value ? 1 : 0);
-        } else {
-            return cp.putObject(fieldClass, value);
-        }
-    }
-
-    private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
-        for (int i = 0; i < nodeFields.length; i++) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.CHILDREN) {
-                Object childArrayObject = unsafe.getObject(nodeInstance, field.getOffset());
-                if (childArrayObject != null && !(childArrayObject instanceof Node[])) {
-                    throw new AssertionError("Node children must be instanceof Node[]");
-                }
-
-                buffer.put(cp.putClass(field.getType()));
-
-                Node[] childArray = (Node[]) childArrayObject;
-                if (childArray == null) {
-                    buffer.put(VariableLengthIntBuffer.NULL);
-                } else {
-                    buffer.put(cp.putInt(childArray.length));
-
-                    for (int j = 0; j < childArray.length; j++) {
-                        serialize(buffer, childArray[j]);
-                    }
-                }
-            }
-        }
-    }
-
-    private void serializeChildFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
-        for (int i = 0; i < nodeFields.length; i++) {
-            NodeFieldAccessor field = nodeFields[i];
-            if (field.getKind() == NodeFieldKind.CHILD) {
-                Object childObject = unsafe.getObject(nodeInstance, field.getOffset());
-                if (childObject != null && !(childObject instanceof Node)) {
-                    throw new AssertionError("Node children must be instanceof Node");
-                }
-                serialize(buffer, (Node) childObject);
-            }
-        }
-    }
-
-    private static Unsafe loadUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes.serial;
-
-/**
- * Experimental API. May change without notice. This interface is used as bridge between the
- * {@link PostOrderDeserializer}, {@link PostOrderSerializer} and underlying constant pool
- * implementation. A constant pool stores a value and returns an identifying index, with which the
- * object can later be returned from the pool again. All methods of this class are optional and may
- * throw a {@link UnsupportedOperationException}.
- */
-public interface SerializerConstantPool {
-
-    /**
-     * Returns the constant pool index of a value that is not a java native type, a java
-     * native-wrapper class or a {@link Class} instance. The implementor should support all
-     * additional types that are necessary to serialize a truffle AST for a specific truffle
-     * implementation. If a type is not supported by this constant pool implementation a
-     * {@link UnsupportedConstantPoolTypeException} should be thrown.
-     *
-     * @param clazz the {@link Class} of the value
-     * @param value the value to be stored. Must be at least a subclass of the given clazz.
-     * @return the constant pool index
-     * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in
-     *             the constant pool.
-     */
-    int putObject(Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException;
-
-    /**
-     * Stores a value in the constant pool that is not a java native type, a java native-wrapper
-     * class or a {@link Class} instance. The implementor should support all additional types that
-     * are necessary to serialize a truffle AST for a specific truffle implementation. If a type is
-     * not supported by this constant pool implementation a
-     * {@link UnsupportedConstantPoolTypeException} should be thrown.
-     *
-     * @param clazz the {@link Class} of the value in the constant pool.
-     * @param cpi the previously returned index
-     * @return the value stored inside the constant pool
-     * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in
-     *             the constant pool.
-     * @throws IllegalArgumentException if the provided cpi is not a valid constant pool index.
-     */
-    Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException;
-
-    /**
-     * Stores a Class instance in the constant pool and returns the constant pool index.
-     *
-     * @param value the class to store
-     * @return the new or existing constant pool index of the Class
-     */
-    int putClass(Class<?> value);
-
-    /**
-     * Returns the {@link Class} instance to the given constant pool index.
-     *
-     * @param cpi the constant pool index
-     * @return stored value
-     * @throws IllegalArgumentException if the constant pool indes is invalid.
-     */
-    Class<?> getClass(int cpi);
-
-    /**
-     * Stores an int value in the constant pool and returns the constant pool index.
-     *
-     * @param value the value to store
-     * @return the new or existing constant pool index of the value
-     */
-    int putInt(int value);
-
-    /**
-     * Returns the stored int value to the given constant pool index from the constant pool.
-     *
-     * @param cpi the constant pool index
-     * @return stored value
-     * @throws IllegalArgumentException if the constant pool index is invalid.
-     */
-    int getInt(int cpi);
-
-    /**
-     * Stores a long value in the constant pool and returns the constant pool index.
-     *
-     * @param value the value to store
-     * @return the new or existing constant pool index of the value
-     */
-    int putLong(long value);
-
-    /**
-     * Returns the stored long value to the given constant pool index from the constant pool.
-     *
-     * @param cpi the constant pool index
-     * @return the stored value
-     * @throws IllegalArgumentException if the constant pool index is invalid.
-     */
-    long getLong(int cpi);
-
-    /**
-     * Stores a double value in the constant pool and returns the constant pool index.
-     *
-     * @param value the value to store
-     * @return the new or existing constant pool index of the value
-     */
-    int putDouble(double value);
-
-    /**
-     * Returns the stored double value to the given constant pool index from the constant pool.
-     *
-     * @param cpi the constant pool index
-     * @return the stored value
-     * @throws IllegalArgumentException if the constant pool index is invalid.
-     */
-    double getDouble(int cpi);
-
-    /**
-     * Stores a float value in the constant pool and returns the constant pool index.
-     *
-     * @param value the value to store
-     * @return the new or existing constant pool index of the value
-     */
-    int putFloat(float value);
-
-    /**
-     * Returns the stored float value to the given constant pool index from the constant pool.
-     *
-     * @param cpi the constant pool index
-     * @return the stored value
-     * @throws IllegalArgumentException if the constant pool index is invalid.
-     */
-    float getFloat(int cpi);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/UnsupportedConstantPoolTypeException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes.serial;
-
-/**
- * Experimental API. May change without notice.
- */
-public class UnsupportedConstantPoolTypeException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public UnsupportedConstantPoolTypeException() {
-        super();
-    }
-
-    public UnsupportedConstantPoolTypeException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public UnsupportedConstantPoolTypeException(String message) {
-        super(message);
-    }
-
-    public UnsupportedConstantPoolTypeException(Throwable cause) {
-        super(cause);
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/VariableLengthIntBuffer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.nodes.serial;
-
-import java.nio.*;
-
-/**
- * Experimental API. May change without notice. Simple variable length unsigned int buffer backed by
- * a byte buffer.
- */
-public class VariableLengthIntBuffer {
-
-    public static final int NULL = -1;
-
-    private ByteBuffer buffer;
-
-    public VariableLengthIntBuffer(ByteBuffer buffer) {
-        this.buffer = buffer;
-    }
-
-    public VariableLengthIntBuffer(byte[] array) {
-        buffer = ByteBuffer.wrap(array);
-    }
-
-    /**
-     * Returns the backing byte buffer.
-     */
-    public ByteBuffer getBuffer() {
-        return buffer;
-    }
-
-    public byte[] getBytes() {
-        int pos = buffer.position();
-        byte[] bytes = new byte[buffer.position()];
-        buffer.rewind();
-        buffer.get(bytes);
-        buffer.position(pos);
-        return bytes;
-    }
-
-    public int get() {
-        byte peekByte = buffer.get(buffer.position());
-        if ((peekByte & 0x80) == 0) {
-            // single byte encoding with prefix 0 (range 127)
-            return buffer.get(); // no bit to be masked
-        } else {
-            if (peekByte == (byte) 0xFF) {
-                buffer.get(); // skip one byte
-                return NULL;
-            }
-            int result = buffer.getInt() & 0x7FFF_FFFF; // first bit masked out
-            assert (result & 0x4000_0000) == 0;
-            return result;
-        }
-    }
-
-    public void put(int i) {
-        ensureCapacity();
-        if (i == NULL) {
-            buffer.put((byte) 0xFF);
-        } else if ((i & 0xFFFF_FF80) == 0) { // 7 bits data
-            buffer.put((byte) i);
-        } else if ((i & 0xC000_0000) == 0) { // 32 bits data
-            buffer.putInt(i | 0x8000_0000); // append leading 1
-        } else {
-            throw new IllegalArgumentException("Integer out of encodeable " + i);
-        }
-    }
-
-    private void ensureCapacity() {
-        if (buffer.position() + 4 > buffer.capacity()) {
-            ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
-
-            int pos = buffer.position();
-            buffer.rewind();
-            newBuffer.put(buffer);
-            newBuffer.position(pos);
-
-            buffer = newBuffer;
-        }
-    }
-
-    public boolean hasRemaining() {
-        return buffer.hasRemaining();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.script;
-
-import javax.script.*;
-
-/**
- * Tool access to the creation of Truffle execution engines.
- */
-public abstract class TruffleScriptEngineFactory implements ScriptEngineFactory {
-
-    // TODO (mlvdv) first step, based on a suggestion from NetBeans
-    /**
-     * To be called by each concrete factory just after each engine instance is created, presenting
-     * an opportunity for an IDE to interrupt in a language-independent way.
-     *
-     * @param engine a just-created engine
-     */
-    protected final void engineCreated(ScriptEngine engine) {
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/BytesDecoder.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-import java.nio.charset.*;
-import java.util.*;
-
-/**
- * For a language where strings do not map into Java strings, provides utilities to find line
- * endings and to decode raw bytes into an approximate representation for tools to display.
- * <p>
- * See {@link Source#fromBytes}.
- */
-public interface BytesDecoder {
-
-    String decode(byte[] bytes, int byteIndex, int length);
-
-    void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker);
-
-    public interface LineMarker {
-
-        void markLine(int index);
-
-    }
-
-    public static class UTF8BytesDecoder implements BytesDecoder {
-
-        @Override
-        public String decode(byte[] bytes, int byteIndex, int length) {
-            return new String(Arrays.copyOfRange(bytes, byteIndex, byteIndex + length), StandardCharsets.UTF_8);
-        }
-
-        @Override
-        public void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker) {
-            for (int n = byteIndex; n < byteIndex + length; n++) {
-                if (bytes[n] == '\n') {
-                    lineMarker.markLine(n + 1);
-                }
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-import java.util.*;
-
-/**
- * A specification for a location in guest language source, expressed as a line number in a specific
- * instance of {@link Source}, suitable for hash table keys with equality defined in terms of
- * content.
- */
-public interface LineLocation {
-
-    Source getSource();
-
-    /**
-     * Gets the 1-based number of a line in the source.
-     */
-    int getLineNumber();
-
-    String getShortDescription();
-
-    /**
-     * Default comparator by (1) textual path name, (2) line number.
-     */
-    Comparator<LineLocation> COMPARATOR = new Comparator<LineLocation>() {
-
-        public int compare(LineLocation l1, LineLocation l2) {
-            final int sourceResult = l1.getSource().getPath().compareTo(l2.getSource().getPath());
-            if (sourceResult != 0) {
-                return sourceResult;
-            }
-            return Integer.compare(l1.getLineNumber(), l2.getLineNumber());
-        }
-
-    };
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * A special subtype of {@link SourceSection} that represents unavailable source, e.g. for language
- * <em>builtins</em>.
- */
-public class NullSourceSection implements SourceSection {
-
-    private final String kind;
-    private final String name;
-    private final String asCode;
-
-    /**
-     * Placeholder for source that is unavailable, e.g. for language <em>builtins</em>.
-     *
-     * @param kind the general category, e.g. "JS builtin"
-     * @param name specific name for this section
-     */
-    public NullSourceSection(String kind, String name) {
-        this(kind, name, kind);
-    }
-
-    /**
-     * Placeholder for source that is unavailable, e.g. for language <em>builtins</em>.
-     *
-     * @param kind the general category, e.g. "JS builtin"
-     * @param name specific name for this section
-     * @param asCode string to return when {@link #getCode()} is called
-     */
-    public NullSourceSection(String kind, String name, String asCode) {
-        this.kind = kind;
-        this.name = name;
-        this.asCode = asCode;
-    }
-
-    public final Source getSource() {
-        return null;
-    }
-
-    public final int getStartLine() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final LineLocation getLineLocation() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final int getStartColumn() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public int getEndLine() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public int getEndColumn() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final int getCharIndex() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final int getCharLength() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final int getCharEndIndex() {
-        throw new UnsupportedOperationException(this.toString());
-    }
-
-    public final String getIdentifier() {
-        return name;
-    }
-
-    public final String getCode() {
-        return asCode;
-    }
-
-    public final String getShortDescription() {
-        return kind + ": " + name;
-    }
-
-    @Override
-    public String toString() {
-        return getShortDescription();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1553 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-import java.io.*;
-import java.lang.ref.*;
-import java.net.*;
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-
-/**
- * Representation of a guest language source code unit and its contents. Sources originate in
- * several ways:
- * <ul>
- * <li><strong>Literal:</strong> An anonymous text string: not named and not indexed. These should
- * be considered value objects; equality is defined based on contents.<br>
- * See {@link Source#fromText(CharSequence, String)}</li>
- * <p>
- * <li><strong>Named Literal:</strong> A text string that can be retrieved by name as if it were a
- * file, but without any assumption that the name is related to a file path. Creating a new literal
- * with an already existing name will replace its predecessor in the index.<br>
- * See {@link Source#fromNamedText(CharSequence, String)}<br>
- * See {@link Source#find(String)}</li>
- * <p>
- * <li><strong>File:</strong> Each file is represented as a canonical object, indexed by the
- * absolute, canonical path name of the file. File contents are <em>read lazily</em> and contents
- * optionally <em>cached</em>. <br>
- * See {@link Source#fromFileName(String)}<br>
- * See {@link Source#fromFileName(String, boolean)}<br>
- * See {@link Source#find(String)}</li>
- * <p>
- * <li><strong>URL:</strong> Each URL source is represented as a canonical object, indexed by the
- * URL. Contents are <em>read eagerly</em> and <em>cached</em>. <br>
- * See {@link Source#fromURL(URL, String)}<br>
- * See {@link Source#find(String)}</li>
- * <p>
- * <li><strong>Reader:</strong> Contents are <em>read eagerly</em> and treated as an anonymous
- * (non-indexed) <em>Literal</em> . <br>
- * See {@link Source#fromReader(Reader, String)}</li>
- * <p>
- * <li><strong>Sub-Source:</strong> A representation of the contents of a sub-range of another
- * {@link Source}.<br>
- * See @link {@link Source#subSource(Source, int, int)}<br>
- * See @link {@link Source#subSource(Source, int)}</li>
- * <p>
- * <li><strong>AppendableSource:</strong> Literal contents are provided by the client,
- * incrementally, after the instance is created.<br>
- * See {@link Source#fromAppendableText(String)}<br>
- * See {@link Source#fromNamedAppendableText(String)}</li>
- * </ul>
- * <p>
- * <strong>File cache:</strong>
- * <ol>
- * <li>File content caching is optional, <em>on</em> by default.</li>
- * <li>The first access to source file contents will result in the contents being read, and (if
- * enabled) cached.</li>
- * <li>If file contents have been cached, access to contents via {@link Source#getInputStream()} or
- * {@link Source#getReader()} will be provided from the cache.</li>
- * <li>Any access to file contents via the cache will result in a timestamp check and possible cache
- * reload.</li>
- * </ol>
- * <p>
- *
- * @see SourceTag
- * @see SourceListener
- */
-public abstract class Source {
-
-    // TODO (mlvdv) consider canonicalizing and reusing SourceSection instances
-    // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup
-
-    public enum Tags implements SourceTag {
-
-        /**
-         * From bytes.
-         */
-        FROM_BYTES("bytes", "read from bytes"),
-
-        /**
-         * Read from a file.
-         */
-        FROM_FILE("file", "read from a file"),
-
-        /**
-         * From literal text.
-         */
-        FROM_LITERAL("literal", "from literal text"),
-
-        /**
-         * From a {@linkplain java.io.Reader Reader}.
-         */
-        FROM_READER("reader", "read from a Java Reader"),
-
-        /**
-         * Read from a URL.
-         */
-        FROM_URL("URL", "read from a URL");
-
-        private final String name;
-        private final String description;
-
-        private Tags(String name, String description) {
-            this.name = name;
-            this.description = description;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-    }
-
-    /**
-     * All Sources that have been created.
-     */
-    private static final List<WeakReference<Source>> allSources = Collections.synchronizedList(new ArrayList<WeakReference<Source>>());
-
-    /**
-     * Index of all named sources.
-     */
-    private static final Map<String, WeakReference<Source>> nameToSource = new HashMap<>();
-
-    private static boolean fileCacheEnabled = true;
-
-    private static final List<SourceListener> sourceListeners = new ArrayList<>();
-
-    /**
-     * Locates an existing instance by the name under which it was indexed.
-     */
-    public static Source find(String name) {
-        final WeakReference<Source> nameRef = nameToSource.get(name);
-        return nameRef == null ? null : nameRef.get();
-    }
-
-    /**
-     * Gets the canonical representation of a source file, whose contents will be read lazily and
-     * then cached.
-     *
-     * @param fileName name
-     * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read
-     * @return canonical representation of the file's contents.
-     * @throws IOException if the file can not be read
-     */
-    public static Source fromFileName(String fileName, boolean reset) throws IOException {
-
-        final WeakReference<Source> nameRef = nameToSource.get(fileName);
-        Source source = nameRef == null ? null : nameRef.get();
-        if (source == null) {
-            final File file = new File(fileName);
-            if (!file.canRead()) {
-                throw new IOException("Can't read file " + fileName);
-            }
-            final String path = file.getCanonicalPath();
-            final WeakReference<Source> pathRef = nameToSource.get(path);
-            source = pathRef == null ? null : pathRef.get();
-            if (source == null) {
-                source = new FileSource(file, fileName, path);
-                nameToSource.put(path, new WeakReference<>(source));
-            }
-        }
-        if (reset) {
-            source.reset();
-        }
-        notifyNewSource(source).tagAs(Tags.FROM_FILE);
-        return source;
-    }
-
-    /**
-     * Gets the canonical representation of a source file, whose contents will be read lazily and
-     * then cached.
-     *
-     * @param fileName name
-     * @return canonical representation of the file's contents.
-     * @throws IOException if the file can not be read
-     */
-    public static Source fromFileName(String fileName) throws IOException {
-        return fromFileName(fileName, false);
-    }
-
-    /**
-     * Gets the canonical representation of a source file, whose contents have already been read and
-     * need not be read again. It is confirmed that the file resolves to a file name, so it can be
-     * indexed by canonical path. It is not confirmed that the text supplied agrees with the file's
-     * contents or even whether the file is readable.
-     *
-     * @param chars textual source code already read from the file
-     * @param fileName
-     * @return canonical representation of the file's contents.
-     * @throws IOException if the file cannot be found
-     */
-    public static Source fromFileName(CharSequence chars, String fileName) throws IOException {
-
-        final WeakReference<Source> nameRef = nameToSource.get(fileName);
-        Source source = nameRef == null ? null : nameRef.get();
-        if (source == null) {
-            final File file = new File(fileName);
-            // We are going to trust that the fileName is readable.
-            final String path = file.getCanonicalPath();
-            final WeakReference<Source> pathRef = nameToSource.get(path);
-            source = pathRef == null ? null : pathRef.get();
-            if (source == null) {
-                source = new FileSource(file, fileName, path, chars);
-                nameToSource.put(path, new WeakReference<>(source));
-            }
-        }
-        notifyNewSource(source).tagAs(Tags.FROM_FILE);
-        return source;
-    }
-
-    /**
-     * Creates an anonymous source from literal text: not named and not indexed.
-     *
-     * @param chars textual source code
-     * @param description a note about the origin, for error messages and debugging
-     * @return a newly created, non-indexed source representation
-     */
-    public static Source fromText(CharSequence chars, String description) {
-        assert chars != null;
-        final LiteralSource source = new LiteralSource(description, chars.toString());
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
-    }
-
-    /**
-     * Creates an anonymous source from literal text that is provided incrementally after creation:
-     * not named and not indexed.
-     *
-     * @param description a note about the origin, for error messages and debugging
-     * @return a newly created, non-indexed, initially empty, appendable source representation
-     */
-    public static Source fromAppendableText(String description) {
-        final Source source = new AppendableLiteralSource(description);
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
-    }
-
-    /**
-     * Creates a source from literal text that can be retrieved by name, with no assumptions about
-     * the structure or meaning of the name. If the name is already in the index, the new instance
-     * will replace the previously existing instance in the index.
-     *
-     * @param chars textual source code
-     * @param name string to use for indexing/lookup
-     * @return a newly created, source representation
-     */
-    public static Source fromNamedText(CharSequence chars, String name) {
-        final Source source = new LiteralSource(name, chars.toString());
-        nameToSource.put(name, new WeakReference<>(source));
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
-    }
-
-    /**
-     * Creates a source from literal text that is provided incrementally after creation and which
-     * can be retrieved by name, with no assumptions about the structure or meaning of the name. If
-     * the name is already in the index, the new instance will replace the previously existing
-     * instance in the index.
-     *
-     * @param name string to use for indexing/lookup
-     * @return a newly created, indexed, initially empty, appendable source representation
-     */
-    public static Source fromNamedAppendableText(String name) {
-        final Source source = new AppendableLiteralSource(name);
-        nameToSource.put(name, new WeakReference<>(source));
-        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
-        return source;
-    }
-
-    /**
-     * Creates a {@linkplain Source Source instance} that represents the contents of a sub-range of
-     * an existing {@link Source}.
-     *
-     * @param base an existing Source instance
-     * @param baseCharIndex 0-based index of the first character of the sub-range
-     * @param length the number of characters in the sub-range
-     * @return a new instance representing a sub-range of another Source
-     * @throws IllegalArgumentException if the specified sub-range is not contained in the base
-     */
-    public static Source subSource(Source base, int baseCharIndex, int length) {
-        final SubSource subSource = SubSource.create(base, baseCharIndex, length);
-        return subSource;
-    }
-
-    /**
-     * Creates a {@linkplain Source Source instance} that represents the contents of a sub-range at
-     * the end of an existing {@link Source}.
-     *
-     * @param base an existing Source instance
-     * @param baseCharIndex 0-based index of the first character of the sub-range
-     * @return a new instance representing a sub-range at the end of another Source
-     * @throws IllegalArgumentException if the index is out of range
-     */
-    public static Source subSource(Source base, int baseCharIndex) {
-        return subSource(base, baseCharIndex, base.getLength() - baseCharIndex);
-    }
-
-    /**
-     * Creates a source whose contents will be read immediately from a URL and cached.
-     *
-     * @param url
-     * @param description identifies the origin, possibly useful for debugging
-     * @return a newly created, non-indexed source representation
-     * @throws IOException if reading fails
-     */
-    public static Source fromURL(URL url, String description) throws IOException {
-        final URLSource source = URLSource.get(url, description);
-        notifyNewSource(source).tagAs(Tags.FROM_URL);
-        return source;
-    }
-
-    /**
-     * Creates a source whose contents will be read immediately and cached.
-     *
-     * @param reader
-     * @param description a note about the origin, possibly useful for debugging
-     * @return a newly created, non-indexed source representation
-     * @throws IOException if reading fails
-     */
-    public static Source fromReader(Reader reader, String description) throws IOException {
-        final LiteralSource source = new LiteralSource(description, read(reader));
-        notifyNewSource(source).tagAs(Tags.FROM_READER);
-        return source;
-    }
-
-    /**
-     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
-     * is not compatible with Java strings, or if your parser returns byte indices instead of
-     * character indices. The returned source is then indexed by byte, not by character.
-     *
-     * @param bytes the raw bytes of the source
-     * @param description a note about the origin, possibly useful for debugging
-     * @param decoder how to decode the bytes into Java strings
-     * @return a newly created, non-indexed source representation
-     */
-    public static Source fromBytes(byte[] bytes, String description, BytesDecoder decoder) {
-        return fromBytes(bytes, 0, bytes.length, description, decoder);
-    }
-
-    /**
-     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
-     * is not compatible with Java strings, or if your parser returns byte indices instead of
-     * character indices. The returned source is then indexed by byte, not by character. Offsets are
-     * relative to byteIndex.
-     *
-     * @param bytes the raw bytes of the source
-     * @param byteIndex where the string starts in the byte array
-     * @param length the length of the string in the byte array
-     * @param description a note about the origin, possibly useful for debugging
-     * @param decoder how to decode the bytes into Java strings
-     * @return a newly created, non-indexed source representation
-     */
-    public static Source fromBytes(byte[] bytes, int byteIndex, int length, String description, BytesDecoder decoder) {
-        final BytesSource source = new BytesSource(description, bytes, byteIndex, length, decoder);
-        notifyNewSource(source).tagAs(Tags.FROM_BYTES);
-        return source;
-    }
-
-    // TODO (mlvdv) enable per-file choice whether to cache?
-    /**
-     * Enables/disables caching of file contents, <em>disabled</em> by default. Caching of sources
-     * created from literal text or readers is always enabled.
-     */
-    public static void setFileCaching(boolean enabled) {
-        fileCacheEnabled = enabled;
-    }
-
-    /**
-     * Returns all {@link Source}s holding a particular {@link SyntaxTag}, or the whole collection
-     * of Sources if the specified tag is {@code null}.
-     *
-     * @return A collection of Sources containing the given tag.
-     */
-    public static Collection<Source> findSourcesTaggedAs(SourceTag tag) {
-        final List<Source> taggedSources = new ArrayList<>();
-        synchronized (allSources) {
-            for (WeakReference<Source> ref : allSources) {
-                Source source = ref.get();
-                if (source != null) {
-                    if (tag == null || source.isTaggedAs(tag)) {
-                        taggedSources.add(ref.get());
-                    }
-                }
-            }
-        }
-        return taggedSources;
-    }
-
-    /**
-     * Adds a {@link SourceListener} to receive events.
-     */
-    public static void addSourceListener(SourceListener listener) {
-        assert listener != null;
-        sourceListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link SourceListener}. Ignored if listener not found.
-     */
-    public static void removeSourceListener(SourceListener listener) {
-        sourceListeners.remove(listener);
-    }
-
-    private static Source notifyNewSource(Source source) {
-        allSources.add(new WeakReference<>(source));
-        for (SourceListener listener : sourceListeners) {
-            listener.sourceCreated(source);
-        }
-        return source;
-    }
-
-    private static String read(Reader reader) throws IOException {
-        final BufferedReader bufferedReader = new BufferedReader(reader);
-        final StringBuilder builder = new StringBuilder();
-        final char[] buffer = new char[1024];
-
-        while (true) {
-            final int n = bufferedReader.read(buffer);
-            if (n == -1) {
-                break;
-            }
-            builder.append(buffer, 0, n);
-        }
-
-        return builder.toString();
-    }
-
-    private final ArrayList<SourceTag> tags = new ArrayList<>();
-
-    private Source() {
-    }
-
-    private TextMap textMap = null;
-
-    protected abstract void reset();
-
-    public final boolean isTaggedAs(SourceTag tag) {
-        assert tag != null;
-        return tags.contains(tag);
-    }
-
-    public final Collection<SourceTag> getSourceTags() {
-        return Collections.unmodifiableCollection(tags);
-    }
-
-    /**
-     * Adds a {@linkplain SourceTag tag} to the set of tags associated with this {@link Source};
-     * {@code no-op} if already in the set.
-     *
-     * @return this
-     */
-    public final Source tagAs(SourceTag tag) {
-        assert tag != null;
-        if (!tags.contains(tag)) {
-            tags.add(tag);
-            for (SourceListener listener : sourceListeners) {
-                listener.sourceTaggedAs(this, tag);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * Returns the name of this resource holding a guest language program. An example would be the
-     * name of a guest language source code file.
-     *
-     * @return the name of the guest language program
-     */
-    public abstract String getName();
-
-    /**
-     * Returns a short version of the name of the resource holding a guest language program (as
-     * described in @getName). For example, this could be just the name of the file, rather than a
-     * full path.
-     *
-     * @return the short name of the guest language program
-     */
-    public abstract String getShortName();
-
-    /**
-     * The normalized, canonical name if the source is a file.
-     */
-    public abstract String getPath();
-
-    /**
-     * The URL if the source is retrieved via URL.
-     */
-    public abstract URL getURL();
-
-    /**
-     * Access to the source contents.
-     */
-    public abstract Reader getReader();
-
-    /**
-     * Access to the source contents.
-     */
-    public final InputStream getInputStream() {
-        return new ByteArrayInputStream(getCode().getBytes());
-    }
-
-    /**
-     * Gets the number of characters in the source.
-     */
-    public final int getLength() {
-        return getTextMap().length();
-    }
-
-    /**
-     * Returns the complete text of the code.
-     */
-    public abstract String getCode();
-
-    /**
-     * Returns a subsection of the code test.
-     */
-    public String getCode(int charIndex, int charLength) {
-        return getCode().substring(charIndex, charIndex + charLength);
-    }
-
-    /**
-     * Gets the text (not including a possible terminating newline) in a (1-based) numbered line.
-     */
-    public final String getCode(int lineNumber) {
-        final int offset = getTextMap().lineStartOffset(lineNumber);
-        final int length = getTextMap().lineLength(lineNumber);
-        return getCode().substring(offset, offset + length);
-    }
-
-    /**
-     * The number of text lines in the source, including empty lines; characters at the end of the
-     * source without a terminating newline count as a line.
-     */
-    public final int getLineCount() {
-        return getTextMap().lineCount();
-    }
-
-    /**
-     * Given a 0-based character offset, return the 1-based number of the line that includes the
-     * position.
-     *
-     * @throws IllegalArgumentException if the offset is outside the text contents
-     */
-    public final int getLineNumber(int offset) throws IllegalArgumentException {
-        return getTextMap().offsetToLine(offset);
-    }
-
-    /**
-     * Given a 0-based character offset, return the 1-based number of the column at the position.
-     *
-     * @throws IllegalArgumentException if the offset is outside the text contents
-     */
-    public final int getColumnNumber(int offset) throws IllegalArgumentException {
-        return getTextMap().offsetToCol(offset);
-    }
-
-    /**
-     * Given a 1-based line number, return the 0-based offset of the first character in the line.
-     *
-     * @throws IllegalArgumentException if there is no such line in the text
-     */
-    public final int getLineStartOffset(int lineNumber) throws IllegalArgumentException {
-        return getTextMap().lineStartOffset(lineNumber);
-    }
-
-    /**
-     * The number of characters (not counting a possible terminating newline) in a (1-based)
-     * numbered line.
-     *
-     * @throws IllegalArgumentException if there is no such line in the text
-     */
-    public final int getLineLength(int lineNumber) throws IllegalArgumentException {
-        return getTextMap().lineLength(lineNumber);
-    }
-
-    /**
-     * Append text to a Source explicitly created as <em>Appendable</em>.
-     *
-     * @param chars the text to append
-     * @throws UnsupportedOperationException by concrete subclasses that do not support appending
-     */
-    public void appendCode(CharSequence chars) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Creates a representation of a contiguous region of text in the source.
-     * <p>
-     * This method performs no checks on the validity of the arguments.
-     * <p>
-     * The resulting representation defines hash/equality around equivalent location, presuming that
-     * {@link Source} representations are canonical.
-     *
-     * @param identifier terse description of the region
-     * @param startLine 1-based line number of the first character in the section
-     * @param startColumn 1-based column number of the first character in the section
-     * @param charIndex the 0-based index of the first character of the section
-     * @param length the number of characters in the section
-     * @return newly created object representing the specified region
-     */
-    public final SourceSection createSection(String identifier, int startLine, int startColumn, int charIndex, int length) {
-        return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length);
-    }
-
-    /**
-     * Creates a representation of a contiguous region of text in the source. Computes the
-     * {@code charIndex} value by building a {@linkplain TextMap map} of lines in the source.
-     * <p>
-     * Checks the position arguments for consistency with the source.
-     * <p>
-     * The resulting representation defines hash/equality around equivalent location, presuming that
-     * {@link Source} representations are canonical.
-     *
-     * @param identifier terse description of the region
-     * @param startLine 1-based line number of the first character in the section
-     * @param startColumn 1-based column number of the first character in the section
-     * @param length the number of characters in the section
-     * @return newly created object representing the specified region
-     * @throws IllegalArgumentException if arguments are outside the text of the source
-     * @throws IllegalStateException if the source is one of the "null" instances
-     */
-    public final SourceSection createSection(String identifier, int startLine, int startColumn, int length) {
-        final int lineStartOffset = getTextMap().lineStartOffset(startLine);
-        if (startColumn > getTextMap().lineLength(startLine)) {
-            throw new IllegalArgumentException("column out of range");
-        }
-        final int startOffset = lineStartOffset + startColumn - 1;
-        return new DefaultSourceSection(this, identifier, startLine, startColumn, startOffset, length);
-    }
-
-    /**
-     * Creates a representation of a contiguous region of text in the source. Computes the
-     * {@code (startLine, startColumn)} values by building a {@linkplain TextMap map} of lines in
-     * the source.
-     * <p>
-     * Checks the position arguments for consistency with the source.
-     * <p>
-     * The resulting representation defines hash/equality around equivalent location, presuming that
-     * {@link Source} representations are canonical.
-     *
-     *
-     * @param identifier terse description of the region
-     * @param charIndex 0-based position of the first character in the section
-     * @param length the number of characters in the section
-     * @return newly created object representing the specified region
-     * @throws IllegalArgumentException if either of the arguments are outside the text of the
-     *             source
-     * @throws IllegalStateException if the source is one of the "null" instances
-     */
-    public final SourceSection createSection(String identifier, int charIndex, int length) throws IllegalArgumentException {
-        checkRange(charIndex, length);
-        final int startLine = getLineNumber(charIndex);
-        final int startColumn = charIndex - getLineStartOffset(startLine) + 1;
-        return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length);
-    }
-
-    protected void checkRange(int charIndex, int length) {
-        if (!(charIndex >= 0 && length >= 0 && charIndex + length <= getCode().length())) {
-            throw new IllegalArgumentException("text positions out of range");
-        }
-    }
-
-    /**
-     * Creates a representation of a line of text in the source identified only by line number, from
-     * which the character information will be computed.
-     *
-     * @param identifier terse description of the line
-     * @param lineNumber 1-based line number of the first character in the section
-     * @return newly created object representing the specified line
-     * @throws IllegalArgumentException if the line does not exist the source
-     * @throws IllegalStateException if the source is one of the "null" instances
-     */
-    public final SourceSection createSection(String identifier, int lineNumber) {
-        final int charIndex = getTextMap().lineStartOffset(lineNumber);
-        final int length = getTextMap().lineLength(lineNumber);
-        return createSection(identifier, charIndex, length);
-    }
-
-    /**
-     * Creates a representation of a line number in this source, suitable for use as a hash table
-     * key with equality defined to mean equivalent location.
-     *
-     * @param lineNumber a 1-based line number in this source
-     * @return a representation of a line in this source
-     */
-    public final LineLocation createLineLocation(int lineNumber) {
-        return new LineLocationImpl(this, lineNumber);
-    }
-
-    /**
-     * An object suitable for using as a key into a hashtable that defines equivalence between
-     * different source types.
-     */
-    protected Object getHashKey() {
-        return getName();
-    }
-
-    protected final TextMap getTextMap() {
-        if (textMap == null) {
-            textMap = createTextMap();
-        }
-        return textMap;
-    }
-
-    protected final void clearTextMap() {
-        textMap = null;
-    }
-
-    protected TextMap createTextMap() {
-        final String code = getCode();
-        if (code == null) {
-            throw new RuntimeException("can't read file " + getName());
-        }
-        return TextMap.fromString(code);
-    }
-
-    private static final class LiteralSource extends Source {
-
-        private final String description;
-        private final String code;
-
-        public LiteralSource(String description, String code) {
-            this.description = description;
-            this.code = code;
-        }
-
-        @Override
-        public String getName() {
-            return description;
-        }
-
-        @Override
-        public String getShortName() {
-            return description;
-        }
-
-        @Override
-        public String getCode() {
-            return code;
-        }
-
-        @Override
-        public String getPath() {
-            return description;
-        }
-
-        @Override
-        public URL getURL() {
-            return null;
-        }
-
-        @Override
-        public Reader getReader() {
-            return new StringReader(code);
-        }
-
-        @Override
-        protected void reset() {
-        }
-
-        @Override
-        public int hashCode() {
-            return description.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (obj instanceof LiteralSource) {
-                LiteralSource other = (LiteralSource) obj;
-                return description.equals(other.description);
-            }
-            return false;
-        }
-    }
-
-    private static final class AppendableLiteralSource extends Source {
-        private String description;
-        final List<CharSequence> codeList = new ArrayList<>();
-
-        public AppendableLiteralSource(String description) {
-            this.description = description;
-        }
-
-        @Override
-        public String getName() {
-            return description;
-        }
-
-        @Override
-        public String getShortName() {
-            return description;
-        }
-
-        @Override
-        public String getCode() {
-            return getCodeFromIndex(0);
-        }
-
-        @Override
-        public String getPath() {
-            return description;
-        }
-
-        @Override
-        public URL getURL() {
-            return null;
-        }
-
-        @Override
-        public Reader getReader() {
-            return new StringReader(getCode());
-        }
-
-        @Override
-        protected void reset() {
-        }
-
-        private String getCodeFromIndex(int index) {
-            StringBuilder sb = new StringBuilder();
-            for (int i = index; i < codeList.size(); i++) {
-                CharSequence s = codeList.get(i);
-                sb.append(s);
-            }
-            return sb.toString();
-        }
-
-        @Override
-        public void appendCode(CharSequence chars) {
-            codeList.add(chars);
-            clearTextMap();
-        }
-
-    }
-
-    private static final class FileSource extends Source {
-
-        private final File file;
-        private final String name; // Name used originally to describe the source
-        private final String path;  // Normalized path description of an actual file
-
-        private String code = null;  // A cache of the file's contents
-        private long timeStamp;      // timestamp of the cache in the file system
-
-        public FileSource(File file, String name, String path) {
-            this(file, name, path, null);
-        }
-
-        public FileSource(File file, String name, String path, CharSequence chars) {
-            this.file = file.getAbsoluteFile();
-            this.name = name;
-            this.path = path;
-            if (chars != null) {
-                this.code = chars.toString();
-            }
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public String getShortName() {
-            return file.getName();
-        }
-
-        @Override
-        protected Object getHashKey() {
-            return path;
-        }
-
-        @Override
-        public String getCode() {
-            if (fileCacheEnabled) {
-                if (code == null || timeStamp != file.lastModified()) {
-                    try {
-                        code = read(getReader());
-                        timeStamp = file.lastModified();
-                    } catch (IOException e) {
-                    }
-                }
-                return code;
-            }
-            try {
-                return read(new FileReader(file));
-            } catch (IOException e) {
-            }
-            return null;
-        }
-
-        @Override
-        public String getPath() {
-            return path;
-        }
-
-        @Override
-        public URL getURL() {
-            return null;
-        }
-
-        @Override
-        public Reader getReader() {
-            if (code != null && timeStamp == file.lastModified()) {
-                return new StringReader(code);
-            }
-            try {
-                return new FileReader(file);
-            } catch (FileNotFoundException e) {
-
-                throw new RuntimeException("Can't find file " + path, e);
-            }
-        }
-
-        @Override
-        public int hashCode() {
-            return path.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj instanceof FileSource) {
-                FileSource other = (FileSource) obj;
-                return path.equals(other.path);
-            }
-            return false;
-        }
-
-        @Override
-        protected void reset() {
-            this.code = null;
-        }
-    }
-
-    private static final class URLSource extends Source {
-
-        private static final Map<URL, WeakReference<URLSource>> urlToSource = new HashMap<>();
-
-        public static URLSource get(URL url, String name) throws IOException {
-            WeakReference<URLSource> sourceRef = urlToSource.get(url);
-            URLSource source = sourceRef == null ? null : sourceRef.get();
-            if (source == null) {
-                source = new URLSource(url, name);
-                urlToSource.put(url, new WeakReference<>(source));
-            }
-            return source;
-        }
-
-        private final URL url;
-        private final String name;
-        private String code = null;  // A cache of the source contents
-
-        public URLSource(URL url, String name) throws IOException {
-            this.url = url;
-            this.name = name;
-            code = read(new InputStreamReader(url.openStream()));
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public String getShortName() {
-            return name;
-        }
-
-        @Override
-        public String getPath() {
-            return url.getPath();
-        }
-
-        @Override
-        public URL getURL() {
-            return url;
-        }
-
-        @Override
-        public Reader getReader() {
-            return new StringReader(code);
-        }
-
-        @Override
-        public String getCode() {
-            return code;
-        }
-
-        @Override
-        protected void reset() {
-        }
-    }
-
-    private static final class SubSource extends Source {
-        private final Source base;
-        private final int baseIndex;
-        private final int subLength;
-
-        private static SubSource create(Source base, int baseIndex, int length) {
-            if (baseIndex < 0 || length < 0 || baseIndex + length > base.getLength()) {
-                throw new IllegalArgumentException("text positions out of range");
-            }
-            return new SubSource(base, baseIndex, length);
-        }
-
-        private SubSource(Source base, int baseIndex, int length) {
-            this.base = base;
-            this.baseIndex = baseIndex;
-            this.subLength = length;
-        }
-
-        @Override
-        protected void reset() {
-            assert false;
-        }
-
-        @Override
-        public String getName() {
-            return base.getName();
-        }
-
-        @Override
-        public String getShortName() {
-            return base.getShortName();
-        }
-
-        @Override
-        public String getPath() {
-            return base.getPath();
-        }
-
-        @Override
-        public URL getURL() {
-            return null;
-        }
-
-        @Override
-        public Reader getReader() {
-            assert false;
-            return null;
-        }
-
-        @Override
-        public String getCode() {
-            return base.getCode(baseIndex, subLength);
-        }
-    }
-
-    private static final class BytesSource extends Source {
-
-        private final String name;
-        private final byte[] bytes;
-        private final int byteIndex;
-        private final int length;
-        private final BytesDecoder decoder;
-
-        public BytesSource(String name, byte[] bytes, int byteIndex, int length, BytesDecoder decoder) {
-            this.name = name;
-            this.bytes = bytes;
-            this.byteIndex = byteIndex;
-            this.length = length;
-            this.decoder = decoder;
-        }
-
-        @Override
-        protected void reset() {
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public String getShortName() {
-            return name;
-        }
-
-        @Override
-        public String getPath() {
-            return name;
-        }
-
-        @Override
-        public URL getURL() {
-            return null;
-        }
-
-        @Override
-        public Reader getReader() {
-            return null;
-        }
-
-        @Override
-        public String getCode() {
-            return decoder.decode(bytes, byteIndex, length);
-        }
-
-        @Override
-        public String getCode(int byteOffset, int codeLength) {
-            return decoder.decode(bytes, byteIndex + byteOffset, codeLength);
-        }
-
-        @Override
-        protected void checkRange(int charIndex, int rangeLength) {
-            if (!(charIndex >= 0 && rangeLength >= 0 && charIndex + rangeLength <= length)) {
-                throw new IllegalArgumentException("text positions out of range");
-            }
-        }
-
-        @Override
-        protected TextMap createTextMap() {
-            return TextMap.fromBytes(bytes, byteIndex, length, decoder);
-        }
-    }
-
-    private static final class DefaultSourceSection implements SourceSection {
-
-        private final Source source;
-        private final String identifier;
-        private final int startLine;
-        private final int startColumn;
-        private final int charIndex;
-        private final int charLength;
-
-        /**
-         * Creates a new object representing a contiguous text section within the source code of a
-         * guest language program's text.
-         * <p>
-         * The starting location of the section is specified using two different coordinate:
-         * <ul>
-         * <li><b>(row, column)</b>: rows and columns are 1-based, so the first character in a
-         * source file is at position {@code (1,1)}.</li>
-         * <li><b>character index</b>: 0-based offset of the character from the beginning of the
-         * source, so the first character in a file is at index {@code 0}.</li>
-         * </ul>
-         * The <b>newline</b> that terminates each line counts as a single character for the purpose
-         * of a character index. The (row,column) coordinates of a newline character should never
-         * appear in a text section.
-         * <p>
-         *
-         * @param source object representing the complete source program that contains this section
-         * @param identifier an identifier used when printing the section
-         * @param startLine the 1-based number of the start line of the section
-         * @param startColumn the 1-based number of the start column of the section
-         * @param charIndex the 0-based index of the first character of the section
-         * @param charLength the length of the section in number of characters
-         */
-        public DefaultSourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
-            this.source = source;
-            this.identifier = identifier;
-            this.startLine = startLine;
-            this.startColumn = startColumn;
-            this.charIndex = charIndex;
-            this.charLength = charLength;
-        }
-
-        @Override
-        public Source getSource() {
-            return source;
-        }
-
-        @Override
-        public int getStartLine() {
-            return startLine;
-        }
-
-        @Override
-        public LineLocation getLineLocation() {
-            return source.createLineLocation(startLine);
-        }
-
-        @Override
-        public int getStartColumn() {
-            return startColumn;
-        }
-
-        public int getEndLine() {
-            return source.getLineNumber(charIndex + charLength - 1);
-        }
-
-        public int getEndColumn() {
-            return source.getColumnNumber(charIndex + charLength - 1);
-        }
-
-        @Override
-        public int getCharIndex() {
-            return charIndex;
-        }
-
-        @Override
-        public int getCharLength() {
-            return charLength;
-        }
-
-        @Override
-        public int getCharEndIndex() {
-            return charIndex + charLength;
-        }
-
-        @Override
-        public String getIdentifier() {
-            return identifier;
-        }
-
-        @Override
-        public String getCode() {
-            return getSource().getCode(charIndex, charLength);
-        }
-
-        @Override
-        public String getShortDescription() {
-            return String.format("%s:%d", source.getShortName(), startLine);
-        }
-
-        @Override
-        public String toString() {
-            return getCode();
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + charIndex;
-            result = prime * result + charLength;
-            result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
-            result = prime * result + ((source == null) ? 0 : source.hashCode());
-            result = prime * result + startColumn;
-            result = prime * result + startLine;
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (!(obj instanceof DefaultSourceSection)) {
-                return false;
-            }
-            DefaultSourceSection other = (DefaultSourceSection) obj;
-            if (charIndex != other.charIndex) {
-                return false;
-            }
-            if (charLength != other.charLength) {
-                return false;
-            }
-            if (identifier == null) {
-                if (other.identifier != null) {
-                    return false;
-                }
-            } else if (!identifier.equals(other.identifier)) {
-                return false;
-            }
-            if (source == null) {
-                if (other.source != null) {
-                    return false;
-                }
-            } else if (!source.equals(other.source)) {
-                return false;
-            }
-            if (startColumn != other.startColumn) {
-                return false;
-            }
-            if (startLine != other.startLine) {
-                return false;
-            }
-            return true;
-        }
-    }
-
-    private static final class LineLocationImpl implements LineLocation {
-        private final Source source;
-        private final int line;
-
-        public LineLocationImpl(Source source, int line) {
-            assert source != null;
-            this.source = source;
-            this.line = line;
-        }
-
-        @Override
-        public Source getSource() {
-            return source;
-        }
-
-        @Override
-        public int getLineNumber() {
-            return line;
-        }
-
-        @Override
-        public String getShortDescription() {
-            return source.getShortName() + ":" + line;
-        }
-
-        @Override
-        public String toString() {
-            return "Line[" + getShortDescription() + "]";
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + line;
-            result = prime * result + source.getHashKey().hashCode();
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (!(obj instanceof LineLocationImpl)) {
-                return false;
-            }
-            LineLocationImpl other = (LineLocationImpl) obj;
-            if (line != other.line) {
-                return false;
-            }
-            return source.getHashKey().equals(other.source.getHashKey());
-        }
-
-    }
-
-    /**
-     * A utility for converting between coordinate systems in a string of text interspersed with
-     * newline characters. The coordinate systems are:
-     * <ul>
-     * <li>0-based character offset from the beginning of the text, where newline characters count
-     * as a single character and the first character in the text occupies position 0.</li>
-     * <li>1-based position in the 2D space of lines and columns, in which the first position in the
-     * text is at (1,1).</li>
-     * </ul>
-     * <p>
-     * This utility is based on positions occupied by characters, not text stream positions as in a
-     * text editor. The distinction shows up in editors where you can put the cursor just past the
-     * last character in a buffer; this is necessary, among other reasons, so that you can put the
-     * edit cursor in a new (empty) buffer. For the purposes of this utility, however, there are no
-     * character positions in an empty text string and there are no lines in an empty text string.
-     * <p>
-     * A newline character designates the end of a line and occupies a column position.
-     * <p>
-     * If the text ends with a character other than a newline, then the characters following the
-     * final newline character count as a line, even though not newline-terminated.
-     * <p>
-     * <strong>Limitations:</strong>
-     * <ul>
-     * <li>Does not handle multiple character encodings correctly.</li>
-     * <li>Treats tabs as occupying 1 column.</li>
-     * <li>Does not handle multiple-character line termination sequences correctly.</li>
-     * </ul>
-     */
-    private static final class TextMap {
-
-        // 0-based offsets of newline characters in the text, with sentinel
-        private final int[] nlOffsets;
-
-        // The number of characters in the text, including newlines (which count as 1).
-        private final int textLength;
-
-        // Is the final text character a newline?
-        final boolean finalNL;
-
-        public TextMap(int[] nlOffsets, int textLength, boolean finalNL) {
-            this.nlOffsets = nlOffsets;
-            this.textLength = textLength;
-            this.finalNL = finalNL;
-        }
-
-        /**
-         * Constructs map permitting translation between 0-based character offsets and 1-based
-         * lines/columns.
-         */
-        public static TextMap fromString(String text) {
-            final int textLength = text.length();
-            final ArrayList<Integer> lines = new ArrayList<>();
-            lines.add(0);
-            int offset = 0;
-
-            while (offset < text.length()) {
-                final int nlIndex = text.indexOf('\n', offset);
-                if (nlIndex >= 0) {
-                    offset = nlIndex + 1;
-                    lines.add(offset);
-                } else {
-                    break;
-                }
-            }
-            lines.add(Integer.MAX_VALUE);
-
-            final int[] nlOffsets = new int[lines.size()];
-            for (int line = 0; line < lines.size(); line++) {
-                nlOffsets[line] = lines.get(line);
-            }
-
-            final boolean finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]);
-
-            return new TextMap(nlOffsets, textLength, finalNL);
-        }
-
-        public static TextMap fromBytes(byte[] bytes, int byteIndex, int length, BytesDecoder bytesDecoder) {
-            final ArrayList<Integer> lines = new ArrayList<>();
-            lines.add(0);
-
-            bytesDecoder.decodeLines(bytes, byteIndex, length, new BytesDecoder.LineMarker() {
-
-                public void markLine(int index) {
-                    lines.add(index);
-                }
-            });
-
-            lines.add(Integer.MAX_VALUE);
-
-            final int[] nlOffsets = new int[lines.size()];
-            for (int line = 0; line < lines.size(); line++) {
-                nlOffsets[line] = lines.get(line);
-            }
-
-            final boolean finalNL = length > 0 && (length == nlOffsets[nlOffsets.length - 2]);
-
-            return new TextMap(nlOffsets, length, finalNL);
-        }
-
-        /**
-         * Converts 0-based character offset to 1-based number of the line containing the character.
-         *
-         * @throws IllegalArgumentException if the offset is outside the string.
-         */
-        public int offsetToLine(int offset) throws IllegalArgumentException {
-            if (offset < 0 || offset >= textLength) {
-                throw new IllegalArgumentException("offset out of bounds");
-            }
-            int line = 1;
-            while (offset >= nlOffsets[line]) {
-                line++;
-            }
-            return line;
-        }
-
-        /**
-         * Converts 0-based character offset to 1-based number of the column occupied by the
-         * character.
-         * <p>
-         * Tabs are not expanded; they occupy 1 column.
-         *
-         * @throws IllegalArgumentException if the offset is outside the string.
-         */
-        public int offsetToCol(int offset) throws IllegalArgumentException {
-            return 1 + offset - nlOffsets[offsetToLine(offset) - 1];
-        }
-
-        /**
-         * The number of characters in the mapped text.
-         */
-        public int length() {
-            return textLength;
-        }
-
-        /**
-         * The number of lines in the text; if characters appear after the final newline, then they
-         * also count as a line, even though not newline-terminated.
-         */
-        public int lineCount() {
-            if (textLength == 0) {
-                return 0;
-            }
-            return finalNL ? nlOffsets.length - 2 : nlOffsets.length - 1;
-        }
-
-        /**
-         * Converts 1-based line number to the 0-based offset of the line's first character; this
-         * would be the offset of a newline if the line is empty.
-         *
-         * @throws IllegalArgumentException if there is no such line in the text.
-         */
-        public int lineStartOffset(int line) throws IllegalArgumentException {
-            if (textLength == 0 || lineOutOfRange(line)) {
-                throw new IllegalArgumentException("line out of bounds");
-            }
-            return nlOffsets[line - 1];
-        }
-
-        /**
-         * Gets the number of characters in a line, identified by 1-based line number;
-         * <em>does not</em> include the final newline, if any.
-         *
-         * @throws IllegalArgumentException if there is no such line in the text.
-         */
-        public int lineLength(int line) throws IllegalArgumentException {
-            if (textLength == 0 || lineOutOfRange(line)) {
-                throw new IllegalArgumentException("line out of bounds");
-            }
-            if (line == nlOffsets.length - 1 && !finalNL) {
-                return textLength - nlOffsets[line - 1];
-            }
-            return (nlOffsets[line] - nlOffsets[line - 1]) - 1;
-
-        }
-
-        /**
-         * Is the line number out of range.
-         */
-        private boolean lineOutOfRange(int line) {
-            return line <= 0 || line >= nlOffsets.length || (line == nlOffsets.length - 1 && finalNL);
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * An observer of events related to {@link Source}s: creating and tagging.
- */
-public interface SourceListener {
-
-    /**
-     * Notifies that a new {@link Source} has just been created.
-     */
-    void sourceCreated(Source source);
-
-    /**
-     * Notifies that a {@link SourceTag} has been newly added to the set of tags associated with a
-     * {@link Source} via {@link Source#tagAs(SourceTag)}.
-     * <p>
-     * The {@linkplain SourceTag tags} at a {@link Source} are a <em>set</em>; this notification
-     * will only be delivered the first time a particular {@linkplain SourceTag tag} is added at a
-     * {@link Source}.
-     *
-     * @param source where a tag has been added
-     * @param tag the tag that has been newly added (subsequent additions of the tag are
-     *            unreported).
-     */
-    void sourceTaggedAs(Source source, SourceTag tag);
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * Description of contiguous section of text within a {@link Source} of program code; supports
- * multiple modes of access to the text and its location. A special {@linkplain NullSourceSection
- * null subtype} should be used for code that is not available from source, e.g language builtins.
- *
- * @see Source#createSection(String, int, int, int, int)
- * @see Source#createSection(String, int, int, int)
- * @see Source#createSection(String, int, int)
- * @see Source#createSection(String, int)
- * @see NullSourceSection
- */
-public interface SourceSection {
-
-    // TODO support alternate text representations/encodings
-
-    /**
-     * Representation of the source program that contains this section.
-     *
-     * @return the source object
-     */
-    Source getSource();
-
-    /**
-     * Returns 1-based line number of the first character in this section (inclusive).
-     *
-     * @return the starting line number
-     */
-    int getStartLine();
-
-    /**
-     * Gets a representation of the first line of the section, suitable for a hash key.
-     */
-    LineLocation getLineLocation();
-
-    /**
-     * Returns the 1-based column number of the first character in this section (inclusive).
-     *
-     * @return the starting column number
-     */
-    int getStartColumn();
-
-    /**
-     * Returns 1-based line number of the last character in this section (inclusive).
-     *
-     * @return the starting line number
-     */
-    int getEndLine();
-
-    /**
-     * Returns the 1-based column number of the last character in this section (inclusive).
-     *
-     * @return the starting column number
-     */
-    int getEndColumn();
-
-    /**
-     * Returns the 0-based index of the first character in this section.
-     *
-     * @return the starting character index
-     */
-    int getCharIndex();
-
-    /**
-     * Returns the length of this section in characters.
-     *
-     * @return the number of characters in the section
-     */
-    int getCharLength();
-
-    /**
-     * Returns the index of the text position immediately following the last character in the
-     * section.
-     *
-     * @return the end position of the section
-     */
-    int getCharEndIndex();
-
-    /**
-     * Returns terse text describing this source section, typically used for printing the section.
-     *
-     * @return the identifier of the section
-     */
-    String getIdentifier();
-
-    /**
-     * Returns text described by this section.
-     *
-     * @return the code as a String object
-     */
-    String getCode();
-
-    /**
-     * Returns a short description of the source section, using just the file name, rather than its
-     * full path.
-     *
-     * @return a short description of the source section
-     */
-    String getShortDescription();
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.source;
-
-/**
- * Categorical information (best implemented as enums} about particular sources of Guest Language
- * code that can be useful to configure behavior of both the language runtime and external tools.
- * These might include {@linkplain Source.Tags standard tags} noting, for example, whether the
- * source was read from a file and whether it should be considered library code.
- * <p>
- * The need for additional tags is likely to arise, in some cases because of issue specific to a
- * Guest Language, but also for help configuring the behavior of particular tools.
- *
- * @see Source
- * @see Source.Tags
- */
-public interface SourceTag {
-
-    /**
-     * Human-friendly name of a category of code sources, e.g. "file", or "library".
-     *
-     */
-    String name();
-
-    /**
-     * Criteria and example uses for the tag.
-     */
-    String getDescription();
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.unsafe;
-
-public interface UnsafeAccess {
-
-    /**
-     * Casts the given value to the value of the given type without any checks. The class must
-     * evaluate to a constant. The condition parameter gives a hint to the compiler under which
-     * circumstances this cast can be moved to an earlier location in the program.
-     *
-     * @param value the value that is known to have the specified type
-     * @param type the specified new type of the value
-     * @param condition the condition that makes this cast safe also at an earlier location of the
-     *            program
-     * @param nonNull whether value is known to never be null
-     * @return the value to be casted to the new type
-     */
-    <T> T uncheckedCast(Object value, Class<T> type, boolean condition, boolean nonNull);
-
-    /**
-     * Unsafe access to a boolean value within an object. The condition parameter gives a hint to
-     * the compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to a byte value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to a short value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    short getShort(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to an int value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    int getInt(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to a long value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    long getLong(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to a float value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to a double value within an object. The condition parameter gives a hint to the
-     * compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Unsafe access to an Object value within an object. The condition parameter gives a hint to
-     * the compiler under which circumstances this access can be moved to an earlier location in the
-     * program. The location identity gives a hint to the compiler for improved global value
-     * numbering.
-     *
-     * @param receiver the object that is accessed
-     * @param offset the offset at which to access the object in bytes
-     * @param condition the condition that makes this access safe also at an earlier location in the
-     *            program
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     * @return the accessed value
-     */
-    Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity);
-
-    /**
-     * Write a boolean value within an object. The location identity gives a hint to the compiler
-     * for improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity);
-
-    /**
-     * Write a byte value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putByte(Object receiver, long offset, byte value, Object locationIdentity);
-
-    /**
-     * Write a short value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putShort(Object receiver, long offset, short value, Object locationIdentity);
-
-    /**
-     * Write an int value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putInt(Object receiver, long offset, int value, Object locationIdentity);
-
-    /**
-     * Write a long value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putLong(Object receiver, long offset, long value, Object locationIdentity);
-
-    /**
-     * Write a float value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putFloat(Object receiver, long offset, float value, Object locationIdentity);
-
-    /**
-     * Write a double value within an object. The location identity gives a hint to the compiler for
-     * improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putDouble(Object receiver, long offset, double value, Object locationIdentity);
-
-    /**
-     * Write an Object value within an object. The location identity gives a hint to the compiler
-     * for improved global value numbering.
-     *
-     * @param receiver the object that is written to
-     * @param offset the offset at which to write to the object in bytes
-     * @param value the value to be written
-     * @param locationIdentity the location identity token that can be used for improved global
-     *            value numbering or null
-     */
-    void putObject(Object receiver, long offset, Object value, Object locationIdentity);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.unsafe;
-
-import sun.misc.*;
-
-public interface UnsafeAccessFactory {
-    UnsafeAccess createUnsafeAccess(Unsafe unsafe);
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An assumption that is always valid. Used as a placeholder where an assumption is needed but never
- * invalidated.
- */
-public final class AlwaysValidAssumption implements Assumption {
-
-    public static final AlwaysValidAssumption INSTANCE = new AlwaysValidAssumption();
-
-    private AlwaysValidAssumption() {
-    }
-
-    @Override
-    public void check() throws InvalidAssumptionException {
-    }
-
-    @Override
-    public void invalidate() {
-        throw new UnsupportedOperationException("Cannot invalidate this assumption - it is always valid");
-    }
-
-    @Override
-    public String getName() {
-        return getClass().getName();
-    }
-
-    @Override
-    public boolean isValid() {
-        return true;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A value that the compiler can assume is constant, but can be changed by invalidation.
- * <p>
- * Compiled code that uses the value will be invalidated each time the value changes, so you should
- * take care to only change values infrequently, or to monitor the number of times the value has
- * changed and at some point to replace the value with something more generic so that it does not
- * have to be changed and code does not have to keep being recompiled.
- */
-public class AssumedValue<T> {
-
-    private final String name;
-
-    @CompilationFinal private T value;
-    @CompilationFinal private Assumption assumption;
-
-    public AssumedValue(T initialValue) {
-        this(null, initialValue);
-    }
-
-    public AssumedValue(String name, T initialValue) {
-        this.name = name;
-        value = initialValue;
-        assumption = Truffle.getRuntime().createAssumption(name);
-    }
-
-    /**
-     * Get the current value, updating it if it has been {@link #set}. The compiler may be able to
-     * make this method return a constant value, but still accommodate mutation.
-     */
-    public T get() {
-        try {
-            assumption.check();
-        } catch (InvalidAssumptionException e) {
-            // No need to rewrite anything - just pick up the new values
-        }
-
-        return value;
-    }
-
-    /**
-     * Set a new value, which will be picked up the next time {@link #get} is called.
-     */
-    public void set(T newValue) {
-        CompilerDirectives.transferToInterpreter();
-
-        value = newValue;
-        final Assumption oldAssumption = assumption;
-        assumption = Truffle.getRuntime().createAssumption(name);
-        oldAssumption.invalidate();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * Utility class to speculate on conditions to be never true or to be never false. Condition
- * profiles are intended to be used as part of if conditions.
- *
- * @see ConditionProfile#createBinaryProfile()
- */
-public final class BinaryConditionProfile extends ConditionProfile {
-
-    @CompilationFinal private boolean wasTrue;
-    @CompilationFinal private boolean wasFalse;
-
-    BinaryConditionProfile() {
-        /* package protected constructor */
-    }
-
-    @Override
-    public boolean profile(boolean value) {
-        if (value) {
-            if (!wasTrue) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                wasTrue = true;
-            }
-            return true;
-        } else {
-            if (!wasFalse) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                wasFalse = true;
-            }
-            return false;
-        }
-    }
-
-    public boolean wasTrue() {
-        return wasTrue;
-    }
-
-    public boolean wasFalse() {
-        return wasFalse;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Utility class to speculate on branches to be never visited. If the {@link #enter()} method is
- * invoked first the optimized code is invalidated and the branch where {@link #enter()} is invoked
- * is enabled for compilation. Otherwise if the {@link #enter()} method was never invoked the branch
- * will not get compiled.
- *
- * All {@code BranchProfile} instances must be held in {@code final} fields for compiler
- * optimizations to take effect.
- */
-public final class BranchProfile extends NodeCloneable {
-
-    @CompilationFinal private boolean visited;
-
-    private BranchProfile() {
-    }
-
-    public void enter() {
-        if (!visited) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            visited = true;
-        }
-    }
-
-    public boolean isVisited() {
-        return visited;
-    }
-
-    public static BranchProfile create() {
-        return new BranchProfile();
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(%s)@%x", getClass().getSimpleName(), visited ? "visited" : "not-visited", hashCode());
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as
- * part of if conditions.
- *
- * Example usage:
- *
- * <pre>
- * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
- *
- * int value = ...;
- * if (zero.profile(value == 0)) {
- *   return 0;
- * } else {
- *   return value;
- * }
- *
- * </pre>
- *
- * All instances of {@code ConditionProfile} (and subclasses) must be held in {@code final} fields
- * for compiler optimizations to take effect.
- *
- * @see #createCountingProfile()
- * @see #createBinaryProfile()
- */
-public abstract class ConditionProfile extends NodeCloneable {
-    ConditionProfile() {
-    }
-
-    public abstract boolean profile(boolean value);
-
-    /**
-     * Returns a {@link ConditionProfile} that speculates on conditions to be never
-     * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
-     * method returns a condition profile that also counts the number of times the condition was
-     * true and false. This information is reported to the underlying optimization system using
-     * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
-     * intended to be used as part of if conditions.
-     *
-     * @see ConditionProfile
-     * @see #createBinaryProfile()
-     */
-    public static ConditionProfile createCountingProfile() {
-        return new CountingConditionProfile();
-    }
-
-    /**
-     * Returns a {@link ConditionProfile} that speculates on conditions to be never true or to be
-     * never false. Condition profiles are intended to be used as part of if conditions.
-     *
-     * @see ConditionProfile
-     * @see ConditionProfile#createCountingProfile()
-     */
-    public static ConditionProfile createBinaryProfile() {
-        return new BinaryConditionProfile();
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * Utility class to speculate on conditions to be never true or to be never false. Additionally to
- * {@link BinaryConditionProfile} this implementation of {@link ConditionProfile} also counts the
- * number of times the condition was true and false. This information is reported to the underlying
- * optimization system using {@link CompilerDirectives#injectBranchProbability(double, boolean)}.
- * Condition profiles are intended to be used as part of if conditions.
- *
- * @see ConditionProfile#createCountingProfile()
- */
-public final class CountingConditionProfile extends ConditionProfile {
-
-    @CompilationFinal private int trueCount;
-    @CompilationFinal private int falseCount;
-
-    CountingConditionProfile() {
-        /* package protected constructor */
-    }
-
-    @Override
-    public boolean profile(boolean value) {
-        if (value) {
-            if (trueCount == 0) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-            }
-            if (CompilerDirectives.inInterpreter()) {
-                trueCount++;
-            }
-        } else {
-            if (falseCount == 0) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-            }
-            if (CompilerDirectives.inInterpreter()) {
-                falseCount++;
-            }
-        }
-        return CompilerDirectives.injectBranchProbability((double) trueCount / (double) (trueCount + falseCount), value);
-    }
-
-    public int getTrueCount() {
-        return trueCount;
-    }
-
-    public int getFalseCount() {
-        return falseCount;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(trueCount=%s, falseCount=%s)@%x", getClass().getSimpleName(), trueCount, falseCount, hashCode());
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import java.util.concurrent.atomic.*;
-
-import com.oracle.truffle.api.*;
-
-/**
- * Holds an {@link Assumption}, and knows how to recreate it with the same properties on
- * invalidation. Used so that mutability is isolated in this class, and all other classes that need
- * an assumption that may be recreated can have a final reference to an object of this class. Note
- * that you should be careful that repeated invalidations do not cause a deoptimization loop in that
- * same way that you would with any other assumption.
- */
-public class CyclicAssumption {
-
-    private final String name;
-    private final AtomicReference<Assumption> assumption;
-
-    public CyclicAssumption(String name) {
-        this.name = name;
-        this.assumption = new AtomicReference<>(Truffle.getRuntime().createAssumption(name));
-    }
-
-    public void invalidate() {
-        Assumption newAssumption = Truffle.getRuntime().createAssumption(name);
-        Assumption oldAssumption = assumption.getAndSet(newAssumption);
-        oldAssumption.invalidate();
-    }
-
-    public Assumption getAssumption() {
-        return assumption.get();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * Represents a {@link ValueProfile} that speculates on the exact class of a value.
- */
-public final class ExactClassValueProfile extends ValueProfile {
-
-    @CompilationFinal protected Class<?> cachedClass;
-
-    ExactClassValueProfile() {
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T> T profile(T value) {
-        if (cachedClass != Object.class) {
-            if (cachedClass != null && cachedClass.isInstance(value)) {
-                return (T) cachedClass.cast(value);
-            } else {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (cachedClass == null && value != null) {
-                    cachedClass = value.getClass();
-                } else {
-                    cachedClass = Object.class;
-                }
-            }
-        }
-        return value;
-    }
-
-    public boolean isGeneric() {
-        return cachedClass == Object.class;
-    }
-
-    public boolean isUninitialized() {
-        return cachedClass == null;
-    }
-
-    public Class<?> getCachedClass() {
-        return cachedClass;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : cachedClass.getName()), hashCode());
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * Represents a {@link ValueProfile} that speculates on the object identity of a value.
- */
-public final class IdentityValueProfile extends ValueProfile {
-
-    private static final Object UNINITIALIZED = new Object();
-    private static final Object GENERIC = new Object();
-
-    @CompilationFinal protected Object cachedValue = UNINITIALIZED;
-
-    IdentityValueProfile() {
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T> T profile(T value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue == value) {
-                return (T) cachedValue;
-            } else {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                if (cachedValue == UNINITIALIZED) {
-                    cachedValue = value;
-                } else {
-                    cachedValue = GENERIC;
-                }
-            }
-        }
-        return value;
-    }
-
-    public boolean isGeneric() {
-        return getCachedValue() == GENERIC;
-    }
-
-    public boolean isUninitialized() {
-        return getCachedValue() == UNINITIALIZED;
-    }
-
-    public Object getCachedValue() {
-        return cachedValue;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : String.format("@%x", Objects.hash(cachedValue))), hashCode());
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import java.util.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Helper function that allows to dump the AST during creation to a JSON format.
- */
-public class JSONHelper {
-
-    private static StringBuilder AstJsonDumpBuilder = new StringBuilder();
-
-    public static void dumpNewChild(Node parentNode, Node childNode) {
-        if (AstJsonDumpBuilder != null) {
-            AstJsonDumpBuilder.append("{ \"action\": \"insertNode\", \"parentId\": \"" + getID(parentNode) + "\", \"newId\": \"" + getID(childNode) + "\" },\n");
-        }
-    }
-
-    public static void dumpReplaceChild(Node oldNode, Node newNode, CharSequence reason) {
-        if (AstJsonDumpBuilder != null) {
-            AstJsonDumpBuilder.append("{ \"action\": \"replaceNode\", \"oldId\": \"" + getID(oldNode) + "\", \"newId\": \"" + getID(newNode) + "\", \"reason\": " + quote(reason) + " },\n");
-        }
-    }
-
-    public static void dumpNewNode(Node newNode) {
-        if (AstJsonDumpBuilder != null) {
-            AstJsonDumpBuilder.append("{ \"action\": \"createNode\", \"newId\": \"" + getID(newNode) + "\", \"type\": \"" + getType(newNode) + "\", \"description\": \"" + newNode.getDescription() +
-                            "\", \"language\": \"" + newNode.getLanguage() + "\"" + getSourceSectionInfo(newNode) + " },\n");
-        }
-    }
-
-    private static String getSourceSectionInfo(Node newNode) {
-        SourceSection sourceSection = newNode.getSourceSection();
-        if (sourceSection != null) {
-            return ", \"identifier\": \"" + sourceSection.getIdentifier() + "\" ";
-        } else {
-            return "";
-        }
-    }
-
-    public static String getResult() {
-        return AstJsonDumpBuilder.toString();
-    }
-
-    private static String getID(Node newChild) {
-        return String.valueOf(newChild.hashCode());
-    }
-
-    private static String getType(Node node) {
-        return node.getClass().getSimpleName();
-    }
-
-    private static String quote(CharSequence value) {
-        StringBuilder builder = new StringBuilder(value.length() + 2);
-        builder.append('"');
-        for (int i = 0; i < value.length(); i++) {
-            char c = value.charAt(i);
-            switch (c) {
-                case '"':
-                    builder.append("\\\"");
-                    break;
-                case '\\':
-                    builder.append("\\\\");
-                    break;
-                case '\b':
-                    builder.append("\\b");
-                    break;
-                case '\f':
-                    builder.append("\\f");
-                    break;
-                case '\n':
-                    builder.append("\\n");
-                    break;
-                case '\r':
-                    builder.append("\\r");
-                    break;
-                case '\t':
-                    builder.append("\\t");
-                    break;
-                default: {
-                    if (c < ' ') {
-                        builder.append("\\u00");
-                        builder.append(Character.forDigit((c >> 4) & 0xF, 16));
-                        builder.append(Character.forDigit(c & 0xF, 16));
-                    } else {
-                        builder.append(c);
-                    }
-                }
-            }
-        }
-        builder.append('"');
-        return builder.toString();
-    }
-
-    public static void restart() {
-        AstJsonDumpBuilder = new StringBuilder();
-    }
-
-    public static JSONObjectBuilder object() {
-        return new JSONObjectBuilder();
-    }
-
-    public static JSONArrayBuilder array() {
-        return new JSONArrayBuilder();
-    }
-
-    public abstract static class JSONStringBuilder {
-        @Override
-        public final String toString() {
-            StringBuilder sb = new StringBuilder();
-            appendTo(sb);
-            return sb.toString();
-        }
-
-        protected abstract void appendTo(StringBuilder sb);
-
-        protected static void appendValue(StringBuilder sb, Object value) {
-            if (value instanceof JSONStringBuilder) {
-                ((JSONStringBuilder) value).appendTo(sb);
-            } else if (value instanceof Integer || value instanceof Boolean || value == null) {
-                sb.append(value);
-            } else {
-                sb.append(quote(String.valueOf(value)));
-            }
-        }
-    }
-
-    public static final class JSONObjectBuilder extends JSONStringBuilder {
-        private final Map<String, Object> contents = new LinkedHashMap<>();
-
-        private JSONObjectBuilder() {
-        }
-
-        public JSONObjectBuilder add(String key, String value) {
-            contents.put(key, value);
-            return this;
-        }
-
-        public JSONObjectBuilder add(String key, Number value) {
-            contents.put(key, value);
-            return this;
-        }
-
-        public JSONObjectBuilder add(String key, Boolean value) {
-            contents.put(key, value);
-            return this;
-        }
-
-        public JSONObjectBuilder add(String key, JSONStringBuilder value) {
-            contents.put(key, value);
-            return this;
-        }
-
-        @Override
-        protected void appendTo(StringBuilder sb) {
-            sb.append("{");
-            boolean comma = false;
-            for (Map.Entry<String, Object> entry : contents.entrySet()) {
-                if (comma) {
-                    sb.append(", ");
-                }
-                sb.append(quote(entry.getKey()));
-                sb.append(": ");
-                appendValue(sb, entry.getValue());
-                comma = true;
-            }
-            sb.append("}");
-        }
-    }
-
-    public static final class JSONArrayBuilder extends JSONStringBuilder {
-        private final List<Object> contents = new ArrayList<>();
-
-        private JSONArrayBuilder() {
-        }
-
-        public JSONArrayBuilder add(String value) {
-            contents.add(value);
-            return this;
-        }
-
-        public JSONArrayBuilder add(Number value) {
-            contents.add(value);
-            return this;
-        }
-
-        public JSONArrayBuilder add(Boolean value) {
-            contents.add(value);
-            return this;
-        }
-
-        public JSONArrayBuilder add(JSONStringBuilder value) {
-            contents.add(value);
-            return this;
-        }
-
-        @Override
-        protected void appendTo(StringBuilder sb) {
-            sb.append("[");
-            boolean comma = false;
-            for (Object value : contents) {
-                if (comma) {
-                    sb.append(", ");
-                }
-                appendValue(sb, value);
-                comma = true;
-            }
-            sb.append("]");
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/NeverValidAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An assumption that is never valid. Used as a placeholder where an assumption is needed that
- * should be invalid from the start.
- */
-public final class NeverValidAssumption implements Assumption {
-
-    public static final NeverValidAssumption INSTANCE = new NeverValidAssumption();
-
-    private NeverValidAssumption() {
-    }
-
-    @Override
-    public void check() throws InvalidAssumptionException {
-        throw new InvalidAssumptionException();
-    }
-
-    @Override
-    public void invalidate() {
-    }
-
-    @Override
-    public String getName() {
-        return getClass().getName();
-    }
-
-    @Override
-    public boolean isValid() {
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-
-/**
- * Represents a {@link ValueProfile} that speculates on the primitive equality or object identity of
- * values.
- * <p>
- * Note that for {@code float} and {@code double} values we compare primitive equality via
- * {@link Float#floatToRawIntBits} and {@link Double#doubleToRawLongBits}, so that for example
- * {@code -0.0} is not considered the same as {@code 0.0}, even though primitive equality would
- * normally say that it was.
- */
-public class PrimitiveValueProfile extends ValueProfile {
-
-    private static final Object UNINITIALIZED = new Object();
-    private static final Object GENERIC = new Object();
-
-    @CompilationFinal private Object cachedValue = UNINITIALIZED;
-
-    PrimitiveValueProfile() {
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Object profile(Object value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Byte) {
-                if (value instanceof Byte && (byte) snapshot == (byte) value) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Short) {
-                if (value instanceof Short && (short) snapshot == (short) value) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Integer) {
-                if (value instanceof Integer && (int) snapshot == (int) value) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Long) {
-                if (value instanceof Long && (long) snapshot == (long) value) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Float) {
-                if (value instanceof Float && exactCompare((float) snapshot, (float) value)) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Double) {
-                if (value instanceof Double && exactCompare((double) snapshot, (double) value)) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Boolean) {
-                if (value instanceof Boolean && (boolean) snapshot == (boolean) value) {
-                    return snapshot;
-                }
-            } else if (snapshot instanceof Character) {
-                if (value instanceof Character && (char) snapshot == (char) value) {
-                    return snapshot;
-                }
-            } else if (snapshot == value) {
-                return snapshot;
-            }
-            cacheMiss(value);
-        }
-        return value;
-    }
-
-    public byte profile(byte value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Byte && (byte) snapshot == value) {
-                return (byte) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public short profile(short value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Short && (short) snapshot == value) {
-                return (short) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public int profile(int value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Integer && (int) snapshot == value) {
-                return (int) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public long profile(long value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Long && (long) snapshot == value) {
-                return (long) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public float profile(float value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Float && exactCompare((float) snapshot, value)) {
-                return (float) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public double profile(double value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Double && exactCompare((double) snapshot, value)) {
-                return (double) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public boolean profile(boolean value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Boolean && (boolean) snapshot == value) {
-                return (boolean) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public char profile(char value) {
-        Object snapshot = this.cachedValue;
-        if (snapshot != GENERIC) {
-            if (snapshot instanceof Character && (char) snapshot == value) {
-                return (char) snapshot;
-            } else {
-                cacheMiss(value);
-            }
-        }
-        return value;
-    }
-
-    public boolean isGeneric() {
-        return cachedValue == GENERIC;
-    }
-
-    public boolean isUninitialized() {
-        return cachedValue == UNINITIALIZED;
-    }
-
-    public Object getCachedValue() {
-        return cachedValue;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s(%s)@%x", getClass().getSimpleName(), formatValue(), hashCode());
-    }
-
-    private void cacheMiss(Object value) {
-        // TODO should we try to handle this more atomically?
-        CompilerDirectives.transferToInterpreterAndInvalidate();
-        if (cachedValue == UNINITIALIZED) {
-            cachedValue = value;
-        } else {
-            cachedValue = GENERIC;
-        }
-    }
-
-    public static boolean exactCompare(float a, float b) {
-        /*
-         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
-         * differentiate.
-         */
-        return Float.floatToRawIntBits(a) == Float.floatToRawIntBits(b);
-    }
-
-    public static boolean exactCompare(double a, double b) {
-        /*
-         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
-         * differentiate.
-         */
-        return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
-    }
-
-    private String formatValue() {
-        Object snapshot = this.cachedValue;
-        if (snapshot == null) {
-            return "null";
-        } else if (snapshot == UNINITIALIZED) {
-            return "uninitialized";
-        } else if (snapshot == GENERIC) {
-            return "generic";
-        } else if (snapshot instanceof Byte || snapshot instanceof Short || snapshot instanceof Integer || snapshot instanceof Long || snapshot instanceof Float || snapshot instanceof Double ||
-                        snapshot instanceof Boolean || snapshot instanceof Character) {
-            return String.format("%s=%s", snapshot.getClass().getSimpleName(), snapshot);
-        } else {
-            return String.format("%s@%x", snapshot.getClass().getSimpleName(), Objects.hash(snapshot));
-        }
-    }
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * An assumption that combines two other assumptions. A check on this assumption checks both of the
- * child assumptions.
- */
-public class UnionAssumption implements Assumption {
-
-    private final String name;
-    private final Assumption first;
-    private final Assumption second;
-
-    public UnionAssumption(String name, Assumption first, Assumption second) {
-        this.name = name;
-        this.first = first;
-        this.second = second;
-    }
-
-    public UnionAssumption(Assumption first, Assumption second) {
-        this(null, first, second);
-    }
-
-    @Override
-    public void check() throws InvalidAssumptionException {
-        first.check();
-        second.check();
-    }
-
-    @Override
-    public void invalidate() {
-        first.invalidate();
-        second.invalidate();
-    }
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public boolean isValid() {
-        return first.isValid() && second.isValid();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.utilities;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Utility class to speculate on certain properties of values.
- *
- * Example usage:
- *
- * <pre>
- * private final ValueProfile classProfile = ValueProfile.createClassProfile();
- *
- * return classProfile.profile(value);
- * </pre>
- *
- * All instances of {@code ValueProfile} (and subclasses) must be held in {@code final} fields for
- * compiler optimizations to take effect.
- *
- * @see #createPrimitiveProfile()
- * @see #createIdentityProfile()
- * @see #createClassProfile()
- */
-public abstract class ValueProfile extends NodeCloneable {
-
-    public abstract <T> T profile(T value);
-
-    /**
-     * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or object
-     * identity of a value.
-     */
-    public static PrimitiveValueProfile createPrimitiveProfile() {
-        return new PrimitiveValueProfile();
-    }
-
-    /**
-     * Returns a {@link ValueProfile} that speculates on the exact class of a value.
-     */
-    public static ValueProfile createClassProfile() {
-        return new ExactClassValueProfile();
-    }
-
-    /**
-     * Returns a {@link ValueProfile} that speculates on the object identity of a value.
-     */
-    public static ValueProfile createIdentityProfile() {
-        return new IdentityValueProfile();
-    }
-
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,565 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.api.vm;
-
-import java.io.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.nio.file.*;
-import java.util.*;
-import java.util.logging.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.TruffleLanguage.Env;
-import com.oracle.truffle.api.TruffleLanguage.Registration;
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.impl.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Virtual machine for Truffle based languages. Use {@link #newVM()} to create new isolated virtual
- * machine ready for execution of various languages. All the languages in a single virtual machine
- * see each other exported global symbols and can cooperate. Use {@link #newVM()} multiple times to
- * create different, isolated virtual machines completely separated from each other.
- * <p>
- * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly
- * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}.
- * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type
- * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets
- * initialized, it remains so, until the virtual machine isn't garbage collected.
- * <p>
- * The <code>TruffleVM</code> is single-threaded and tries to enforce that. It records the thread it
- * has been {@link Builder#build() created} by and checks that all subsequent calls are coming from
- * the same thread.
- */
-public final class TruffleVM {
-    private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName());
-    private static final SPIAccessor SPI = new SPIAccessor();
-    private final Thread initThread;
-    private final Map<String, Language> langs;
-    private final Reader in;
-    private final Writer err;
-    private final Writer out;
-
-    /**
-     * Private & temporary only constructor.
-     */
-    private TruffleVM() {
-        this.initThread = null;
-        this.in = null;
-        this.err = null;
-        this.out = null;
-        this.langs = null;
-    }
-
-    /**
-     * Real constructor used from the builder.
-     *
-     * @param out stdout
-     * @param err stderr
-     * @param in stdin
-     */
-    private TruffleVM(Writer out, Writer err, Reader in) {
-        this.out = out;
-        this.err = err;
-        this.in = in;
-        this.initThread = Thread.currentThread();
-        this.langs = new HashMap<>();
-        Enumeration<URL> en;
-        try {
-            en = loader().getResources("META-INF/truffle/language");
-        } catch (IOException ex) {
-            throw new IllegalStateException("Cannot read list of Truffle languages", ex);
-        }
-        while (en.hasMoreElements()) {
-            URL u = en.nextElement();
-            Properties p;
-            try {
-                p = new Properties();
-                try (InputStream is = u.openStream()) {
-                    p.load(is);
-                }
-            } catch (IOException ex) {
-                LOG.log(Level.CONFIG, "Cannot process " + u + " as language definition", ex);
-                continue;
-            }
-            for (int cnt = 1;; cnt++) {
-                String prefix = "language" + cnt + ".";
-                if (p.getProperty(prefix + "name") == null) {
-                    break;
-                }
-                Language l = new Language(prefix, p);
-                for (String mimeType : l.getMimeTypes()) {
-                    langs.put(mimeType, l);
-                }
-            }
-        }
-    }
-
-    static ClassLoader loader() {
-        ClassLoader l = TruffleVM.class.getClassLoader();
-        if (l == null) {
-            l = ClassLoader.getSystemClassLoader();
-        }
-        return l;
-    }
-
-    /**
-     * Creation of new Truffle virtual machine. Use the {@link Builder} methods to configure your
-     * virtual machine and then create one using {@link Builder#build()}:
-     *
-     * <pre>
-     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
-     *     .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
-     *     .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
-     *     .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
-     *     .{@link Builder#build() build()};
-     * </pre>
-     *
-     * It searches for {@link Registration languages registered} in the system class loader and
-     * makes them available for later evaluation via
-     * {@link #eval(java.lang.String, java.lang.String)} methods.
-     *
-     * @return new, isolated virtual machine with pre-registered languages
-     */
-    public static TruffleVM.Builder newVM() {
-        // making Builder non-static inner class is a
-        // nasty trick to avoid the Builder class to appear
-        // in Javadoc next to TruffleVM class
-        TruffleVM vm = new TruffleVM();
-        return vm.new Builder();
-    }
-
-    /**
-     * Builder for a new {@link TruffleVM}. Call various configuration methods in a chain and at the
-     * end create new {@link TruffleVM virtual machine}:
-     *
-     * <pre>
-     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
-     *     .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
-     *     .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
-     *     .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
-     *     .{@link Builder#build() build()};
-     * </pre>
-     */
-    public final class Builder {
-        private Writer out;
-        private Writer err;
-        private Reader in;
-
-        Builder() {
-        }
-
-        /**
-         * Changes the defaut output for languages running in <em>to be created</em>
-         * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
-         *
-         * @param w the writer to use as output
-         * @return instance of this builder
-         */
-        public Builder stdOut(Writer w) {
-            out = w;
-            return this;
-        }
-
-        /**
-         * Changes the error output for languages running in <em>to be created</em>
-         * {@link TruffleVM virtual machine}. The default is to use {@link System#err}.
-         *
-         * @param w the writer to use as output
-         * @return instance of this builder
-         */
-        public Builder stdErr(Writer w) {
-            err = w;
-            return this;
-        }
-
-        /**
-         * Changes the default input for languages running in <em>to be created</em>
-         * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
-         *
-         * @param r the reader to use as input
-         * @return instance of this builder
-         */
-        public Builder stdIn(Reader r) {
-            in = r;
-            return this;
-        }
-
-        /**
-         * Creates the {@link TruffleVM Truffle virtual machine}. The configuration is taken from
-         * values passed into configuration methods in this class.
-         *
-         * @return new, isolated virtual machine with pre-registered languages
-         */
-        public TruffleVM build() {
-            if (out == null) {
-                out = new OutputStreamWriter(System.out);
-            }
-            if (err == null) {
-                err = new OutputStreamWriter(System.err);
-            }
-            if (in == null) {
-                in = new InputStreamReader(System.in);
-            }
-            return new TruffleVM(out, err, in);
-        }
-    }
-
-    /**
-     * Descriptions of languages supported in this Truffle virtual machine.
-     *
-     * @return an immutable map with keys being MIME types and values the {@link Language
-     *         descriptions} of associated languages
-     */
-    public Map<String, Language> getLanguages() {
-        return Collections.unmodifiableMap(langs);
-    }
-
-    /**
-     * Evaluates file located on a given URL. Is equivalent to loading the content of a file and
-     * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess
-     * based on the file's extension and/or content.
-     *
-     * @param location the location of a file to execute
-     * @return result of a processing the file, possibly <code>null</code>
-     * @throws IOException exception to signal I/O problems or problems with processing the file's
-     *             content
-     */
-    public Object eval(URI location) throws IOException {
-        checkThread();
-        Source s;
-        String mimeType;
-        if (location.getScheme().equals("file")) {
-            File file = new File(location);
-            s = Source.fromFileName(file.getPath(), true);
-            if (file.getName().endsWith(".c")) {
-                mimeType = "text/x-c";
-            } else if (file.getName().endsWith(".sl")) {
-                mimeType = "application/x-sl";
-            } else {
-                mimeType = Files.probeContentType(file.toPath());
-            }
-        } else {
-            URL url = location.toURL();
-            s = Source.fromURL(url, location.toString());
-            URLConnection conn = url.openConnection();
-            mimeType = conn.getContentType();
-        }
-        TruffleLanguage l = getTruffleLang(mimeType);
-        if (l == null) {
-            throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet());
-        }
-        return SPI.eval(l, s);
-    }
-
-    /**
-     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
-     * {@link IOException} if there is none). And passes the specified code to it for execution.
-     *
-     * @param mimeType MIME type of the code snippet - chooses the right language
-     * @param reader the source of code snippet to execute
-     * @return result of an execution, possibly <code>null</code>
-     * @throws IOException thrown to signal errors while processing the code
-     */
-    public Object eval(String mimeType, Reader reader) throws IOException {
-        checkThread();
-        TruffleLanguage l = getTruffleLang(mimeType);
-        if (l == null) {
-            throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
-        }
-        return SPI.eval(l, Source.fromReader(reader, mimeType));
-    }
-
-    /**
-     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
-     * {@link IOException} if there is none). And passes the specified code to it for execution.
-     *
-     * @param mimeType MIME type of the code snippet - chooses the right language
-     * @param code the code snippet to execute
-     * @return result of an execution, possibly <code>null</code>
-     * @throws IOException thrown to signal errors while processing the code
-     */
-    public Object eval(String mimeType, String code) throws IOException {
-        checkThread();
-        TruffleLanguage l = getTruffleLang(mimeType);
-        if (l == null) {
-            throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
-        }
-        return SPI.eval(l, Source.fromText(code, mimeType));
-    }
-
-    /**
-     * Looks global symbol provided by one of initialized languages up. First of all execute your
-     * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look
-     * expected symbol up using this method.
-     * <p>
-     * The names of the symbols are language dependent, but for example the Java language bindings
-     * follow the specification for method references:
-     * <ul>
-     * <li>"java.lang.Exception::new" is a reference to constructor of {@link Exception}
-     * <li>"java.lang.Integer::valueOf" is a reference to static method in {@link Integer} class
-     * </ul>
-     * Once an symbol is obtained, it remembers values for fast access and is ready for being
-     * invoked.
-     *
-     * @param globalName the name of the symbol to find
-     * @return found symbol or <code>null</code> if it has not been found
-     */
-    public Symbol findGlobalSymbol(String globalName) {
-        checkThread();
-        Object obj = null;
-        Object global = null;
-        for (Language dl : langs.values()) {
-            TruffleLanguage l = dl.getImpl();
-            obj = SPI.findExportedSymbol(l, globalName, true);
-            if (obj != null) {
-                global = SPI.languageGlobal(l);
-                break;
-            }
-        }
-        if (obj == null) {
-            for (Language dl : langs.values()) {
-                TruffleLanguage l = dl.getImpl();
-                obj = SPI.findExportedSymbol(l, globalName, false);
-                if (obj != null) {
-                    global = SPI.languageGlobal(l);
-                    break;
-                }
-            }
-        }
-        return obj == null ? null : new Symbol(obj, global);
-    }
-
-    private void checkThread() {
-        if (initThread != Thread.currentThread()) {
-            throw new IllegalStateException("TruffleVM created on " + initThread.getName() + " but used on " + Thread.currentThread().getName());
-        }
-    }
-
-    private TruffleLanguage getTruffleLang(String mimeType) {
-        checkThread();
-        Language l = langs.get(mimeType);
-        return l == null ? null : l.getImpl();
-    }
-
-    /**
-     * Represents {@link TruffleVM#findGlobalSymbol(java.lang.String) global symbol} provided by one
-     * of the initialized languages in {@link TruffleVM Truffle virtual machine}.
-     */
-    public class Symbol {
-        private final Object obj;
-        private final Object global;
-
-        Symbol(Object obj, Object global) {
-            this.obj = obj;
-            this.global = global;
-        }
-
-        /**
-         * Invokes the symbol. If the symbol represents a function, then it should be invoked with
-         * provided arguments. If the symbol represents a field, then first argument (if provided)
-         * should set the value to the field; the return value should be the actual value of the
-         * field when the <code>invoke</code> method returns.
-         *
-         * @param thiz this/self in language that support such concept; use <code>null</code> to let
-         *            the language use default this/self or ignore the value
-         * @param args arguments to pass when invoking the symbol
-         * @return the value returned by invoking the symbol
-         * @throws IOException signals problem during execution
-         */
-        public Object invoke(Object thiz, Object... args) throws IOException {
-            List<Object> arr = new ArrayList<>();
-            if (thiz == null) {
-                if (global != null) {
-                    arr.add(global);
-                }
-            } else {
-                arr.add(thiz);
-            }
-            arr.addAll(Arrays.asList(args));
-            return SPI.invoke(obj, arr.toArray());
-        }
-    }
-
-    /**
-     * Description of a language registered in {@link TruffleVM Truffle virtual machine}. Languages
-     * are registered by {@link Registration} annotation which stores necessary information into a
-     * descriptor inside of the language's JAR file. When a new {@link TruffleVM} is created, it
-     * reads all available descriptors and creates {@link Language} objects to represent them. One
-     * can obtain a {@link #getName() name} or list of supported {@link #getMimeTypes() MIME types}
-     * for each language. The actual language implementation is not initialized until
-     * {@link TruffleVM#eval(java.lang.String, java.lang.String) a code is evaluated} in it.
-     */
-    public final class Language {
-        private final Properties props;
-        private TruffleLanguage impl;
-        private final String prefix;
-        private String shortName;
-
-        Language(String prefix, Properties props) {
-            this.prefix = prefix;
-            this.props = props;
-        }
-
-        /**
-         * MIME types recognized by the language.
-         *
-         * @return returns immutable set of recognized MIME types
-         */
-        public Set<String> getMimeTypes() {
-            TreeSet<String> ts = new TreeSet<>();
-            for (int i = 0;; i++) {
-                String mt = props.getProperty(prefix + "mimeType." + i);
-                if (mt == null) {
-                    break;
-                }
-                ts.add(mt);
-            }
-            return Collections.unmodifiableSet(ts);
-        }
-
-        /**
-         * Human readable name of the language. Think of C, Ruby, JS, etc.
-         *
-         * @return string giving the language a name
-         */
-        public String getName() {
-            return props.getProperty(prefix + "name");
-        }
-
-        /**
-         * Name of the language version.
-         *
-         * @return string specifying the language version
-         */
-        public String getVersion() {
-            return props.getProperty(prefix + "version");
-        }
-
-        /**
-         * Human readable string that identifies the language and version.
-         *
-         * @return string describing the specific language version
-         */
-        public String getShortName() {
-            if (shortName == null) {
-                shortName = getName() + "(" + getVersion() + ")";
-            }
-            return shortName;
-        }
-
-        public ToolSupportProvider getToolSupport() {
-            return SPI.getToolSupport(getImpl());
-        }
-
-        public DebugSupportProvider getDebugSupport() {
-            return SPI.getDebugSupport(getImpl());
-        }
-
-        TruffleLanguage getImpl() {
-            if (impl == null) {
-                String n = props.getProperty(prefix + "className");
-                try {
-                    Class<?> langClazz = Class.forName(n, true, loader());
-                    Constructor<?> constructor = langClazz.getConstructor(Env.class);
-                    impl = SPI.attachEnv(TruffleVM.this, constructor, out, err, in);
-                } catch (Exception ex) {
-                    throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + n, ex);
-                }
-            }
-            return impl;
-        }
-
-        @Override
-        public String toString() {
-            return "[" + getShortName() + " for " + getMimeTypes() + "]";
-        }
-    } // end of Language
-
-    private static class SPIAccessor extends Accessor {
-        @Override
-        public Object importSymbol(TruffleVM vm, TruffleLanguage ownLang, String globalName) {
-            Set<Language> uniqueLang = new LinkedHashSet<>(vm.langs.values());
-            for (Language dl : uniqueLang) {
-                TruffleLanguage l = dl.getImpl();
-                if (l == ownLang) {
-                    continue;
-                }
-                Object obj = SPI.findExportedSymbol(l, globalName, true);
-                if (obj != null) {
-                    return obj;
-                }
-            }
-            for (Language dl : uniqueLang) {
-                TruffleLanguage l = dl.getImpl();
-                if (l == ownLang) {
-                    continue;
-                }
-                Object obj = SPI.findExportedSymbol(l, globalName, false);
-                if (obj != null) {
-                    return obj;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
-            return super.attachEnv(vm, langClazz, stdOut, stdErr, stdIn);
-        }
-
-        @Override
-        public Object eval(TruffleLanguage l, Source s) throws IOException {
-            return super.eval(l, s);
-        }
-
-        @Override
-        public Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
-            return super.findExportedSymbol(l, globalName, onlyExplicit);
-        }
-
-        @Override
-        public Object languageGlobal(TruffleLanguage l) {
-            return super.languageGlobal(l);
-        }
-
-        @Override
-        public Object invoke(Object obj, Object[] args) throws IOException {
-            return super.invoke(obj, args);
-        }
-
-        @Override
-        public ToolSupportProvider getToolSupport(TruffleLanguage l) {
-            return super.getToolSupport(l);
-        }
-
-        @Override
-        public DebugSupportProvider getDebugSupport(TruffleLanguage l) {
-            return super.getDebugSupport(l);
-        }
-    } // end of SPIAccessor
-}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/package.html	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<html>
-    <head>
-        <title>Truffle Virtual Machine</title>
-        <meta charset="UTF-8">
-        <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    </head>
-    <body>
-        <div>Central place to control <a href="TruffleVM.html">Truffle Virtual Machine</a> and
-        all languages hosted in it.</div>
-    </body>
-</html>
--- a/graal/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,212 +0,0 @@
-<?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: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <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"/>
-    <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="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="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <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">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </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"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="FileTabCharacter">
-    <property name="severity" value="error"/>
-    <property name="fileExtensions" value="java"/>
-  </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="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 name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-    <property name="checkFormat" value=".*Header"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
-    <property name="checkFormat" value="LineLength"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: start generated"/>
-    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength"/>
-  </module>
-</module>
--- a/graal/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-com.oracle.truffle.dsl.processor.TruffleProcessor
-com.oracle.truffle.dsl.processor.verify.VerifyTruffleProcessor
-com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.generator.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.java.transform.*;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.parser.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-class AnnotationProcessor<M extends Template> {
-
-    private final AbstractParser<M> parser;
-    private final CodeTypeElementFactory<M> factory;
-
-    private final Set<String> processedElements = new HashSet<>();
-
-    public AnnotationProcessor(AbstractParser<M> parser, CodeTypeElementFactory<M> factory) {
-        this.parser = parser;
-        this.factory = factory;
-    }
-
-    public AbstractParser<M> getParser() {
-        return parser;
-    }
-
-    @SuppressWarnings({"unchecked"})
-    public void process(Element element, boolean callback) {
-        // since it is not guaranteed to be called only once by the compiler
-        // we check for already processed elements to avoid errors when writing files.
-        if (!callback && element instanceof TypeElement) {
-            String qualifiedName = ElementUtils.getQualifiedName((TypeElement) element);
-            if (processedElements.contains(qualifiedName)) {
-                return;
-            }
-            processedElements.add(qualifiedName);
-        }
-
-        ProcessorContext context = ProcessorContext.getInstance();
-        TypeElement type = (TypeElement) element;
-
-        M model = (M) context.getTemplate(type.asType(), false);
-        boolean firstRun = !context.containsTemplate(type);
-
-        if (firstRun || !callback) {
-            context.registerTemplate(type, null);
-            model = parser.parse(element);
-            context.registerTemplate(type, model);
-
-            if (model != null) {
-                CodeTypeElement unit;
-                try {
-                    unit = factory.create(ProcessorContext.getInstance(), model);
-                } catch (Throwable e) {
-                    throw new RuntimeException(String.format("Failed to write code for %s. Parserdump:%s.", ElementUtils.getQualifiedName(type), ""), e);
-                }
-                if (unit == null) {
-                    return;
-                }
-                unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
-                unit.setGeneratorElement(model.getTemplateType());
-
-                DeclaredType overrideType = (DeclaredType) context.getType(Override.class);
-                DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class);
-                unit.accept(new GenerateOverrideVisitor(overrideType), null);
-                unit.accept(new FixWarningsVisitor(context.getEnvironment(), unusedType, overrideType), null);
-
-                if (!callback) {
-                    unit.accept(new CodeWriter(context.getEnvironment(), element), null);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.io.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.*;
-
-import com.oracle.truffle.dsl.processor.java.compiler.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.java.transform.*;
-
-public final class CodeWriter extends AbstractCodeWriter {
-
-    private final Element originalElement;
-    private final ProcessingEnvironment env;
-
-    public CodeWriter(ProcessingEnvironment env, Element originalElement) {
-        this.env = env;
-        this.originalElement = originalElement;
-    }
-
-    @Override
-    protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-        JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement);
-        return new BufferedWriter(jfo.openWriter());
-    }
-
-    @Override
-    protected void writeHeader() {
-        if (env == null) {
-            return;
-        }
-        String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement);
-        if (comment != null) {
-            writeLn(comment);
-        }
-        writeLn("// CheckStyle: start generated");
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-public class CompileErrorException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public CompileErrorException(String message) {
-        super(message);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ExpectError.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.*;
-
-public class ExpectError {
-
-    public static void assertNoErrorExpected(ProcessingEnvironment processingEnv, Element element) {
-        TypeElement eee = processingEnv.getElementUtils().getTypeElement(TruffleTypes.EXPECT_ERROR_CLASS_NAME);
-        if (eee != null) {
-            for (AnnotationMirror am : element.getAnnotationMirrors()) {
-                if (am.getAnnotationType().asElement().equals(eee)) {
-                    processingEnv.getMessager().printMessage(Kind.ERROR, "Expected an error, but none found!", element);
-                }
-            }
-        }
-    }
-
-    public static boolean isExpectedError(ProcessingEnvironment processingEnv, Element element, String message) {
-        TypeElement eee = processingEnv.getElementUtils().getTypeElement(TruffleTypes.EXPECT_ERROR_CLASS_NAME);
-        if (eee != null) {
-            for (AnnotationMirror am : element.getAnnotationMirrors()) {
-                if (am.getAnnotationType().asElement().equals(eee)) {
-                    Map<? extends ExecutableElement, ? extends AnnotationValue> vals = am.getElementValues();
-                    if (vals.size() == 1) {
-                        AnnotationValue av = vals.values().iterator().next();
-                        if (av.getValue() instanceof List) {
-                            List<?> arr = (List<?>) av.getValue();
-                            for (Object o : arr) {
-                                if (o instanceof AnnotationValue) {
-                                    AnnotationValue ov = (AnnotationValue) o;
-                                    if (message.equals(ov.getValue())) {
-                                        return true;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.io.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.tools.Diagnostic.Kind;
-import javax.tools.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.TruffleLanguage.Registration;
-
-@SupportedAnnotationTypes("com.oracle.truffle.api.*")
-public final class LanguageRegistrationProcessor extends AbstractProcessor {
-    private final List<TypeElement> registrations = new ArrayList<>();
-
-    @Override
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-    private void generateFile(List<TypeElement> languages) {
-        String filename = "META-INF/truffle/language";
-        Properties p = new Properties();
-        int cnt = 0;
-        for (TypeElement l : languages) {
-            Registration annotation = l.getAnnotation(Registration.class);
-            if (annotation == null) {
-                continue;
-            }
-            String prefix = "language" + ++cnt + ".";
-            String className = processingEnv.getElementUtils().getBinaryName(l).toString();
-            p.setProperty(prefix + "name", annotation.name());
-            p.setProperty(prefix + "version", annotation.version());
-            p.setProperty(prefix + "className", className);
-            String[] mimes = annotation.mimeType();
-            for (int i = 0; i < mimes.length; i++) {
-                p.setProperty(prefix + "mimeType." + i, mimes[i]);
-            }
-        }
-        if (cnt > 0) {
-            try {
-                FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0]));
-                try (OutputStream os = file.openOutputStream()) {
-                    p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName());
-                }
-            } catch (IOException e) {
-                processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0));
-            }
-        }
-    }
-
-    @Override
-    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-        if (roundEnv.processingOver()) {
-            generateFile(registrations);
-            registrations.clear();
-            return true;
-        }
-        for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) {
-            Registration annotation = e.getAnnotation(Registration.class);
-            if (annotation != null && e.getKind() == ElementKind.CLASS) {
-                if (!e.getModifiers().contains(Modifier.PUBLIC)) {
-                    emitError("Registered language class must be public", e);
-                    continue;
-                }
-                if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) {
-                    emitError("Registered language inner-class must be static", e);
-                    continue;
-                }
-                TypeMirror truffleLang = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.class.getName()).asType();
-                if (!processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) {
-                    emitError("Registered language class must subclass TruffleLanguage", e);
-                    continue;
-                }
-                boolean found = false;
-                for (Element mem : e.getEnclosedElements()) {
-                    if (mem.getKind() != ElementKind.CONSTRUCTOR) {
-                        continue;
-                    }
-                    ExecutableElement ee = (ExecutableElement) mem;
-                    if (ee.getParameters().size() != 1) {
-                        continue;
-                    }
-                    if (!ee.getModifiers().contains(Modifier.PUBLIC)) {
-                        continue;
-                    }
-                    TypeMirror env = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.Env.class.getCanonicalName()).asType();
-                    if (processingEnv.getTypeUtils().isSameType(ee.getParameters().get(0).asType(), env)) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    emitError("Language must have a public constructor accepting TruffleLanguage.Env as parameter", e);
-                    continue;
-                }
-                assertNoErrorExpected(e);
-                registrations.add((TypeElement) e);
-            }
-        }
-
-        return true;
-    }
-
-    void assertNoErrorExpected(Element e) {
-        ExpectError.assertNoErrorExpected(processingEnv, e);
-    }
-
-    void emitError(String msg, Element e) {
-        if (ExpectError.isExpectedError(processingEnv, e, msg)) {
-            return;
-        }
-        processingEnv.getMessager().printMessage(Kind.ERROR, msg, e);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public class Log {
-
-    public static boolean isDebug() {
-        return false;
-    }
-
-    private final ProcessingEnvironment processingEnv;
-
-    public Log(ProcessingEnvironment env) {
-        this.processingEnv = env;
-    }
-
-    public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
-        AnnotationMirror usedMirror = mirror;
-        Element usedElement = element;
-        AnnotationValue usedValue = value;
-        String message = String.format(format, args);
-
-        if (element instanceof GeneratedElement) {
-            usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror();
-            usedElement = ((GeneratedElement) element).getGeneratorElement();
-            usedValue = null;
-            if (usedElement != null) {
-                message = String.format("Element %s: %s", element, message);
-            }
-        }
-        processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public class ProcessorContext {
-
-    private final ProcessingEnvironment environment;
-
-    private final Map<String, Template> models = new HashMap<>();
-
-    private final ProcessCallback callback;
-    private final Log log;
-    private final TruffleTypes truffleTypes;
-
-    ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
-        this.environment = env;
-        this.callback = callback;
-        this.log = new Log(environment);
-        this.truffleTypes = new TruffleTypes(this);
-    }
-
-    public TruffleTypes getTruffleTypes() {
-        return truffleTypes;
-    }
-
-    public Log getLog() {
-        return log;
-    }
-
-    public ProcessingEnvironment getEnvironment() {
-        return environment;
-    }
-
-    public boolean containsTemplate(TypeElement element) {
-        return models.containsKey(ElementUtils.getQualifiedName(element));
-    }
-
-    public void registerTemplate(TypeElement element, Template model) {
-        models.put(ElementUtils.getQualifiedName(element), model);
-    }
-
-    public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) {
-        String qualifiedName = ElementUtils.getQualifiedName(templateTypeMirror);
-        Template model = models.get(qualifiedName);
-        if (model == null && invokeCallback) {
-            callback.callback(ElementUtils.fromTypeMirror(templateTypeMirror));
-            model = models.get(qualifiedName);
-        }
-        return model;
-    }
-
-    public DeclaredType getDeclaredType(Class<?> element) {
-        return (DeclaredType) ElementUtils.getType(environment, element);
-    }
-
-    public boolean isType(TypeMirror type, Class<?> clazz) {
-        return ElementUtils.typeEquals(type, getType(clazz));
-    }
-
-    public TypeMirror getType(Class<?> element) {
-        return ElementUtils.getType(environment, element);
-    }
-
-    public interface ProcessCallback {
-
-        void callback(TypeElement template);
-
-    }
-
-    public TypeMirror reloadTypeElement(TypeElement type) {
-        return getType(type.getQualifiedName().toString());
-    }
-
-    private TypeMirror getType(String className) {
-        TypeElement element = environment.getElementUtils().getTypeElement(className);
-        if (element != null) {
-            return element.asType();
-        }
-        return null;
-    }
-
-    public TypeMirror reloadType(TypeMirror type) {
-        if (type instanceof CodeTypeMirror) {
-            return type;
-        } else if (type.getKind().isPrimitive()) {
-            return type;
-        }
-        Types types = getEnvironment().getTypeUtils();
-
-        switch (type.getKind()) {
-            case ARRAY:
-                return types.getArrayType(reloadType(((ArrayType) type).getComponentType()));
-            case WILDCARD:
-                return types.getWildcardType(((WildcardType) type).getExtendsBound(), ((WildcardType) type).getSuperBound());
-            case DECLARED:
-                return reloadTypeElement((TypeElement) (((DeclaredType) type).asElement()));
-        }
-        return type;
-    }
-
-    private static final ThreadLocal<ProcessorContext> instance = new ThreadLocal<>();
-
-    public static void setThreadLocalInstance(ProcessorContext context) {
-        instance.set(context);
-    }
-
-    public static ProcessorContext getInstance() {
-        return instance.get();
-    }
-
-    public List<TypeMirror> getFrameTypes() {
-        return Arrays.asList(getType(VirtualFrame.class), getType(MaterializedFrame.class), getType(Frame.class));
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.ProcessorContext.ProcessCallback;
-import com.oracle.truffle.dsl.processor.generator.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.parser.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-// @SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation",
-// "com.oracle.truffle.codegen.TypeLattice"})
-public class TruffleProcessor extends AbstractProcessor implements ProcessCallback {
-
-    private List<AnnotationProcessor<?>> generators;
-
-    @Override
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-    @Override
-    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-        if (!roundEnv.processingOver()) {
-            processImpl(roundEnv);
-        }
-        return false;
-    }
-
-    private void processImpl(RoundEnvironment env) {
-        // TODO run verifications that other annotations are not processed out of scope of the
-        // operation or typelattice.
-        try {
-            ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, this));
-            for (AnnotationProcessor<?> generator : getGenerators()) {
-                AbstractParser<?> parser = generator.getParser();
-                if (parser.getAnnotationType() != null) {
-                    for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
-                        processElement(generator, e, false);
-                    }
-                }
-
-                for (Class<? extends Annotation> annotationType : parser.getTypeDelegatedAnnotationTypes()) {
-                    for (Element e : env.getElementsAnnotatedWith(annotationType)) {
-                        TypeElement processedType;
-                        if (parser.isDelegateToRootDeclaredType()) {
-                            processedType = ElementUtils.findRootEnclosingType(e);
-                        } else {
-                            processedType = ElementUtils.findNearestEnclosingType(e);
-                        }
-                        processElement(generator, processedType, false);
-                    }
-                }
-
-            }
-        } finally {
-            ProcessorContext.setThreadLocalInstance(null);
-        }
-    }
-
-    private static void processElement(AnnotationProcessor<?> generator, Element e, boolean callback) {
-        try {
-            generator.process(e, callback);
-        } catch (Throwable e1) {
-            handleThrowable(generator, e1, e);
-        }
-    }
-
-    private static void handleThrowable(AnnotationProcessor<?> generator, Throwable t, Element e) {
-        String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e + " ";
-        ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + ElementUtils.printException(t), e);
-    }
-
-    @Override
-    public void callback(TypeElement template) {
-        for (AnnotationProcessor<?> generator : generators) {
-            Class<? extends Annotation> annotationType = generator.getParser().getAnnotationType();
-            if (annotationType != null) {
-                Annotation annotation = template.getAnnotation(annotationType);
-                if (annotation != null) {
-                    processElement(generator, template, true);
-                }
-            }
-        }
-    }
-
-    @Override
-    public Set<String> getSupportedAnnotationTypes() {
-        Set<String> annotations = new HashSet<>();
-        List<Class<? extends Annotation>> annotationsTypes = new ArrayList<>();
-        annotationsTypes.addAll(NodeParser.ANNOTATIONS);
-        annotationsTypes.addAll(TypeSystemParser.ANNOTATIONS);
-        for (Class<? extends Annotation> type : annotationsTypes) {
-            annotations.add(type.getCanonicalName());
-        }
-        return annotations;
-    }
-
-    private List<AnnotationProcessor<?>> getGenerators() {
-        if (generators == null && processingEnv != null) {
-            generators = new ArrayList<>();
-            generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator()));
-            generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator()));
-        }
-        return generators;
-    }
-
-    @Override
-    public synchronized void init(ProcessingEnvironment env) {
-        this.processingEnv = env;
-        super.init(env);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.api.source.*;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public final class TruffleTypes {
-
-    public static final String EXPECT_ERROR_CLASS_NAME = "com.oracle.truffle.api.dsl.test.ExpectError";
-
-    private final DeclaredType node;
-    private final ArrayType nodeArray;
-    private final TypeMirror unexpectedValueException;
-    private final TypeMirror frame;
-    private final TypeMirror assumption;
-    private final TypeMirror invalidAssumption;
-    private final DeclaredType childAnnotation;
-    private final DeclaredType childrenAnnotation;
-    private final DeclaredType nodeInfoAnnotation;
-    private final DeclaredType nodeCost;
-    private final TypeMirror compilerDirectives;
-    private final TypeMirror compilerAsserts;
-    private final DeclaredType truffleBoundary;
-    private final DeclaredType sourceSection;
-    private final DeclaredType truffleOptions;
-    private final DeclaredType compilationFinal;
-    private final DeclaredType nodeUtil;
-    private final DeclaredType dslNode;
-    private final DeclaredType dslShare;
-    private final DeclaredType nodeFactory;
-    private final DeclaredType nodeFactoryBase;
-    private final DeclaredType dslMetadata;
-    private final DeclaredType generateNodeFactory;
-    private final TypeElement expectError;
-
-    private final List<String> errors = new ArrayList<>();
-
-    TruffleTypes(ProcessorContext context) {
-        node = getRequired(context, Node.class);
-        nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node);
-        unexpectedValueException = getRequired(context, UnexpectedResultException.class);
-        frame = getRequired(context, VirtualFrame.class);
-        childAnnotation = getRequired(context, Child.class);
-        childrenAnnotation = getRequired(context, Children.class);
-        compilerDirectives = getRequired(context, CompilerDirectives.class);
-        compilerAsserts = getRequired(context, CompilerAsserts.class);
-        assumption = getRequired(context, Assumption.class);
-        invalidAssumption = getRequired(context, InvalidAssumptionException.class);
-        nodeInfoAnnotation = getRequired(context, NodeInfo.class);
-        nodeCost = getRequired(context, NodeCost.class);
-        truffleBoundary = getRequired(context, TruffleBoundary.class);
-        sourceSection = getRequired(context, SourceSection.class);
-        truffleOptions = getRequired(context, TruffleOptions.class);
-        compilationFinal = getRequired(context, CompilationFinal.class);
-        nodeUtil = getRequired(context, NodeUtil.class);
-        dslNode = getRequired(context, DSLNode.class);
-        dslShare = getRequired(context, DSLShare.class);
-        nodeFactory = getRequired(context, NodeFactory.class);
-        nodeFactoryBase = getRequired(context, NodeFactoryBase.class);
-        dslMetadata = getRequired(context, DSLMetadata.class);
-        expectError = getOptional(context, EXPECT_ERROR_CLASS_NAME);
-        generateNodeFactory = getRequired(context, GenerateNodeFactory.class);
-    }
-
-    public DeclaredType getGenerateNodeFactory() {
-        return generateNodeFactory;
-    }
-
-    public DeclaredType getDslMetadata() {
-        return dslMetadata;
-    }
-
-    public DeclaredType getNodeFactory() {
-        return nodeFactory;
-    }
-
-    public DeclaredType getNodeFactoryBase() {
-        return nodeFactoryBase;
-    }
-
-    public DeclaredType getDslNode() {
-        return dslNode;
-    }
-
-    public DeclaredType getDslShare() {
-        return dslShare;
-    }
-
-    public DeclaredType getCompilationFinal() {
-        return compilationFinal;
-    }
-
-    public TypeElement getExpectError() {
-        return expectError;
-    }
-
-    public DeclaredType getNodeInfoAnnotation() {
-        return nodeInfoAnnotation;
-    }
-
-    public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
-        if (errors.isEmpty()) {
-            return true;
-        }
-
-        for (String error : errors) {
-            context.getLog().message(Kind.ERROR, element, mirror, null, error);
-        }
-
-        return false;
-    }
-
-    public DeclaredType getNodeCost() {
-        return nodeCost;
-    }
-
-    private DeclaredType getRequired(ProcessorContext context, Class<?> clazz) {
-        TypeMirror type = context.getType(clazz);
-        if (type == null) {
-            errors.add(String.format("Could not find required type: %s", clazz.getSimpleName()));
-        }
-        return (DeclaredType) type;
-    }
-
-    private static TypeElement getOptional(ProcessorContext context, String name) {
-        return context.getEnvironment().getElementUtils().getTypeElement(name);
-    }
-
-    public TypeMirror getInvalidAssumption() {
-        return invalidAssumption;
-    }
-
-    public TypeMirror getAssumption() {
-        return assumption;
-    }
-
-    public TypeMirror getCompilerDirectives() {
-        return compilerDirectives;
-    }
-
-    public DeclaredType getNode() {
-        return node;
-    }
-
-    public ArrayType getNodeArray() {
-        return nodeArray;
-    }
-
-    public TypeMirror getFrame() {
-        return frame;
-    }
-
-    public TypeMirror getUnexpectedValueException() {
-        return unexpectedValueException;
-    }
-
-    public DeclaredType getChildAnnotation() {
-        return childAnnotation;
-    }
-
-    public DeclaredType getChildrenAnnotation() {
-        return childrenAnnotation;
-    }
-
-    public TypeMirror getCompilerAsserts() {
-        return compilerAsserts;
-    }
-
-    public DeclaredType getTruffleOptions() {
-        return truffleOptions;
-    }
-
-    public DeclaredType getTruffleBoundary() {
-        return truffleBoundary;
-    }
-
-    public DeclaredType getSourceSection() {
-        return sourceSection;
-    }
-
-    public DeclaredType getNodeUtil() {
-        return nodeUtil;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 content of this file is automatically generated. DO NOT EDIT.
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public abstract class DSLExpression {
-
-    private TypeMirror resolvedTargetType;
-
-    private DSLExpression() {
-    }
-
-    public static DSLExpression parse(String input) {
-        return Parser.parse(input);
-    }
-
-    public final Set<VariableElement> findBoundVariableElements() {
-        final Set<VariableElement> variables = new HashSet<>();
-        this.accept(new AbstractDSLExpressionVisitor() {
-
-            @Override
-            public void visitVariable(Variable variable) {
-                if (variable.getReceiver() == null) {
-                    variables.add(variable.getResolvedVariable());
-                }
-            }
-
-        });
-        return variables;
-    }
-
-    public final Set<Variable> findBoundVariables() {
-        final Set<Variable> variables = new HashSet<>();
-        this.accept(new AbstractDSLExpressionVisitor() {
-
-            @Override
-            public void visitVariable(Variable variable) {
-                if (variable.getReceiver() == null) {
-                    variables.add(variable);
-                }
-            }
-
-        });
-        return variables;
-    }
-
-    public boolean containsComparisons() {
-        final AtomicBoolean found = new AtomicBoolean();
-        this.accept(new AbstractDSLExpressionVisitor() {
-            @Override
-            public void visitBinary(Binary binary) {
-                if (binary.isComparison()) {
-                    found.set(true);
-                }
-            }
-        });
-        return found.get();
-    }
-
-    public void setResolvedTargetType(TypeMirror resolvedTargetType) {
-        this.resolvedTargetType = resolvedTargetType;
-    }
-
-    public TypeMirror getResolvedTargetType() {
-        return resolvedTargetType;
-    }
-
-    public abstract TypeMirror getResolvedType();
-
-    public abstract void accept(DSLExpressionVisitor visitor);
-
-    public static final class Negate extends DSLExpression {
-
-        private final DSLExpression receiver;
-
-        public Negate(DSLExpression receiver) {
-            this.receiver = receiver;
-        }
-
-        @Override
-        public void accept(DSLExpressionVisitor visitor) {
-            receiver.accept(visitor);
-            visitor.visitNegate(this);
-        }
-
-        public DSLExpression getReceiver() {
-            return receiver;
-        }
-
-        @Override
-        public TypeMirror getResolvedType() {
-            return receiver.getResolvedType();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Negate) {
-                return receiver.equals(((Negate) obj).receiver);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return receiver.hashCode();
-        }
-    }
-
-    public static final class Binary extends DSLExpression {
-
-        private final String operator;
-        private final DSLExpression left;
-        private final DSLExpression right;
-
-        private TypeMirror resolvedType;
-
-        public Binary(String operator, DSLExpression left, DSLExpression right) {
-            this.operator = operator;
-            this.left = left;
-            this.right = right;
-        }
-
-        public boolean isComparison() {
-            return DSLExpressionResolver.COMPARABLE_OPERATORS.contains(operator) || DSLExpressionResolver.IDENTITY_OPERATORS.contains(operator);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Binary) {
-                Binary other = (Binary) obj;
-                return operator.equals(other.operator) && left.equals(other.left) && right.equals(other.right);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(operator, left, right);
-        }
-
-        public String getOperator() {
-            return operator;
-        }
-
-        public DSLExpression getLeft() {
-            return left;
-        }
-
-        public DSLExpression getRight() {
-            return right;
-        }
-
-        @Override
-        public void accept(DSLExpressionVisitor visitor) {
-            left.accept(visitor);
-            right.accept(visitor);
-            visitor.visitBinary(this);
-        }
-
-        @Override
-        public TypeMirror getResolvedType() {
-            return resolvedType;
-        }
-
-        public void setResolvedType(TypeMirror resolvedType) {
-            this.resolvedType = resolvedType;
-        }
-
-        @Override
-        public String toString() {
-            return "Binary [left=" + left + ", operator=" + operator + ", right=" + right + ", resolvedType=" + resolvedType + "]";
-        }
-
-    }
-
-    public static final class Call extends DSLExpression {
-
-        private final DSLExpression receiver;
-        private final String name;
-        private final List<DSLExpression> parameters;
-
-        private ExecutableElement resolvedMethod;
-
-        public Call(DSLExpression receiver, String name, List<DSLExpression> parameters) {
-            this.receiver = receiver;
-            this.name = name;
-            this.parameters = parameters;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Call) {
-                Call other = (Call) obj;
-                return Objects.equals(receiver, other.receiver) && name.equals(other.name) && parameters.equals(other.parameters);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(receiver, name, parameters);
-        }
-
-        public DSLExpression getReceiver() {
-            return receiver;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public List<DSLExpression> getParameters() {
-            return parameters;
-        }
-
-        @Override
-        public void accept(DSLExpressionVisitor visitor) {
-            if (receiver != null) {
-                receiver.accept(visitor);
-            }
-            for (DSLExpression parameter : getParameters()) {
-                parameter.accept(visitor);
-            }
-            visitor.visitCall(this);
-        }
-
-        @Override
-        public TypeMirror getResolvedType() {
-            if (resolvedMethod == null) {
-                return null;
-            }
-            if (resolvedMethod.getKind() == ElementKind.CONSTRUCTOR) {
-                return resolvedMethod.getEnclosingElement().asType();
-            } else {
-                return resolvedMethod.getReturnType();
-            }
-        }
-
-        public ExecutableElement getResolvedMethod() {
-            return resolvedMethod;
-        }
-
-        public void setResolvedMethod(ExecutableElement resolvedMethod) {
-            this.resolvedMethod = resolvedMethod;
-        }
-
-        @Override
-        public String toString() {
-            return "Call [receiver=" + receiver + ", name=" + name + ", parameters=" + parameters + ", resolvedMethod=" + resolvedMethod + "]";
-        }
-
-    }
-
-    public static final class Variable extends DSLExpression {
-
-        private final DSLExpression receiver;
-        private final String name;
-
-        private VariableElement resolvedVariable;
-
-        public Variable(DSLExpression receiver, String name) {
-            this.receiver = receiver;
-            this.name = name;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Variable) {
-                Variable other = (Variable) obj;
-                return Objects.equals(receiver, other.receiver) && name.equals(other.name);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(receiver, name);
-        }
-
-        public DSLExpression getReceiver() {
-            return receiver;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public void accept(DSLExpressionVisitor visitor) {
-            if (receiver != null) {
-                receiver.accept(visitor);
-            }
-            visitor.visitVariable(this);
-        }
-
-        @Override
-        public TypeMirror getResolvedType() {
-            return resolvedVariable != null ? resolvedVariable.asType() : null;
-        }
-
-        public void setResolvedVariable(VariableElement resolvedVariable) {
-            this.resolvedVariable = resolvedVariable;
-        }
-
-        public VariableElement getResolvedVariable() {
-            return resolvedVariable;
-        }
-
-        @Override
-        public String toString() {
-            return "Variable [receiver=" + receiver + ", name=" + name + ", resolvedVariable=" + resolvedVariable + "]";
-        }
-
-    }
-
-    public static final class IntLiteral extends DSLExpression {
-
-        private final String literal;
-
-        private int resolvedValueInt;
-        private TypeMirror resolvedType;
-
-        public IntLiteral(String literal) {
-            this.literal = literal;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof IntLiteral) {
-                IntLiteral other = (IntLiteral) obj;
-                return resolvedValueInt == other.resolvedValueInt;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return resolvedValueInt;
-        }
-
-        public String getLiteral() {
-            return literal;
-        }
-
-        public int getResolvedValueInt() {
-            return resolvedValueInt;
-        }
-
-        public void setResolvedValueInt(int resolved) {
-            this.resolvedValueInt = resolved;
-        }
-
-        @Override
-        public TypeMirror getResolvedType() {
-            return resolvedType;
-        }
-
-        public void setResolvedType(TypeMirror resolvedType) {
-            this.resolvedType = resolvedType;
-        }
-
-        @Override
-        public void accept(DSLExpressionVisitor visitor) {
-            visitor.visitIntLiteral(this);
-        }
-
-        @Override
-        public String toString() {
-            return "IntLiteral [literal=" + literal + ", resolvedValueInt=" + resolvedValueInt + ", resolvedType=" + resolvedType + "]";
-        }
-
-    }
-
-    public abstract class AbstractDSLExpressionVisitor implements DSLExpressionVisitor {
-
-        public void visitBinary(Binary binary) {
-        }
-
-        public void visitCall(Call binary) {
-        }
-
-        public void visitIntLiteral(IntLiteral binary) {
-        }
-
-        public void visitNegate(Negate negate) {
-        }
-
-        public void visitVariable(Variable binary) {
-        }
-    }
-
-    public interface DSLExpressionVisitor {
-
-        void visitBinary(Binary binary);
-
-        void visitNegate(Negate negate);
-
-        void visitCall(Call binary);
-
-        void visitVariable(Variable binary);
-
-        void visitIntLiteral(IntLiteral binary);
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,258 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public class DSLExpressionResolver implements DSLExpressionVisitor {
-
-    private static final List<String> LOGIC_OPERATORS = Arrays.asList("||");
-    public static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">=");
-    public static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!=");
-    private static final String CONSTRUCTOR_KEYWORD = "new";
-
-    private final List<VariableElement> variables = new ArrayList<>();
-    private final List<ExecutableElement> methods = new ArrayList<>();
-    private final ProcessorContext context;
-
-    private DSLExpressionResolver(ProcessorContext context) {
-        this.context = context;
-    }
-
-    public DSLExpressionResolver(ProcessorContext context, List<? extends Element> lookupElements) {
-        this(context);
-        lookup(lookupElements);
-    }
-
-    public DSLExpressionResolver copy(List<? extends Element> prefixElements) {
-        DSLExpressionResolver resolver = new DSLExpressionResolver(context);
-        resolver.lookup(prefixElements);
-        resolver.variables.addAll(variables);
-        resolver.methods.addAll(methods);
-        return resolver;
-    }
-
-    private void lookup(List<? extends Element> lookupElements) {
-        variablesIn(variables, lookupElements, false);
-        methodsIn(lookupElements);
-    }
-
-    private void methodsIn(List<? extends Element> lookupElements) {
-        for (Element variable : lookupElements) {
-            ElementKind kind = variable.getKind();
-            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
-                methods.add((ExecutableElement) variable);
-            }
-        }
-    }
-
-    private static void variablesIn(List<VariableElement> variables, List<? extends Element> lookupElements, boolean publicOnly) {
-        for (Element variable : lookupElements) {
-            ElementKind kind = variable.getKind();
-            if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER || kind == ElementKind.FIELD || kind == ElementKind.ENUM_CONSTANT) {
-                VariableElement variableElement = (VariableElement) variable;
-                if (!publicOnly || variableElement.getModifiers().contains(Modifier.PUBLIC)) {
-                    variables.add(variableElement);
-                }
-            }
-        }
-    }
-
-    private static String getMethodName(ExecutableElement method) {
-        if (method.getKind() == ElementKind.CONSTRUCTOR) {
-            return CONSTRUCTOR_KEYWORD;
-        } else {
-            return method.getSimpleName().toString();
-        }
-    }
-
-    public void visitBinary(Binary binary) {
-        String operator = binary.getOperator();
-        TypeMirror leftType = binary.getLeft().getResolvedType();
-        TypeMirror rightType = binary.getRight().getResolvedType();
-        if (!ElementUtils.areTypesCompatible(leftType, rightType)) {
-            throw new InvalidExpressionException(String.format("Incompatible operand types %s and %s.", ElementUtils.getSimpleName(leftType), ElementUtils.getSimpleName(rightType)));
-        }
-
-        TypeMirror booleanType = context.getType(boolean.class);
-        boolean valid;
-        if (LOGIC_OPERATORS.contains(operator)) {
-            valid = ElementUtils.typeEquals(leftType, booleanType);
-        } else if (COMPARABLE_OPERATORS.contains(operator)) {
-            valid = ElementUtils.isPrimitive(leftType);
-        } else if (IDENTITY_OPERATORS.contains(operator)) {
-            valid = leftType.getKind().isPrimitive() || leftType.getKind() == TypeKind.DECLARED || leftType.getKind() == TypeKind.ARRAY;
-        } else {
-            throw new InvalidExpressionException(String.format("The operator %s is undefined.", operator));
-        }
-        binary.setResolvedType(booleanType);
-
-        if (!valid) {
-            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type(s) %s %s.", operator, ElementUtils.getSimpleName(leftType),
-                            ElementUtils.getSimpleName(rightType)));
-        }
-    }
-
-    public void visitNegate(Negate negate) {
-        TypeMirror booleanType = context.getType(boolean.class);
-        TypeMirror resolvedType = negate.getResolvedType();
-        if (!ElementUtils.typeEquals(resolvedType, booleanType)) {
-            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type %s.", "!", ElementUtils.getSimpleName(resolvedType)));
-        }
-    }
-
-    public void visitCall(Call call) {
-        List<ExecutableElement> lookupMethods;
-        DSLExpression receiver = call.getReceiver();
-        if (receiver == null) {
-            lookupMethods = this.methods;
-        } else {
-            TypeMirror type = receiver.getResolvedType();
-            if (type.getKind() == TypeKind.DECLARED) {
-                type = context.reloadType(type); // ensure ECJ has the type loaded
-                lookupMethods = ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()));
-            } else {
-                lookupMethods = Collections.emptyList();
-            }
-        }
-
-        ExecutableElement foundWithName = null;
-        outer: for (ExecutableElement method : lookupMethods) {
-            if (getMethodName(method).equals(call.getName())) {
-                foundWithName = method;
-
-                List<? extends VariableElement> parameters = method.getParameters();
-                if (parameters.size() != call.getParameters().size()) {
-                    continue outer;
-                }
-
-                int parameterIndex = 0;
-                for (DSLExpression expression : call.getParameters()) {
-                    TypeMirror sourceType = expression.getResolvedType();
-                    TypeMirror targetType = parameters.get(parameterIndex).asType();
-                    if (!ElementUtils.isAssignable(sourceType, targetType)) {
-                        continue outer;
-                    }
-                    expression.setResolvedTargetType(targetType);
-                    parameterIndex++;
-                }
-
-                call.setResolvedMethod(method);
-                break;
-            }
-        }
-        if (call.getResolvedMethod() == null) {
-            if (foundWithName == null) {
-                // parameter mismatch
-                throw new InvalidExpressionException(String.format("The method %s is undefined for the enclosing scope.", call.getName()));
-            } else {
-                StringBuilder arguments = new StringBuilder();
-                String sep = "";
-                for (DSLExpression expression : call.getParameters()) {
-                    arguments.append(sep).append(ElementUtils.getSimpleName(expression.getResolvedType()));
-                    sep = ", ";
-                }
-                // name mismatch
-                throw new InvalidExpressionException(String.format("The method %s in the type %s is not applicable for the arguments %s.", //
-                                ElementUtils.getReadableSignature(foundWithName), //
-                                ElementUtils.getSimpleName((TypeElement) foundWithName.getEnclosingElement()), arguments.toString()));
-            }
-        }
-    }
-
-    public void visitVariable(Variable variable) {
-        List<VariableElement> lookupVariables;
-        DSLExpression receiver = variable.getReceiver();
-        if (variable.getName().equals("null")) {
-            variable.setResolvedVariable(new CodeVariableElement(new CodeTypeMirror(TypeKind.NULL), "null"));
-        } else {
-            if (receiver == null) {
-                lookupVariables = this.variables;
-            } else {
-                TypeMirror type = receiver.getResolvedType();
-                if (type.getKind() == TypeKind.DECLARED) {
-                    type = context.reloadType(type); // ensure ECJ has the type loaded
-                    lookupVariables = new ArrayList<>();
-                    variablesIn(lookupVariables, context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()), true);
-                } else if (type.getKind() == TypeKind.ARRAY) {
-                    lookupVariables = Arrays.<VariableElement> asList(new CodeVariableElement(context.getType(int.class), "length"));
-                } else {
-                    lookupVariables = Collections.emptyList();
-                }
-            }
-
-            for (VariableElement variableElement : lookupVariables) {
-                if (variableElement.getSimpleName().toString().equals(variable.getName())) {
-                    variable.setResolvedVariable(variableElement);
-                    break;
-                }
-            }
-        }
-
-        if (variable.getResolvedVariable() == null) {
-            throw new InvalidExpressionException(String.format("%s cannot be resolved.", variable.getName()));
-        }
-    }
-
-    public void visitIntLiteral(IntLiteral binary) {
-        try {
-            binary.setResolvedType(context.getType(int.class));
-
-            final int base;
-            final String literal;
-
-            if (binary.getLiteral().startsWith("0x")) {
-                base = 16;
-                literal = binary.getLiteral().substring(2);
-            } else if (binary.getLiteral().startsWith("0b")) {
-                base = 2;
-                literal = binary.getLiteral().substring(2);
-            } else if (binary.getLiteral().startsWith("0")) {
-                base = 8;
-                literal = binary.getLiteral();
-            } else {
-                base = 10;
-                literal = binary.getLiteral();
-            }
-
-            binary.setResolvedValueInt(Integer.parseInt(literal, base));
-        } catch (NumberFormatException e) {
-            throw new InvalidExpressionException(String.format("Type mismatch: cannot convert from String '%s' to int", binary.getLiteral()));
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 is the grammar for DSL expressions that is used to automatically generate the Parser.java and Scanner.java
- * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run
- * "java -jar Coco.jar Expression.atg"
- */
-
-COMPILER Expression
-
-CHARACTERS
-
-letter = 'A' .. 'Z' + 'a' .. 'z' + '_' + '$'.
-nonZeroDigit = "123456789".
-digit = '0' + nonZeroDigit .
-hexDigit = "0123456789abcdefABCDEF".
-octDigit = "01234567".
-binaryDigit = "01".
-
-TOKENS
-
-identifier = letter {letter | digit}.
-numericLiteral = "0" ( "x" { hexDigit } | "b" { binaryDigit } | { octDigit } ) | nonZeroDigit { digit }.
-
-PRAGMAS
-
-PRODUCTIONS
-
-
-Expression<out DSLExpression result>
-=
-LogicFactor<out result>
-.
-
-
-LogicFactor<out DSLExpression  result>
-=
-ComparisonFactor<out result>
-[
-    ("||")                                      (. Token op = t; .)
-    ComparisonFactor<out DSLExpression  right>  (.  result = new Binary(op.val, result, right); .)
-]
-.
-
-ComparisonFactor<out DSLExpression  result>
-=
-NegateFactor<out result>
-[
-    ("<" | "<=" | ">" | ">=" | "==" | "!=" )    (. Token op = t; .)
-    NegateFactor<out DSLExpression  right>      (.  result = new Binary(op.val, result, right); .)
-]
-.
-
-
-NegateFactor<out DSLExpression  result>
-=                                               (. boolean negated = false; .)
-[
-    "!"                                         (. negated = true; .)
-]                                        
-    Factor<out result>                          (. result = negated ? new Negate(result) : result;.)
-.
-
-
-Factor<out DSLExpression result>
-=                                               (. result = null; .)
-
-(
-    MemberExpression<out result, result>
-|
-    numericLiteral                              (. result = new IntLiteral(t.val); .)
-|
-    "("                                        
-    Expression<out result>                      
-    ")"                                        
-                                                
-)
-.
-
-MemberExpression<out DSLExpression result, DSLExpression receiver>
-=                                               (. result = null; .)
-(
-    
-    identifier                                  (. Variable variable = new Variable(receiver, t.val); .)
-                                                (. result = variable; .)
-[
-
-    "("                                         (. List<DSLExpression> parameters = new ArrayList<>();
-                                                   DSLExpression parameter; .)
-    [
-        Expression<out parameter>               (. parameters.add(parameter); .)
-        {
-            ","
-            Expression<out parameter>           (. parameters.add(parameter); .)
-        }
-    ]
-    ")"                                         (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .)
-]
-                                                
-)
-[
-   "." MemberExpression<out result, result>
-]
-.
-END Expression.
-
-
-
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.expression;
-
-public class InvalidExpressionException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public InvalidExpressionException(String message) {
-        super(message);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*-------------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported from C# to Java by Wolfgang Ahorner
-with improvements by Pat Terry, Rhodes University
-
-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, 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.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than 
-Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
--->begin
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.util.*;
-import java.io.*;
-import java.nio.charset.*;
-
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.*;
-
-// Checkstyle: stop
-// @formatter:off
-class Parser {
--->constants
-    static final boolean _T = true;
-    static final boolean _x = false;
-    static final int minErrDist = 2;
-
-    public Token t; // last recognized token
-    public Token la; // lookahead token
-    int errDist = minErrDist;
-
-    public final Scanner scanner;
-    public final Errors errors;
-    
-    -->declarations
-    public Parser(InputStream input) {
-        this.scanner = new Scanner(input);
-        errors = new Errors();
-    }
-
-    void SynErr(int n) {
-        if (errDist >= minErrDist)
-            errors.SynErr(la.line, la.col, n);
-        errDist = 0;
-    }
-
-    public void SemErr(String msg) {
-        if (errDist >= minErrDist)
-            errors.SemErr(t.line, t.col, msg);
-        errDist = 0;
-    }
-
-    void Get() {
-        for (;;) {
-            t = la;
-            la = scanner.Scan();
-            if (la.kind <= maxT) {
-                ++errDist;
-                break;
-            }
--->pragmas
-            la = t;
-        }
-    }
-
-    void Expect(int n) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-        }
-    }
-
-    boolean StartOf(int s) {
-        return set[s][la.kind];
-    }
-
-    void ExpectWeak(int n, int follow) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-            while (!StartOf(follow))
-                Get();
-        }
-    }
-
-    boolean WeakSeparator(int n, int syFol, int repFol) {
-        int kind = la.kind;
-        if (kind == n) {
-            Get();
-            return true;
-        } else if (StartOf(repFol))
-            return false;
-        else {
-            SynErr(n);
-            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
-                Get();
-                kind = la.kind;
-            }
-            return StartOf(syFol);
-        }
-    }
-
--->productions
-
-    private DSLExpression parseImpl() {
-        la = new Token();
-        la.val = "";
-        Get();
-        DSLExpression result = -->parseRoot
-        return result;
-    }
-
-    private static final boolean[][] set = {
--->initialization
-    };
-
-    public static DSLExpression parse(InputStream input) {
-        Parser parser = new Parser(input);
-        DSLExpression result = parser.parseImpl();
-        if (parser.errors.errors.size() > 0) {
-            StringBuilder msg = new StringBuilder();
-            for (String error : parser.errors.errors) {
-                msg.append(error).append("\n");
-            }
-            throw new InvalidExpressionException(msg.toString());
-        }
-        return result;
-    }
-
-    public static DSLExpression parse(String s) {
-        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
-    }
-} // end Parser
-
-class Errors {
-
-    protected final List<String> errors = new ArrayList<>();
-    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-
-    protected void printMsg(int line, int column, String msg) {
-        StringBuffer b = new StringBuffer(errMsgFormat);
-        int pos = b.indexOf("{0}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, line);
-        }
-        pos = b.indexOf("{1}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, column);
-        }
-        pos = b.indexOf("{2}");
-        if (pos >= 0)
-            b.replace(pos, pos + 3, msg);
-        errors.add(b.toString());
-    }
-
-    public void SynErr(int line, int col, int n) {
-        String s;
-        switch (n) {-->errors
-            default:
-                s = "error " + n;
-                break;
-        }
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(String s) {
-        errors.add(s);
-    }
-
-    public void Warning(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void Warning(String s) {
-        errors.add(s);
-    }
-} // Errors
-
-class FatalError extends RuntimeException {
-
-    public static final long serialVersionUID = 1L;
-
-    public FatalError(String s) {
-        super(s);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,350 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 content of this file is automatically generated. DO NOT EDIT.
-
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.util.*;
-
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
-
-// Checkstyle: stop
-// @formatter:off
-class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _numericLiteral = 2;
-	public static final int maxT = 15;
-
-    static final boolean _T = true;
-    static final boolean _x = false;
-    static final int minErrDist = 2;
-
-    public Token t; // last recognized token
-    public Token la; // lookahead token
-    int errDist = minErrDist;
-
-    public final Scanner scanner;
-    public final Errors errors;
-    
-    
-    public Parser(InputStream input) {
-        this.scanner = new Scanner(input);
-        errors = new Errors();
-    }
-
-    void SynErr(int n) {
-        if (errDist >= minErrDist)
-            errors.SynErr(la.line, la.col, n);
-        errDist = 0;
-    }
-
-    public void SemErr(String msg) {
-        if (errDist >= minErrDist)
-            errors.SemErr(t.line, t.col, msg);
-        errDist = 0;
-    }
-
-    void Get() {
-        for (;;) {
-            t = la;
-            la = scanner.Scan();
-            if (la.kind <= maxT) {
-                ++errDist;
-                break;
-            }
-
-            la = t;
-        }
-    }
-
-    void Expect(int n) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-        }
-    }
-
-    boolean StartOf(int s) {
-        return set[s][la.kind];
-    }
-
-    void ExpectWeak(int n, int follow) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-            while (!StartOf(follow))
-                Get();
-        }
-    }
-
-    boolean WeakSeparator(int n, int syFol, int repFol) {
-        int kind = la.kind;
-        if (kind == n) {
-            Get();
-            return true;
-        } else if (StartOf(repFol))
-            return false;
-        else {
-            SynErr(n);
-            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
-                Get();
-                kind = la.kind;
-            }
-            return StartOf(syFol);
-        }
-    }
-
-	DSLExpression  Expression() {
-		DSLExpression  result;
-		result = LogicFactor();
-		return result;
-	}
-
-	DSLExpression   LogicFactor() {
-		DSLExpression   result;
-		result = ComparisonFactor();
-		if (la.kind == 3) {
-			Get();
-			Token op = t; 
-			DSLExpression  right = ComparisonFactor();
-			result = new Binary(op.val, result, right); 
-		}
-		return result;
-	}
-
-	DSLExpression   ComparisonFactor() {
-		DSLExpression   result;
-		result = NegateFactor();
-		if (StartOf(1)) {
-			switch (la.kind) {
-			case 4: {
-				Get();
-				break;
-			}
-			case 5: {
-				Get();
-				break;
-			}
-			case 6: {
-				Get();
-				break;
-			}
-			case 7: {
-				Get();
-				break;
-			}
-			case 8: {
-				Get();
-				break;
-			}
-			case 9: {
-				Get();
-				break;
-			}
-			}
-			Token op = t; 
-			DSLExpression  right = NegateFactor();
-			result = new Binary(op.val, result, right); 
-		}
-		return result;
-	}
-
-	DSLExpression   NegateFactor() {
-		DSLExpression   result;
-		boolean negated = false; 
-		if (la.kind == 10) {
-			Get();
-			negated = true; 
-		}
-		result = Factor();
-		result = negated ? new Negate(result) : result;
-		return result;
-	}
-
-	DSLExpression  Factor() {
-		DSLExpression  result;
-		result = null; 
-		if (la.kind == 1) {
-			result = MemberExpression(result);
-		} else if (la.kind == 2) {
-			Get();
-			result = new IntLiteral(t.val); 
-		} else if (la.kind == 11) {
-			Get();
-			result = Expression();
-			Expect(12);
-		} else SynErr(16);
-		return result;
-	}
-
-	DSLExpression  MemberExpression(DSLExpression receiver) {
-		DSLExpression  result;
-		result = null; 
-		Expect(1);
-		Variable variable = new Variable(receiver, t.val); 
-		result = variable; 
-		if (la.kind == 11) {
-			Get();
-			List<DSLExpression> parameters = new ArrayList<>();
-			DSLExpression parameter; 
-			if (StartOf(2)) {
-				parameter = Expression();
-				parameters.add(parameter); 
-				while (la.kind == 13) {
-					Get();
-					parameter = Expression();
-					parameters.add(parameter); 
-				}
-			}
-			Expect(12);
-			result = new Call(variable.getReceiver(), variable.getName(), parameters); 
-		}
-		if (la.kind == 14) {
-			Get();
-			result = MemberExpression(result);
-		}
-		return result;
-	}
-
-
-
-    private DSLExpression parseImpl() {
-        la = new Token();
-        la.val = "";
-        Get();
-        DSLExpression result = 		Expression();
-		Expect(0);
-
-        return result;
-    }
-
-    private static final boolean[][] set = {
-		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_T,_T,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x}
-
-    };
-
-    public static DSLExpression parse(InputStream input) {
-        Parser parser = new Parser(input);
-        DSLExpression result = parser.parseImpl();
-        if (parser.errors.errors.size() > 0) {
-            StringBuilder msg = new StringBuilder();
-            for (String error : parser.errors.errors) {
-                msg.append(error).append("\n");
-            }
-            throw new InvalidExpressionException(msg.toString());
-        }
-        return result;
-    }
-
-    public static DSLExpression parse(String s) {
-        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
-    }
-} // end Parser
-
-class Errors {
-
-    protected final List<String> errors = new ArrayList<>();
-    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-
-    protected void printMsg(int line, int column, String msg) {
-        StringBuffer b = new StringBuffer(errMsgFormat);
-        int pos = b.indexOf("{0}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, line);
-        }
-        pos = b.indexOf("{1}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, column);
-        }
-        pos = b.indexOf("{2}");
-        if (pos >= 0)
-            b.replace(pos, pos + 3, msg);
-        errors.add(b.toString());
-    }
-
-    public void SynErr(int line, int col, int n) {
-        String s;
-        switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "numericLiteral expected"; break;
-			case 3: s = "\"||\" expected"; break;
-			case 4: s = "\"<\" expected"; break;
-			case 5: s = "\"<=\" expected"; break;
-			case 6: s = "\">\" expected"; break;
-			case 7: s = "\">=\" expected"; break;
-			case 8: s = "\"==\" expected"; break;
-			case 9: s = "\"!=\" expected"; break;
-			case 10: s = "\"!\" expected"; break;
-			case 11: s = "\"(\" expected"; break;
-			case 12: s = "\")\" expected"; break;
-			case 13: s = "\",\" expected"; break;
-			case 14: s = "\".\" expected"; break;
-			case 15: s = "??? expected"; break;
-			case 16: s = "invalid Factor"; break;
-            default:
-                s = "error " + n;
-                break;
-        }
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(String s) {
-        errors.add(s);
-    }
-
-    public void Warning(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void Warning(String s) {
-        errors.add(s);
-    }
-} // Errors
-
-class FatalError extends RuntimeException {
-
-    public static final long serialVersionUID = 1L;
-
-    public FatalError(String s) {
-        super(s);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,495 +0,0 @@
-/*-------------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported from C# to Java by Wolfgang Ahorner
-with improvements by Pat Terry, Rhodes University
-
-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, 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.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than 
-Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
--->begin
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.Map;
-import java.util.HashMap;
-
-// Checkstyle: stop
-// @formatter:off
-class Token {
-
-    public int kind; // token kind
-    public int pos; // token position in bytes in the source text (starting at 0)
-    public int charPos; // token position in characters in the source text (starting at 0)
-    public int col; // token column (starting at 1)
-    public int line; // token line (starting at 1)
-    public String val; // token value
-    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
-}
-
-// -----------------------------------------------------------------------------------
-// Buffer
-// -----------------------------------------------------------------------------------
-class Buffer {
-
-    // This Buffer supports the following cases:
-    // 1) seekable stream (file)
-    // a) whole stream in buffer
-    // b) part of stream in buffer
-    // 2) non seekable stream (network, console)
-
-    public static final int EOF = Character.MAX_VALUE + 1;
-    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
-    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
-    private byte[] buf; // input buffer
-    private int bufStart; // position of first byte in buffer relative to input stream
-    private int bufLen; // length of buffer
-    private int fileLen; // length of input stream (may change if stream is no file)
-    private int bufPos; // current position in buffer
-    private RandomAccessFile file; // input stream (seekable)
-    private InputStream stream; // growing input stream (e.g.: console, network)
-
-    public Buffer(InputStream s) {
-        stream = s;
-        fileLen = bufLen = bufStart = bufPos = 0;
-        buf = new byte[MIN_BUFFER_LENGTH];
-    }
-
-    public Buffer(String fileName) {
-        try {
-            file = new RandomAccessFile(fileName, "r");
-            fileLen = (int) file.length();
-            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
-            buf = new byte[bufLen];
-            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
-            if (fileLen > 0)
-                setPos(0); // setup buffer to position 0 (start)
-            else
-                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
-            if (bufLen == fileLen)
-                Close();
-        } catch (IOException e) {
-            throw new FatalError("Could not open file " + fileName);
-        }
-    }
-
-    // don't use b after this call anymore
-    // called in UTF8Buffer constructor
-    protected Buffer(Buffer b) {
-        buf = b.buf;
-        bufStart = b.bufStart;
-        bufLen = b.bufLen;
-        fileLen = b.fileLen;
-        bufPos = b.bufPos;
-        file = b.file;
-        stream = b.stream;
-        // keep finalize from closing the file
-        b.file = null;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        Close();
-    }
-
-    protected void Close() {
-        if (file != null) {
-            try {
-                file.close();
-                file = null;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        }
-    }
-
-    public int Read() {
-        if (bufPos < bufLen) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (getPos() < fileLen) {
-            setPos(getPos()); // shift buffer start to pos
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (stream != null && ReadNextStreamChunk() > 0) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else {
-            return EOF;
-        }
-    }
-
-    public int Peek() {
-        int curPos = getPos();
-        int ch = Read();
-        setPos(curPos);
-        return ch;
-    }
-
-    // beg .. begin, zero-based, inclusive, in byte
-    // end .. end, zero-based, exclusive, in byte
-    public String GetString(int beg, int end) {
-        int len = 0;
-        char[] buffer = new char[end - beg];
-        int oldPos = getPos();
-        setPos(beg);
-        while (getPos() < end)
-            buffer[len++] = (char) Read();
-        setPos(oldPos);
-        return new String(buffer, 0, len);
-    }
-
-    public int getPos() {
-        return bufPos + bufStart;
-    }
-
-    public void setPos(int value) {
-        if (value >= fileLen && stream != null) {
-            // Wanted position is after buffer and the stream
-            // is not seek-able e.g. network or console,
-            // thus we have to read the stream manually till
-            // the wanted position is in sight.
-            while (value >= fileLen && ReadNextStreamChunk() > 0) {
-                // nothing to do...
-            }
-        }
-
-        if (value < 0 || value > fileLen) {
-            throw new FatalError("buffer out of bounds access, position: " + value);
-        }
-
-        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
-            bufPos = value - bufStart;
-        } else if (file != null) { // must be swapped in
-            try {
-                file.seek(value);
-                bufLen = file.read(buf);
-                bufStart = value;
-                bufPos = 0;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        } else {
-            // set the position to the end of the file, Pos will return fileLen.
-            bufPos = fileLen - bufStart;
-        }
-    }
-
-    // Read the next chunk of bytes from the stream, increases the buffer
-    // if needed and updates the fields fileLen and bufLen.
-    // Returns the number of bytes read.
-    private int ReadNextStreamChunk() {
-        int free = buf.length - bufLen;
-        if (free == 0) {
-            // in the case of a growing input stream
-            // we can neither seek in the stream, nor can we
-            // foresee the maximum length, thus we must adapt
-            // the buffer size on demand.
-            byte[] newBuf = new byte[bufLen * 2];
-            System.arraycopy(buf, 0, newBuf, 0, bufLen);
-            buf = newBuf;
-            free = bufLen;
-        }
-
-        int read;
-        try {
-            read = stream.read(buf, bufLen, free);
-        } catch (IOException ioex) {
-            throw new FatalError(ioex.getMessage());
-        }
-
-        if (read > 0) {
-            fileLen = bufLen = (bufLen + read);
-            return read;
-        }
-        // end of stream reached
-        return 0;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// UTF8Buffer
-// -----------------------------------------------------------------------------------
-class UTF8Buffer extends Buffer {
-
-    UTF8Buffer(Buffer b) {
-        super(b);
-    }
-
-    @Override
-    public int Read() {
-        int ch;
-        do {
-            ch = super.Read();
-            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
-        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
-        if (ch < 128 || ch == EOF) {
-            // nothing to do, first 127 chars are the same in ascii and utf8
-            // 0xxxxxxx or end of file character
-        } else if ((ch & 0xF0) == 0xF0) {
-            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x07;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = super.Read();
-            int c4 = ch & 0x3F;
-            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
-        } else if ((ch & 0xE0) == 0xE0) {
-            // 1110xxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x0F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = (((c1 << 6) | c2) << 6) | c3;
-        } else if ((ch & 0xC0) == 0xC0) {
-            // 110xxxxx 10xxxxxx
-            int c1 = ch & 0x1F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = (c1 << 6) | c2;
-        }
-        return ch;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// StartStates -- maps characters to start states of tokens
-// -----------------------------------------------------------------------------------
-class StartStates {
-
-    private static class Elem {
-
-        public int key, val;
-        public Elem next;
-
-        public Elem(int key, int val) {
-            this.key = key;
-            this.val = val;
-        }
-    }
-
-    private Elem[] tab = new Elem[128];
-
-    public void set(int key, int val) {
-        Elem e = new Elem(key, val);
-        int k = key % 128;
-        e.next = tab[k];
-        tab[k] = e;
-    }
-
-    public int state(int key) {
-        Elem e = tab[key % 128];
-        while (e != null && e.key != key)
-            e = e.next;
-        return e == null ? 0 : e.val;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// Scanner
-// -----------------------------------------------------------------------------------
-@SuppressWarnings({"rawtypes"})
-public class Scanner {
-
-    static final char EOL = '\n';
-    static final int eofSym = 0;
--->declarations
-
-    public Buffer buffer; // scanner buffer
-
-    Token t; // current token
-    int ch; // current input character
-    int pos; // byte position of current character
-    int charPos; // position by unicode characters starting with 0
-    int col; // column number of current character
-    int line; // line number of current character
-    int oldEols; // EOLs that appeared in a comment;
-    static final StartStates start; // maps initial token character to start state
-    static final Map literals; // maps literal strings to literal kinds
-
-    Token tokens; // list of tokens already peeked (first token is a dummy)
-    Token pt; // current peek token
-
-    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
-    int tlen; // length of current token
-
-    static {
-        start = new StartStates();
-        literals = new HashMap();
--->initialization
-    }
-
-    public Scanner(String fileName) {
-        buffer = new Buffer(fileName);
-        Init();
-    }
-
-    public Scanner(InputStream s) {
-        buffer = new Buffer(s);
-        Init();
-    }
-
-    void Init() {
-        pos = -1;
-        line = 1;
-        col = 0;
-        charPos = -1;
-        oldEols = 0;
-        NextCh();
-        if (ch == 0xEF) { // check optional byte order mark for UTF-8
-            NextCh();
-            int ch1 = ch;
-            NextCh();
-            int ch2 = ch;
-            if (ch1 != 0xBB || ch2 != 0xBF) {
-                throw new FatalError("Illegal byte order mark at start of file");
-            }
-            buffer = new UTF8Buffer(buffer);
-            col = 0;
-            charPos = -1;
-            NextCh();
-        }
-        pt = tokens = new Token(); // first token is a dummy
-    }
-
-    void NextCh() {
-        if (oldEols > 0) {
-            ch = EOL;
-            oldEols--;
-        } else {
-            pos = buffer.getPos();
-            // buffer reads unicode chars, if UTF8 has been detected
-            ch = buffer.Read();
-            col++;
-            charPos++;
-            // replace isolated '\r' by '\n' in order to make
-            // eol handling uniform across Windows, Unix and Mac
-            if (ch == '\r' && buffer.Peek() != '\n')
-                ch = EOL;
-            if (ch == EOL) {
-                line++;
-                col = 0;
-            }
-        }
--->casing
-    }
-
-    void AddCh() {
-        if (tlen >= tval.length) {
-            char[] newBuf = new char[2 * tval.length];
-            System.arraycopy(tval, 0, newBuf, 0, tval.length);
-            tval = newBuf;
-        }
-        if (ch != Buffer.EOF) {
--->casing2
-            NextCh();
-        }
-    }
-
--->comments
-
-    void CheckLiteral() {
-        String val = t.val;
--->casing3
-        Object kind = literals.get(val);
-        if (kind != null) {
-            t.kind = ((Integer) kind).intValue();
-        }
-    }
-
-    Token NextToken() {
-        while (ch == ' ' || 
--->scan1
-        ) NextCh();
--->scan2
-        int recKind = noSym;
-        int recEnd = pos;
-        t = new Token();
-        t.pos = pos;
-        t.col = col;
-        t.line = line;
-        t.charPos = charPos;
-        int state = start.state(ch);
-        tlen = 0;
-        AddCh();
-
-        loop: for (;;) {
-            switch (state) {
-                case -1: {
-                    t.kind = eofSym;
-                    break loop;
-                } // NextCh already done
-                case 0: {
-                    if (recKind != noSym) {
-                        tlen = recEnd - t.pos;
-                        SetScannerBehindT();
-                    }
-                    t.kind = recKind;
-                    break loop;
-                } // NextCh already done
--->scan3
-            }
-        }
-        t.val = new String(tval, 0, tlen);
-        return t;
-    }
-
-    private void SetScannerBehindT() {
-        buffer.setPos(t.pos);
-        NextCh();
-        line = t.line;
-        col = t.col;
-        charPos = t.charPos;
-        for (int i = 0; i < tlen; i++)
-            NextCh();
-    }
-
-    // get the next token (possibly a token already seen during peeking)
-    public Token Scan() {
-        if (tokens.next == null) {
-            return NextToken();
-        } else {
-            pt = tokens = tokens.next;
-            return tokens;
-        }
-    }
-
-    // get the next token, ignore pragmas
-    public Token Peek() {
-        do {
-            if (pt.next == null) {
-                pt.next = NextToken();
-            }
-            pt = pt.next;
-        } while (pt.kind > maxT); // skip pragmas
-
-        return pt;
-    }
-
-    // make sure that peeking starts at current scan position
-    public void ResetPeek() {
-        pt = tokens;
-    }
-
-} // end Scanner
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,570 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 content of this file is automatically generated. DO NOT EDIT.
-
-package com.oracle.truffle.dsl.processor.expression;
-
-import java.io.*;
-import java.util.*;
-
-// Checkstyle: stop
-// @formatter:off
-class Token {
-
-    public int kind; // token kind
-    public int pos; // token position in bytes in the source text (starting at 0)
-    public int charPos; // token position in characters in the source text (starting at 0)
-    public int col; // token column (starting at 1)
-    public int line; // token line (starting at 1)
-    public String val; // token value
-    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
-}
-
-// -----------------------------------------------------------------------------------
-// Buffer
-// -----------------------------------------------------------------------------------
-class Buffer {
-
-    // This Buffer supports the following cases:
-    // 1) seekable stream (file)
-    // a) whole stream in buffer
-    // b) part of stream in buffer
-    // 2) non seekable stream (network, console)
-
-    public static final int EOF = Character.MAX_VALUE + 1;
-    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
-    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
-    private byte[] buf; // input buffer
-    private int bufStart; // position of first byte in buffer relative to input stream
-    private int bufLen; // length of buffer
-    private int fileLen; // length of input stream (may change if stream is no file)
-    private int bufPos; // current position in buffer
-    private RandomAccessFile file; // input stream (seekable)
-    private InputStream stream; // growing input stream (e.g.: console, network)
-
-    public Buffer(InputStream s) {
-        stream = s;
-        fileLen = bufLen = bufStart = bufPos = 0;
-        buf = new byte[MIN_BUFFER_LENGTH];
-    }
-
-    public Buffer(String fileName) {
-        try {
-            file = new RandomAccessFile(fileName, "r");
-            fileLen = (int) file.length();
-            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
-            buf = new byte[bufLen];
-            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
-            if (fileLen > 0)
-                setPos(0); // setup buffer to position 0 (start)
-            else
-                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
-            if (bufLen == fileLen)
-                Close();
-        } catch (IOException e) {
-            throw new FatalError("Could not open file " + fileName);
-        }
-    }
-
-    // don't use b after this call anymore
-    // called in UTF8Buffer constructor
-    protected Buffer(Buffer b) {
-        buf = b.buf;
-        bufStart = b.bufStart;
-        bufLen = b.bufLen;
-        fileLen = b.fileLen;
-        bufPos = b.bufPos;
-        file = b.file;
-        stream = b.stream;
-        // keep finalize from closing the file
-        b.file = null;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        Close();
-    }
-
-    protected void Close() {
-        if (file != null) {
-            try {
-                file.close();
-                file = null;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        }
-    }
-
-    public int Read() {
-        if (bufPos < bufLen) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (getPos() < fileLen) {
-            setPos(getPos()); // shift buffer start to pos
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (stream != null && ReadNextStreamChunk() > 0) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else {
-            return EOF;
-        }
-    }
-
-    public int Peek() {
-        int curPos = getPos();
-        int ch = Read();
-        setPos(curPos);
-        return ch;
-    }
-
-    // beg .. begin, zero-based, inclusive, in byte
-    // end .. end, zero-based, exclusive, in byte
-    public String GetString(int beg, int end) {
-        int len = 0;
-        char[] buffer = new char[end - beg];
-        int oldPos = getPos();
-        setPos(beg);
-        while (getPos() < end)
-            buffer[len++] = (char) Read();
-        setPos(oldPos);
-        return new String(buffer, 0, len);
-    }
-
-    public int getPos() {
-        return bufPos + bufStart;
-    }
-
-    public void setPos(int value) {
-        if (value >= fileLen && stream != null) {
-            // Wanted position is after buffer and the stream
-            // is not seek-able e.g. network or console,
-            // thus we have to read the stream manually till
-            // the wanted position is in sight.
-            while (value >= fileLen && ReadNextStreamChunk() > 0) {
-                // nothing to do...
-            }
-        }
-
-        if (value < 0 || value > fileLen) {
-            throw new FatalError("buffer out of bounds access, position: " + value);
-        }
-
-        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
-            bufPos = value - bufStart;
-        } else if (file != null) { // must be swapped in
-            try {
-                file.seek(value);
-                bufLen = file.read(buf);
-                bufStart = value;
-                bufPos = 0;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        } else {
-            // set the position to the end of the file, Pos will return fileLen.
-            bufPos = fileLen - bufStart;
-        }
-    }
-
-    // Read the next chunk of bytes from the stream, increases the buffer
-    // if needed and updates the fields fileLen and bufLen.
-    // Returns the number of bytes read.
-    private int ReadNextStreamChunk() {
-        int free = buf.length - bufLen;
-        if (free == 0) {
-            // in the case of a growing input stream
-            // we can neither seek in the stream, nor can we
-            // foresee the maximum length, thus we must adapt
-            // the buffer size on demand.
-            byte[] newBuf = new byte[bufLen * 2];
-            System.arraycopy(buf, 0, newBuf, 0, bufLen);
-            buf = newBuf;
-            free = bufLen;
-        }
-
-        int read;
-        try {
-            read = stream.read(buf, bufLen, free);
-        } catch (IOException ioex) {
-            throw new FatalError(ioex.getMessage());
-        }
-
-        if (read > 0) {
-            fileLen = bufLen = (bufLen + read);
-            return read;
-        }
-        // end of stream reached
-        return 0;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// UTF8Buffer
-// -----------------------------------------------------------------------------------
-class UTF8Buffer extends Buffer {
-
-    UTF8Buffer(Buffer b) {
-        super(b);
-    }
-
-    @Override
-    public int Read() {
-        int ch;
-        do {
-            ch = super.Read();
-            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
-        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
-        if (ch < 128 || ch == EOF) {
-            // nothing to do, first 127 chars are the same in ascii and utf8
-            // 0xxxxxxx or end of file character
-        } else if ((ch & 0xF0) == 0xF0) {
-            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x07;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = super.Read();
-            int c4 = ch & 0x3F;
-            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
-        } else if ((ch & 0xE0) == 0xE0) {
-            // 1110xxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x0F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = (((c1 << 6) | c2) << 6) | c3;
-        } else if ((ch & 0xC0) == 0xC0) {
-            // 110xxxxx 10xxxxxx
-            int c1 = ch & 0x1F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = (c1 << 6) | c2;
-        }
-        return ch;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// StartStates -- maps characters to start states of tokens
-// -----------------------------------------------------------------------------------
-class StartStates {
-
-    private static class Elem {
-
-        public int key, val;
-        public Elem next;
-
-        public Elem(int key, int val) {
-            this.key = key;
-            this.val = val;
-        }
-    }
-
-    private Elem[] tab = new Elem[128];
-
-    public void set(int key, int val) {
-        Elem e = new Elem(key, val);
-        int k = key % 128;
-        e.next = tab[k];
-        tab[k] = e;
-    }
-
-    public int state(int key) {
-        Elem e = tab[key % 128];
-        while (e != null && e.key != key)
-            e = e.next;
-        return e == null ? 0 : e.val;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// Scanner
-// -----------------------------------------------------------------------------------
-@SuppressWarnings({"rawtypes"})
-public class Scanner {
-
-    static final char EOL = '\n';
-    static final int eofSym = 0;
-	static final int maxT = 15;
-	static final int noSym = 15;
-
-
-    public Buffer buffer; // scanner buffer
-
-    Token t; // current token
-    int ch; // current input character
-    int pos; // byte position of current character
-    int charPos; // position by unicode characters starting with 0
-    int col; // column number of current character
-    int line; // line number of current character
-    int oldEols; // EOLs that appeared in a comment;
-    static final StartStates start; // maps initial token character to start state
-    static final Map literals; // maps literal strings to literal kinds
-
-    Token tokens; // list of tokens already peeked (first token is a dummy)
-    Token pt; // current peek token
-
-    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
-    int tlen; // length of current token
-
-    static {
-        start = new StartStates();
-        literals = new HashMap();
-		for (int i = 36; i <= 36; ++i) start.set(i, 1);
-		for (int i = 65; i <= 90; ++i) start.set(i, 1);
-		for (int i = 95; i <= 95; ++i) start.set(i, 1);
-		for (int i = 97; i <= 122; ++i) start.set(i, 1);
-		for (int i = 49; i <= 57; ++i) start.set(i, 6);
-		start.set(48, 2);
-		start.set(124, 7);
-		start.set(60, 18);
-		start.set(62, 19);
-		start.set(61, 11);
-		start.set(33, 20);
-		start.set(40, 14);
-		start.set(41, 15);
-		start.set(44, 16);
-		start.set(46, 17);
-		start.set(Buffer.EOF, -1);
-
-    }
-
-    public Scanner(String fileName) {
-        buffer = new Buffer(fileName);
-        Init();
-    }
-
-    public Scanner(InputStream s) {
-        buffer = new Buffer(s);
-        Init();
-    }
-
-    void Init() {
-        pos = -1;
-        line = 1;
-        col = 0;
-        charPos = -1;
-        oldEols = 0;
-        NextCh();
-        if (ch == 0xEF) { // check optional byte order mark for UTF-8
-            NextCh();
-            int ch1 = ch;
-            NextCh();
-            int ch2 = ch;
-            if (ch1 != 0xBB || ch2 != 0xBF) {
-                throw new FatalError("Illegal byte order mark at start of file");
-            }
-            buffer = new UTF8Buffer(buffer);
-            col = 0;
-            charPos = -1;
-            NextCh();
-        }
-        pt = tokens = new Token(); // first token is a dummy
-    }
-
-    void NextCh() {
-        if (oldEols > 0) {
-            ch = EOL;
-            oldEols--;
-        } else {
-            pos = buffer.getPos();
-            // buffer reads unicode chars, if UTF8 has been detected
-            ch = buffer.Read();
-            col++;
-            charPos++;
-            // replace isolated '\r' by '\n' in order to make
-            // eol handling uniform across Windows, Unix and Mac
-            if (ch == '\r' && buffer.Peek() != '\n')
-                ch = EOL;
-            if (ch == EOL) {
-                line++;
-                col = 0;
-            }
-        }
-
-    }
-
-    void AddCh() {
-        if (tlen >= tval.length) {
-            char[] newBuf = new char[2 * tval.length];
-            System.arraycopy(tval, 0, newBuf, 0, tval.length);
-            tval = newBuf;
-        }
-        if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch;
-
-            NextCh();
-        }
-    }
-
-
-
-    void CheckLiteral() {
-        String val = t.val;
-
-        Object kind = literals.get(val);
-        if (kind != null) {
-            t.kind = ((Integer) kind).intValue();
-        }
-    }
-
-    Token NextToken() {
-        while (ch == ' ' ||
-			false
-        ) NextCh();
-
-        int recKind = noSym;
-        int recEnd = pos;
-        t = new Token();
-        t.pos = pos;
-        t.col = col;
-        t.line = line;
-        t.charPos = charPos;
-        int state = start.state(ch);
-        tlen = 0;
-        AddCh();
-
-        loop: for (;;) {
-            switch (state) {
-                case -1: {
-                    t.kind = eofSym;
-                    break loop;
-                } // NextCh already done
-                case 0: {
-                    if (recKind != noSym) {
-                        tlen = recEnd - t.pos;
-                        SetScannerBehindT();
-                    }
-                    t.kind = recKind;
-                    break loop;
-                } // NextCh already done
-				case 1:
-					recEnd = pos; recKind = 1;
-					if (ch == '$' || ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else {t.kind = 1; break loop;}
-				case 2:
-					recEnd = pos; recKind = 2;
-					if (ch >= '0' && ch <= '7') {AddCh(); state = 5; break;}
-					else if (ch == 'x') {AddCh(); state = 3; break;}
-					else if (ch == 'b') {AddCh(); state = 4; break;}
-					else {t.kind = 2; break loop;}
-				case 3:
-					recEnd = pos; recKind = 2;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); state = 3; break;}
-					else {t.kind = 2; break loop;}
-				case 4:
-					recEnd = pos; recKind = 2;
-					if (ch >= '0' && ch <= '1') {AddCh(); state = 4; break;}
-					else {t.kind = 2; break loop;}
-				case 5:
-					recEnd = pos; recKind = 2;
-					if (ch >= '0' && ch <= '7') {AddCh(); state = 5; break;}
-					else {t.kind = 2; break loop;}
-				case 6:
-					recEnd = pos; recKind = 2;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 6; break;}
-					else {t.kind = 2; break loop;}
-				case 7:
-					if (ch == '|') {AddCh(); state = 8; break;}
-					else {state = 0; break;}
-				case 8:
-					{t.kind = 3; break loop;}
-				case 9:
-					{t.kind = 5; break loop;}
-				case 10:
-					{t.kind = 7; break loop;}
-				case 11:
-					if (ch == '=') {AddCh(); state = 12; break;}
-					else {state = 0; break;}
-				case 12:
-					{t.kind = 8; break loop;}
-				case 13:
-					{t.kind = 9; break loop;}
-				case 14:
-					{t.kind = 11; break loop;}
-				case 15:
-					{t.kind = 12; break loop;}
-				case 16:
-					{t.kind = 13; break loop;}
-				case 17:
-					{t.kind = 14; break loop;}
-				case 18:
-					recEnd = pos; recKind = 4;
-					if (ch == '=') {AddCh(); state = 9; break;}
-					else {t.kind = 4; break loop;}
-				case 19:
-					recEnd = pos; recKind = 6;
-					if (ch == '=') {AddCh(); state = 10; break;}
-					else {t.kind = 6; break loop;}
-				case 20:
-					recEnd = pos; recKind = 10;
-					if (ch == '=') {AddCh(); state = 13; break;}
-					else {t.kind = 10; break loop;}
-
-            }
-        }
-        t.val = new String(tval, 0, tlen);
-        return t;
-    }
-
-    private void SetScannerBehindT() {
-        buffer.setPos(t.pos);
-        NextCh();
-        line = t.line;
-        col = t.col;
-        charPos = t.charPos;
-        for (int i = 0; i < tlen; i++)
-            NextCh();
-    }
-
-    // get the next token (possibly a token already seen during peeking)
-    public Token Scan() {
-        if (tokens.next == null) {
-            return NextToken();
-        } else {
-            pt = tokens = tokens.next;
-            return tokens;
-        }
-    }
-
-    // get the next token, ignore pragmas
-    public Token Peek() {
-        do {
-            if (pt.next == null) {
-                pt.next = NextToken();
-            }
-            pt = pt.next;
-        } while (pt.kind > maxT); // skip pragmas
-
-        return pt;
-    }
-
-    // make sure that peeking starts at current scan position
-    public void ResetPeek() {
-        pt = tokens;
-    }
-
-} // end Scanner
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public abstract class CodeTypeElementFactory<M> {
-
-    public abstract CodeTypeElement create(ProcessorContext context, M m);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public class DSLExpressionGenerator implements DSLExpressionVisitor {
-
-    private final Map<Variable, CodeTree> bindings;
-    private final CodeTree root;
-    private final Deque<CodeTree> stack = new ArrayDeque<>();
-
-    public DSLExpressionGenerator(CodeTree root, Map<Variable, CodeTree> bindings) {
-        this.bindings = bindings;
-        this.root = root;
-    }
-
-    public void visitBinary(Binary binary) {
-        CodeTree right = stack.pop();
-        CodeTree left = stack.pop();
-        stack.push(combine(left, string(" " + binary.getOperator() + " "), right));
-    }
-
-    public void visitCall(Call call) {
-        ExecutableElement method = call.getResolvedMethod();
-        CodeTree[] parameters = new CodeTree[method.getParameters().size()];
-        for (int i = 0; i < parameters.length; i++) {
-            parameters[parameters.length - i - 1] = pop();
-        }
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        if (call.getResolvedMethod().getKind() == ElementKind.CONSTRUCTOR) {
-            builder.startNew(call.getResolvedType());
-        } else if (call.getReceiver() == null) {
-            if (isStatic(method)) {
-                builder.startStaticCall(method);
-            } else {
-                if (root != null) {
-                    builder.tree(root).string(".");
-                }
-                builder.startCall(method.getSimpleName().toString());
-            }
-        } else {
-            if (isStatic(method)) {
-                throw new AssertionError("Static calls must not have receivers.");
-            }
-            builder.startCall(pop(), method.getSimpleName().toString());
-        }
-        for (CodeTree parameter : parameters) {
-            builder.tree(parameter);
-        }
-        builder.end();
-
-        push(builder.build());
-    }
-
-    public void visitIntLiteral(IntLiteral binary) {
-        push(string(binary.getLiteral()));
-    }
-
-    public void visitNegate(Negate negate) {
-        push(combine(string("!"), combine(string("("), pop(), string(")"))));
-    }
-
-    public void visitVariable(Variable variable) {
-        VariableElement resolvedVariable = variable.getResolvedVariable();
-        CodeTree tree;
-        if (variable.getResolvedType().getKind() == TypeKind.NULL) {
-            tree = CodeTreeBuilder.singleString("null");
-        } else if (variable.getReceiver() == null) {
-
-            if (isStatic(resolvedVariable)) {
-                tree = staticReference(resolvedVariable);
-            } else {
-                tree = bindings.get(variable);
-                boolean bound = true;
-                if (tree == null) {
-                    tree = string(resolvedVariable.getSimpleName().toString());
-                    bound = false;
-                }
-                if (root != null && !bound) {
-                    tree = combine(root, string("."), tree);
-                }
-            }
-        } else {
-            if (isStatic(resolvedVariable)) {
-                throw new AssertionError("Static variables cannot have receivers.");
-            }
-            tree = combine(pop(), string("."), string(resolvedVariable.getSimpleName().toString()));
-        }
-        push(tree);
-    }
-
-    private static boolean isStatic(Element element) {
-        return element.getModifiers().contains(Modifier.STATIC);
-    }
-
-    private static CodeTree combine(CodeTree tree1, CodeTree tree2) {
-        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).end().build();
-    }
-
-    private static CodeTree combine(CodeTree tree1, CodeTree tree2, CodeTree tree3) {
-        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).tree(tree3).end().build();
-    }
-
-    private static CodeTree string(String s) {
-        return CodeTreeBuilder.singleString(s);
-    }
-
-    private static CodeTree staticReference(VariableElement var) {
-        return CodeTreeBuilder.createBuilder().staticReference(var.getEnclosingElement().asType(), var.getSimpleName().toString()).build();
-    }
-
-    private void push(CodeTree tree) {
-        stack.push(tree);
-    }
-
-    private CodeTree pop() {
-        return stack.pop();
-    }
-
-    public static CodeTree write(DSLExpression expression, CodeTree root, Map<Variable, CodeTree> bindings) {
-        DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings);
-        expression.accept(writer);
-        return combine(string("("), writer.pop(), string(")"));
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.DSLOptions.TypeBoxingOptimization;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class GeneratorUtils {
-
-    public static CodeTree createTransferToInterpreterAndInvalidate() {
-        ProcessorContext context = ProcessorContext.getInstance();
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startStatement().startStaticCall(context.getType(CompilerDirectives.class), "transferToInterpreterAndInvalidate").end().end();
-        return builder.build();
-    }
-
-    public static CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
-        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
-        ExecutableElement constructor = findConstructor(superClass);
-        return createConstructorUsingFields(modifiers, clazz, constructor);
-    }
-
-    public static CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz, ExecutableElement constructor) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
-        CodeTreeBuilder builder = method.createBuilder();
-        if (constructor != null && constructor.getParameters().size() > 0) {
-            builder.startStatement();
-            builder.startSuperCall();
-            for (VariableElement parameter : constructor.getParameters()) {
-                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
-                builder.string(parameter.getSimpleName().toString());
-            }
-            builder.end(); // super
-            builder.end(); // statement
-        }
-
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(STATIC)) {
-                continue;
-            }
-            String fieldName = field.getSimpleName().toString();
-            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
-            builder.startStatement();
-            builder.string("this.");
-            builder.string(fieldName);
-            builder.string(" = ");
-            builder.string(fieldName);
-            builder.end(); // statement
-        }
-
-        return method;
-    }
-
-    public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeMirror type) {
-        switch (boxing) {
-            case NONE:
-                return false;
-            case ALWAYS:
-                return !ElementUtils.isObject(type) && !ElementUtils.isVoid(type);
-            case PRIMITIVE:
-                return ElementUtils.isPrimitive(type);
-            default:
-                throw new AssertionError();
-        }
-    }
-
-    private static ExecutableElement findConstructor(TypeElement clazz) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
-        if (constructors.isEmpty()) {
-            return null;
-        } else {
-            return constructors.get(0);
-        }
-    }
-
-    public static CodeExecutableElement createSuperConstructor(ProcessorContext context, TypeElement type, ExecutableElement element) {
-        if (element.getModifiers().contains(Modifier.PRIVATE)) {
-            return null;
-        }
-        CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), element);
-        executable.setReturnType(null);
-        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
-        CodeTreeBuilder b = executable.createBuilder();
-        b.startStatement();
-        b.startSuperCall();
-        for (VariableElement v : element.getParameters()) {
-            b.string(v.getSimpleName().toString());
-        }
-        b.end();
-        b.end();
-
-        return executable;
-    }
-
-    public static CodeTypeElement createClass(Template sourceModel, TemplateMethod sourceMethod, Set<Modifier> modifiers, String simpleName, TypeMirror superType) {
-        TypeElement templateType = sourceModel.getTemplateType();
-
-        ProcessorContext context = ProcessorContext.getInstance();
-
-        PackageElement pack = context.getEnvironment().getElementUtils().getPackageOf(templateType);
-        CodeTypeElement clazz = new CodeTypeElement(modifiers, ElementKind.CLASS, pack, simpleName);
-        TypeMirror resolvedSuperType = superType;
-        if (resolvedSuperType == null) {
-            resolvedSuperType = context.getType(Object.class);
-        }
-        clazz.setSuperClass(resolvedSuperType);
-
-        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) context.getType(GeneratedBy.class));
-        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
-        if (sourceMethod != null && sourceMethod.getMethod() != null) {
-            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(sourceMethod.createReferenceName()));
-        }
-
-        clazz.addAnnotationMirror(generatedByAnnotation);
-        return clazz;
-    }
-
-    public static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
-        List<ExecutableElement> constructors = new ArrayList<>();
-        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) {
-            if (constructor.getModifiers().contains(PRIVATE)) {
-                continue;
-            }
-            if (isCopyConstructor(constructor)) {
-                continue;
-            }
-            constructors.add(constructor);
-        }
-
-        if (constructors.isEmpty()) {
-            constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType)));
-        }
-
-        return constructors;
-    }
-
-    public static boolean isCopyConstructor(ExecutableElement element) {
-        if (element.getParameters().size() != 1) {
-            return false;
-        }
-        VariableElement var = element.getParameters().get(0);
-        TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var);
-        if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) {
-            return true;
-        }
-        List<TypeElement> types = ElementUtils.getDirectSuperTypes(enclosingType);
-        for (TypeElement type : types) {
-            if (!(type instanceof CodeTypeElement)) {
-                // no copy constructors which are not generated types
-                return false;
-            }
-
-            if (ElementUtils.typeEquals(var.asType(), type.asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class ImplicitCastNodeFactory {
-
-    private final ProcessorContext context;
-    private final TypeMirror forType;
-    private final TypeSystemData typeSystem;
-    private final DSLOptions options;
-    private final List<TypeMirror> sourceTypes;
-
-    public ImplicitCastNodeFactory(ProcessorContext context, TypeSystemData typeSystem, TypeMirror forType) {
-        this.context = context;
-        this.forType = forType;
-        this.typeSystem = typeSystem;
-        this.options = typeSystem.getOptions();
-        this.sourceTypes = typeSystem.lookupSourceTypes(forType);
-    }
-
-    public static String typeName(TypeMirror type) {
-        return "Implicit" + getTypeId(type) + "Cast";
-    }
-
-    public static TypeMirror type(TypeSystemData typeSystem, TypeMirror type) {
-        String typeSystemName = TypeSystemCodeGenerator.typeName(typeSystem);
-        return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()) + "." + typeSystemName, typeName(type));
-    }
-
-    public static CodeTree create(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
-        return CodeTreeBuilder.createBuilder().startStaticCall(type(typeSystem, type), "create").tree(value).end().build();
-    }
-
-    public static CodeTree cast(String nodeName, CodeTree value) {
-        return CodeTreeBuilder.createBuilder().startCall(nodeName, "cast").tree(value).end().build();
-    }
-
-    public static CodeTree check(String nodeName, CodeTree value) {
-        return CodeTreeBuilder.createBuilder().startCall(nodeName, "check").tree(value).end().build();
-    }
-
-    private static String seenFieldName(TypeMirror type) {
-        return "seen" + getTypeId(type);
-    }
-
-    public CodeTypeElement create() {
-        String typeName = typeName(forType);
-        TypeMirror baseType = context.getType(Object.class);
-        CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL, STATIC), typeName, baseType);
-
-        for (TypeMirror sourceType : sourceTypes) {
-            CodeVariableElement hasSeen = new CodeVariableElement(modifiers(PUBLIC), context.getType(boolean.class), seenFieldName(sourceType));
-            hasSeen.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
-            clazz.add(hasSeen);
-        }
-
-        clazz.add(createConstructor(clazz));
-        if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), forType)) {
-            clazz.add(createIsMonomorphic());
-        }
-        clazz.add(createCast(false));
-        clazz.add(createCast(true));
-        clazz.add(createCheck());
-        clazz.add(createMerge(clazz));
-        clazz.add(createCreate(clazz));
-
-        return clazz;
-    }
-
-    private Element createIsMonomorphic() {
-        String methodName = "isMonomorphic";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName);
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startReturn();
-        String operator = "";
-        for (TypeMirror sourceType : sourceTypes) {
-            builder.string(operator);
-            builder.string(seenFieldName(sourceType));
-            operator = " ^ ";
-        }
-        builder.end();
-        return method;
-    }
-
-    private static Element createConstructor(CodeTypeElement clazz) {
-        return new CodeExecutableElement(modifiers(PRIVATE), null, clazz.getSimpleName().toString());
-    }
-
-    private Element createCreate(CodeTypeElement clazz) {
-        String methodName = "create";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), clazz.asType(), methodName);
-        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
-        CodeTreeBuilder builder = method.createBuilder();
-
-        builder.declaration(clazz.asType(), "newCast", builder.create().startNew(clazz.asType()).end());
-
-        for (TypeMirror sourceType : sourceTypes) {
-            String seenField = seenFieldName(sourceType);
-            builder.startStatement();
-            builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
-            builder.end();
-        }
-        builder.startReturn().string("newCast").end();
-        return method;
-    }
-
-    private Element createMerge(CodeTypeElement clazz) {
-        String methodName = "merge";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), methodName);
-        method.addParameter(new CodeVariableElement(clazz.asType(), "otherCast"));
-        CodeTreeBuilder builder = method.createBuilder();
-
-        for (TypeMirror sourceType : sourceTypes) {
-            String seenField = seenFieldName(sourceType);
-            builder.startStatement();
-            builder.string("this.").string(seenField).string(" |= ").string("otherCast.").string(seenField);
-            builder.end();
-        }
-        return method;
-    }
-
-    private Element createCheck() {
-        String methodName = "check";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName);
-        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
-        CodeTreeBuilder builder = method.createBuilder();
-
-        boolean elseIf = false;
-        for (TypeMirror sourceType : sourceTypes) {
-            elseIf = builder.startIf(elseIf);
-            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
-            builder.end();
-            builder.startBlock().returnTrue().end();
-        }
-        builder.returnFalse();
-        return method;
-    }
-
-    private Element createCast(boolean expect) {
-        String methodName = expect ? "expect" : "cast";
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType, methodName);
-        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
-        if (expect) {
-            method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
-        }
-
-        CodeTreeBuilder builder = method.createBuilder();
-
-        boolean elseIf = false;
-        for (TypeMirror sourceType : sourceTypes) {
-            elseIf = builder.startIf(elseIf);
-            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
-            builder.end();
-            builder.startBlock();
-            builder.startReturn();
-            CodeTree castTree = TypeSystemCodeGenerator.cast(typeSystem, sourceType, "value");
-            ImplicitCastData cast = typeSystem.lookupCast(sourceType, forType);
-            if (cast != null) {
-                builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(typeSystem, cast, castTree));
-            } else {
-                builder.tree(castTree);
-            }
-            builder.end();
-            builder.end();
-        }
-        if (expect) {
-            builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string("value").end().end();
-        } else {
-            builder.startStatement().startStaticCall(context.getType(CompilerDirectives.class), "transferToInterpreter").end().end();
-            builder.startThrow().startNew(context.getType(AssertionError.class)).end().end();
-        }
-        return method;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
-
-    @Override
-    public CodeTypeElement create(ProcessorContext context, NodeData node) {
-        List<CodeTypeElement> enclosedTypes = new ArrayList<>();
-        for (NodeData childNode : node.getEnclosingNodes()) {
-            CodeTypeElement type = create(context, childNode);
-            if (type != null) {
-                enclosedTypes.add(type);
-            }
-        }
-        List<CodeTypeElement> generatedNodes = generateNodes(context, node);
-
-        if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
-            CodeTypeElement type;
-            if (generatedNodes.isEmpty()) {
-                type = createContainer(node);
-            } else {
-                type = wrapGeneratedNodes(context, node, generatedNodes);
-            }
-
-            for (CodeTypeElement enclosedFactory : enclosedTypes) {
-                type.add(makeInnerClass(enclosedFactory));
-            }
-
-            if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) {
-                ExecutableElement getFactories = createGetFactories(context, node);
-                if (getFactories != null) {
-                    type.add(getFactories);
-                }
-            }
-
-            return type;
-        } else {
-            return null;
-        }
-    }
-
-    private static CodeTypeElement makeInnerClass(CodeTypeElement type) {
-        Set<Modifier> modifiers = type.getModifiers();
-        modifiers.add(Modifier.STATIC);
-        return type;
-    }
-
-    private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
-        if (node.isGenerateFactory()) {
-            // wrap all types into a generated factory
-            CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.get(0)).create();
-            for (CodeTypeElement generatedNode : generatedNodes) {
-                factoryElement.add(makeInnerClass(generatedNode));
-            }
-            return factoryElement;
-        } else {
-            // wrap all types into the first node
-            CodeTypeElement first = generatedNodes.get(0);
-            CodeTypeElement second = first;
-            if (generatedNodes.size() > 1) {
-                second = generatedNodes.get(1);
-                for (CodeTypeElement generatedNode : generatedNodes) {
-                    if (first != generatedNode) {
-                        first.add(makeInnerClass(generatedNode));
-                    }
-                }
-            }
-            new NodeFactoryFactory(context, node, second).createFactoryMethods(first);
-            ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
-
-            return first;
-        }
-    }
-
-    private static CodeTypeElement createContainer(NodeData node) {
-        CodeTypeElement container;
-        Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
-        String containerName = NodeFactoryFactory.factoryClassName(node);
-        container = GeneratorUtils.createClass(node, null, modifiers(), containerName, null);
-        if (visibility != null) {
-            container.getModifiers().add(visibility);
-        }
-        container.getModifiers().add(Modifier.FINAL);
-
-        return container;
-    }
-
-    private static String getAccessorClassName(NodeData node) {
-        return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeGenFactory.nodeTypeName(node);
-    }
-
-    private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
-        if (!node.needsFactory()) {
-            return Collections.emptyList();
-        }
-        return Arrays.asList(new NodeGenFactory(context, node).create());
-    }
-
-    private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) {
-        List<NodeData> factoryList = node.getNodesWithFactories();
-        if (node.needsFactory() && node.isGenerateFactory()) {
-            factoryList.add(node);
-        }
-
-        if (factoryList.isEmpty()) {
-            return null;
-        }
-
-        List<TypeMirror> nodeTypesList = new ArrayList<>();
-        TypeMirror prev = null;
-        boolean allSame = true;
-        for (NodeData child : factoryList) {
-            nodeTypesList.add(child.getNodeType());
-            if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
-                allSame = false;
-            }
-            prev = child.getNodeType();
-        }
-        TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList);
-
-        Types types = context.getEnvironment().getTypeUtils();
-        TypeMirror factoryType = context.getType(NodeFactory.class);
-        TypeMirror baseType;
-        if (allSame) {
-            baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
-        } else {
-            baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
-        }
-        TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType);
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
-
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startReturn();
-
-        if (factoryList.size() > 1) {
-            builder.startStaticCall(context.getType(Arrays.class), "asList");
-        } else {
-            builder.startStaticCall(context.getType(Collections.class), "singletonList");
-        }
-
-        for (NodeData child : factoryList) {
-            builder.startGroup();
-            NodeData childNode = child;
-            List<NodeData> factories = new ArrayList<>();
-            while (childNode.getDeclaringNode() != null) {
-                factories.add(childNode);
-                childNode = childNode.getDeclaringNode();
-            }
-            Collections.reverse(factories);
-            for (NodeData nodeData : factories) {
-
-                builder.string(getAccessorClassName(nodeData)).string(".");
-            }
-            builder.string("getInstance()");
-            builder.end();
-        }
-        builder.end();
-        builder.end();
-
-        return method;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,260 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.model.*;
-
-class NodeFactoryFactory {
-
-    static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
-
-    private final ProcessorContext context;
-    private final NodeData node;
-    private final CodeTypeElement createdFactoryElement;
-
-    public NodeFactoryFactory(ProcessorContext context, NodeData node, CodeTypeElement createdClass) {
-        this.context = context;
-        this.node = node;
-        this.createdFactoryElement = createdClass;
-    }
-
-    public static String factoryClassName(NodeData node) {
-        return node.getNodeId() + "Factory";
-    }
-
-    public CodeTypeElement create() {
-        Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
-        TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
-
-        CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(), factoryClassName(node), null);
-        if (visibility != null) {
-            clazz.getModifiers().add(visibility);
-        }
-        clazz.getModifiers().add(Modifier.FINAL);
-
-        if (createdFactoryElement != null) {
-            clazz.setSuperClass(nodeFactory);
-            clazz.add(createNodeFactoryConstructor());
-            clazz.add(createCreateNodeMethod());
-            clazz.add(createGetInstanceMethod(visibility));
-            clazz.add(createInstanceConstant(clazz.asType()));
-            createFactoryMethods(clazz);
-        }
-
-        return clazz;
-    }
-
-    private Element createNodeFactoryConstructor() {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startStatement();
-        builder.startCall("super");
-
-        // node type
-        builder.typeLiteral(node.getNodeType());
-
-        // execution signature
-        builder.startGroup();
-        if (node.getChildExecutions().isEmpty()) {
-            builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-        } else {
-            builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
-            for (NodeExecutionData execution : node.getChildExecutions()) {
-                builder.typeLiteral(execution.getNodeType());
-            }
-            builder.end();
-        }
-        builder.end();
-
-        // node signatures
-        builder.startGroup();
-        builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
-        List<ExecutableElement> constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
-        for (ExecutableElement constructor : constructors) {
-            builder.startGroup();
-            if (constructor.getParameters().isEmpty()) {
-                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
-            } else {
-                builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
-                for (VariableElement var : constructor.getParameters()) {
-                    builder.typeLiteral(var.asType());
-                }
-                builder.end();
-            }
-            builder.end();
-        }
-        builder.end();
-        builder.end();
-
-        builder.end().end().end();
-        return method;
-    }
-
-    private CodeExecutableElement createCreateNodeMethod() {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
-        CodeVariableElement arguments = new CodeVariableElement(context.getType(Object.class), "arguments");
-        method.setVarArgs(true);
-        method.addParameter(arguments);
-
-        CodeTreeBuilder builder = method.createBuilder();
-        List<ExecutableElement> signatures = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
-        boolean ifStarted = false;
-
-        for (ExecutableElement element : signatures) {
-            ifStarted = builder.startIf(ifStarted);
-            builder.string("arguments.length == " + element.getParameters().size());
-
-            int index = 0;
-            for (VariableElement param : element.getParameters()) {
-                if (ElementUtils.isObject(param.asType())) {
-                    continue;
-                }
-                builder.string(" && ");
-                if (!param.asType().getKind().isPrimitive()) {
-                    builder.string("(arguments[" + index + "] == null || ");
-                }
-                builder.string("arguments[" + index + "] instanceof ");
-                builder.type(ElementUtils.boxType(context, param.asType()));
-                if (!param.asType().getKind().isPrimitive()) {
-                    builder.string(")");
-                }
-                index++;
-            }
-            builder.end();
-            builder.startBlock();
-
-            builder.startReturn().startCall("create");
-            index = 0;
-            for (VariableElement param : element.getParameters()) {
-                builder.startGroup();
-                if (!ElementUtils.isObject(param.asType())) {
-                    builder.string("(").type(param.asType()).string(") ");
-                }
-                builder.string("arguments[").string(String.valueOf(index)).string("]");
-                builder.end();
-                index++;
-            }
-            builder.end().end();
-
-            builder.end(); // block
-        }
-
-        builder.startElseBlock();
-        builder.startThrow().startNew(context.getType(IllegalArgumentException.class));
-        builder.doubleQuote("Invalid create signature.");
-        builder.end().end();
-        builder.end(); // else block
-        return method;
-    }
-
-    private ExecutableElement createGetInstanceMethod(Modifier visibility) {
-        TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(context.getType(NodeFactory.class));
-        TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType());
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
-        if (visibility != null) {
-            method.getModifiers().add(visibility);
-        }
-        method.getModifiers().add(Modifier.STATIC);
-
-        String varName = instanceVarName(node);
-
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startIf();
-        builder.string(varName).string(" == null");
-        builder.end().startBlock();
-
-        builder.startStatement();
-        builder.string(varName);
-        builder.string(" = ");
-        builder.startNew(factoryClassName(node)).end();
-        builder.end();
-
-        builder.end();
-        builder.startReturn().string(varName).end();
-        return method;
-    }
-
-    private static String instanceVarName(NodeData node) {
-        if (node.getDeclaringNode() != null) {
-            return ElementUtils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
-        } else {
-            return "instance";
-        }
-    }
-
-    private CodeVariableElement createInstanceConstant(TypeMirror factoryType) {
-        String varName = instanceVarName(node);
-        CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
-        var.getModifiers().add(Modifier.PRIVATE);
-        var.getModifiers().add(Modifier.STATIC);
-        return var;
-    }
-
-    public void createFactoryMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
-        for (ExecutableElement constructor : constructors) {
-            clazz.add(createCreateMethod(constructor));
-            if (constructor instanceof CodeExecutableElement) {
-                ElementUtils.setVisibility(constructor.getModifiers(), Modifier.PRIVATE);
-            }
-        }
-    }
-
-    private CodeExecutableElement createCreateMethod(ExecutableElement constructor) {
-        CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), constructor);
-        method.setSimpleName(CodeNames.of("create"));
-        method.getModifiers().clear();
-        method.getModifiers().add(Modifier.PUBLIC);
-        method.getModifiers().add(Modifier.STATIC);
-        method.setReturnType(node.getNodeType());
-
-        CodeTreeBuilder body = method.createBuilder();
-        body.startReturn();
-        if (node.getSpecializations().isEmpty()) {
-            body.nullLiteral();
-        } else {
-            body.startNew(NodeGenFactory.nodeType(node));
-            for (VariableElement var : method.getParameters()) {
-                body.string(var.getSimpleName().toString());
-            }
-            body.end();
-
-        }
-        body.end();
-        return method;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3044 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.dsl.internal.DSLOptions.ImplicitCastOptimization;
-import com.oracle.truffle.api.dsl.internal.DSLOptions.TypeBoxingOptimization;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.parser.*;
-import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard;
-
-public class NodeGenFactory {
-
-    private static final String FRAME_VALUE = TemplateMethod.FRAME_NAME;
-    private static final String NAME_SUFFIX = "_";
-    private static final String NODE_SUFFIX = "NodeGen";
-
-    private final ProcessorContext context;
-    private final NodeData node;
-    private final TypeSystemData typeSystem;
-    private final TypeMirror genericType;
-    private final DSLOptions options;
-    private final boolean singleSpecializable;
-    private final int varArgsThreshold;
-    private final Set<TypeMirror> expectedTypes = new HashSet<>();
-    private final Set<NodeExecutionData> usedExecuteChildMethods = new HashSet<>();
-    private boolean nextUsed;
-    private boolean singleSpecializableUnsupportedUsed;
-
-    private List<ExecutableTypeData> usedTypes;
-    private List<SpecializationData> reachableSpecializations;
-
-    public NodeGenFactory(ProcessorContext context, NodeData node) {
-        this.context = context;
-        this.node = node;
-        this.typeSystem = node.getTypeSystem();
-        this.genericType = context.getType(Object.class);
-        this.options = typeSystem.getOptions();
-        this.varArgsThreshold = calculateVarArgsThreshold();
-        this.reachableSpecializations = calculateReachableSpecializations();
-        this.singleSpecializable = isSingleSpecializableImpl();
-        this.usedTypes = filterBaseExecutableTypes(node.getExecutableTypes(), reachableSpecializations);
-    }
-
-    private int calculateVarArgsThreshold() {
-        TypeMirror specialization = context.getType(SpecializationNode.class);
-        TypeElement specializationType = fromTypeMirror(specialization);
-
-        int maxParameters = 0;
-        for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) {
-            if (element.getSimpleName().contentEquals("acceptAndExecute")) {
-                maxParameters = Math.max(maxParameters, element.getParameters().size());
-            }
-        }
-        return maxParameters;
-    }
-
-    public static String nodeTypeName(NodeData node) {
-        return resolveNodeId(node) + NODE_SUFFIX;
-    }
-
-    private static String assumptionName(AssumptionExpression assumption) {
-        return assumption.getId() + NAME_SUFFIX;
-    }
-
-    private static String resolveNodeId(NodeData node) {
-        String nodeid = node.getNodeId();
-        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
-            nodeid = nodeid.substring(0, nodeid.length() - 4);
-        }
-        return nodeid;
-    }
-
-    public static TypeMirror nodeType(NodeData node) {
-        return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), nodeTypeName(node));
-    }
-
-    private static String specializationTypeName(SpecializationData specialization) {
-        String id;
-        if (specialization == null) {
-            id = "Base";
-        } else {
-            id = specialization.getId();
-        }
-        return id + "Node_";
-    }
-
-    private TypeMirror specializationType(SpecializationData specialization) {
-        return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()) + "." + nodeTypeName(node), specializationTypeName(specialization));
-    }
-
-    private static String polymorphicTypeProfileFieldName(NodeExecutionData execution) {
-        return execution.getName() + "Type" + NAME_SUFFIX;
-    }
-
-    private static String nodeFieldName(NodeExecutionData execution) {
-        return execution.getName() + NAME_SUFFIX;
-    }
-
-    private static String specializationStartFieldName() {
-        return "specialization" + NAME_SUFFIX;
-    }
-
-    private static String excludedFieldName(SpecializationData specialization) {
-        return "exclude" + specialization.getId() + NAME_SUFFIX;
-    }
-
-    private static String executeChildMethodName(NodeExecutionData execution, TypeMirror type) {
-        return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (ElementUtils.isObject(type) ? "" : getTypeId(type)) + NAME_SUFFIX;
-    }
-
-    private CodeTree accessParent(String name) {
-        if (singleSpecializable) {
-            if (name == null) {
-                return CodeTreeBuilder.singleString("this");
-            } else {
-                return CodeTreeBuilder.singleString(name);
-            }
-        } else {
-            if (name == null) {
-                return CodeTreeBuilder.singleString("root");
-            } else {
-                return CodeTreeBuilder.createBuilder().string("root.").string(name).build();
-            }
-        }
-    }
-
-    public CodeTypeElement create() {
-        CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType());
-        ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
-
-        for (NodeChildData child : node.getChildren()) {
-            clazz.addOptional(createAccessChildMethod(child));
-        }
-
-        for (NodeFieldData field : node.getFields()) {
-            if (!field.isGenerated()) {
-                continue;
-            }
-
-            clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), field.getType(), field.getName()));
-            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
-                CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), field.getGetter());
-                method.getModifiers().remove(Modifier.ABSTRACT);
-                method.createBuilder().startReturn().string("this.").string(field.getName()).end();
-                clazz.add(method);
-            }
-        }
-
-        for (ExecutableElement superConstructor : GeneratorUtils.findUserConstructors(node.getTemplateType().asType())) {
-            clazz.add(createNodeConstructor(clazz, superConstructor));
-        }
-
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.getChild() != null) {
-                clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
-            }
-        }
-
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (!resolvePolymorphicExecutables(execution).isEmpty()) {
-                clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class));
-            }
-        }
-
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (mayBeExcluded(specialization)) {
-                clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class));
-            }
-        }
-
-        clazz.add(createGetCostMethod());
-
-        avoidFindbugsProblems(clazz);
-
-        if (singleSpecializable) {
-            SpecializationData specialization = reachableSpecializations.iterator().next();
-
-            for (ExecutableTypeData execType : usedTypes) {
-                if (execType.getMethod() == null) {
-                    boolean foundDelegate = false;
-                    for (ExecutableTypeData type : usedTypes) {
-                        if (type == execType) {
-                            continue;
-                        }
-                        if (findFastPathDelegate(specialization.getReturnType().getType(), type, usedTypes) == execType) {
-                            foundDelegate = true;
-                            break;
-                        }
-                    }
-                    // just exclude synthetic execute methods that were not delegated to
-                    if (!foundDelegate) {
-                        continue;
-                    }
-                }
-
-                clazz.add(createExecutableTypeOverride(usedTypes, execType));
-            }
-
-            if (singleSpecializableUnsupportedUsed) {
-                addUnsupportedMethod(clazz);
-            }
-        } else {
-
-            for (ExecutableTypeData execType : usedTypes) {
-                if (execType.getMethod() == null) {
-                    continue;
-                }
-                clazz.add(createExecutableTypeOverride(usedTypes, execType));
-            }
-
-            clazz.getImplements().add(getType(SpecializedNode.class));
-            clazz.add(createMethodGetSpecializationNode());
-            clazz.add(createDeepCopyMethod());
-            SpecializationData specializationStart = createSpecializations(clazz);
-            clazz.add(createNodeField(PRIVATE, specializationType(null), specializationStartFieldName(), Child.class));
-
-            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
-                CodeTreeBuilder builder = ((CodeExecutableElement) constructor).appendBuilder();
-                builder.startStatement();
-                builder.string("this.").string(specializationStartFieldName());
-                builder.string(" = ").tree(createCallCreateMethod(specializationStart, "this", null));
-                builder.end();
-            }
-        }
-
-        for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes, false)) {
-            if (!typeSystem.hasType(type)) {
-                clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type));
-            }
-        }
-
-        return clazz;
-    }
-
-    private void avoidFindbugsProblems(CodeTypeElement clazz) {
-        TypeElement type = context.getEnvironment().getElementUtils().getTypeElement("edu.umd.cs.findbugs.annotations.SuppressFBWarnings");
-        if (type == null) {
-            return;
-        }
-        boolean foundComparison = false;
-        outer: for (SpecializationData specialization : node.getSpecializations()) {
-            for (GuardExpression guard : specialization.getGuards()) {
-                if (guard.getExpression().containsComparisons()) {
-                    foundComparison = true;
-                    break outer;
-                }
-            }
-        }
-
-        if (foundComparison) {
-            CodeAnnotationMirror annotation = new CodeAnnotationMirror((DeclaredType) type.asType());
-            annotation.setElementValue(annotation.findExecutableElement("value"), new CodeAnnotationValue("SA_LOCAL_SELF_COMPARISON"));
-            clazz.addAnnotationMirror(annotation);
-        }
-    }
-
-    private void addUnsupportedMethod(CodeTypeElement clazz) {
-        CodeVariableElement seenUnsupportedField = new CodeVariableElement(modifiers(PRIVATE), getType(boolean.class), "seenUnsupported0");
-        seenUnsupportedField.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
-        clazz.add(seenUnsupportedField);
-        LocalContext locals = LocalContext.load(this);
-        CodeExecutableElement method = locals.createMethod(modifiers(PRIVATE), getType(UnsupportedSpecializationException.class), "unsupported", varArgsThreshold);
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startIf().string("!").string(seenUnsupportedField.getName()).end().startBlock();
-        builder.startStatement().startStaticCall(getType(CompilerDirectives.class), "transferToInterpreterAndInvalidate").end().end();
-        builder.startStatement().string(seenUnsupportedField.getName()).string(" = true").end();
-        builder.end();
-
-        builder.startReturn();
-        builder.startNew(getType(UnsupportedSpecializationException.class));
-        builder.string("this");
-        builder.tree(createGetSuppliedChildren());
-        locals.addReferencesTo(builder);
-        builder.end();
-        builder.end();
-        clazz.add(method);
-    }
-
-    private CodeExecutableElement createNodeConstructor(CodeTypeElement clazz, ExecutableElement superConstructor) {
-        CodeExecutableElement constructor = GeneratorUtils.createConstructorUsingFields(modifiers(), clazz, superConstructor);
-        ElementUtils.setVisibility(constructor.getModifiers(), ElementUtils.getVisibility(superConstructor.getModifiers()));
-
-        List<CodeVariableElement> childParameters = new ArrayList<>();
-        for (NodeChildData child : node.getChildren()) {
-            childParameters.add(new CodeVariableElement(child.getOriginalType(), child.getName()));
-        }
-        constructor.getParameters().addAll(superConstructor.getParameters().size(), childParameters);
-
-        CodeTreeBuilder builder = constructor.appendBuilder();
-        List<String> childValues = new ArrayList<>(node.getChildren().size());
-        for (NodeChildData child : node.getChildren()) {
-            String name = child.getName();
-            if (child.getCardinality().isMany()) {
-                CreateCastData createCast = node.findCast(child.getName());
-                if (createCast != null) {
-                    CodeTree nameTree = CodeTreeBuilder.singleString(name);
-                    CodeTreeBuilder callBuilder = builder.create();
-                    callBuilder.string(name).string(" != null ? ");
-                    callBuilder.tree(callMethod(null, createCast.getMethod(), nameTree));
-                    callBuilder.string(" : null");
-                    name += "_";
-                    builder.declaration(child.getNodeType(), name, callBuilder.build());
-                }
-            }
-            childValues.add(name);
-        }
-
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.getChild() == null) {
-                continue;
-            }
-            CreateCastData createCast = node.findCast(execution.getChild().getName());
-
-            builder.startStatement();
-            builder.string("this.").string(nodeFieldName(execution)).string(" = ");
-
-            String name = childValues.get(node.getChildren().indexOf(execution.getChild()));
-            CodeTreeBuilder accessorBuilder = builder.create();
-            accessorBuilder.string(name);
-
-            if (execution.isIndexed()) {
-                accessorBuilder.string("[").string(String.valueOf(execution.getChildIndex())).string("]");
-            }
-
-            CodeTree accessor = accessorBuilder.build();
-
-            if (createCast != null && execution.getChild().getCardinality().isOne()) {
-                accessor = callMethod(null, createCast.getMethod(), accessor);
-            }
-
-            if (execution.isIndexed()) {
-                CodeTreeBuilder nullCheck = builder.create();
-                nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getChildIndex())).string(" < ").string(name).string(".length").string(" ? ");
-                nullCheck.tree(accessor);
-                nullCheck.string(" : null");
-                accessor = nullCheck.build();
-            }
-
-            builder.tree(accessor);
-
-            builder.end();
-        }
-
-        return constructor;
-    }
-
-    private static boolean mayBeExcluded(SpecializationData specialization) {
-        return !specialization.getExceptions().isEmpty() || !specialization.getExcludedBy().isEmpty();
-    }
-
-    private SpecializationData createSpecializations(CodeTypeElement clazz) {
-        CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization());
-        TypeMirror baseSpecializationType = baseSpecialization.asType();
-
-        Map<SpecializationData, CodeTypeElement> generated = new LinkedHashMap<>();
-
-        List<SpecializationData> generateSpecializations = new ArrayList<>();
-        generateSpecializations.add(node.getUninitializedSpecialization());
-        if (needsPolymorphic()) {
-            generateSpecializations.add(node.getPolymorphicSpecialization());
-        }
-        generateSpecializations.addAll(reachableSpecializations);
-
-        for (SpecializationData specialization : generateSpecializations) {
-            generated.put(specialization, clazz.add(createSpecialization(specialization, baseSpecializationType)));
-        }
-
-        baseSpecialization.addOptional(createCreateNext(generated));
-        baseSpecialization.addOptional(createCreateFallback(generated));
-        baseSpecialization.addOptional(createCreatePolymorphic(generated));
-        baseSpecialization.addOptional(createGetNext(baseSpecialization));
-
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution);
-            specializedTypes.add(genericType);
-            for (TypeMirror specializedType : specializedTypes) {
-                if (isExecuteChildShared(execution, specializedType)) {
-                    baseSpecialization.addOptional(createExecuteChildMethod(execution, specializedType));
-                }
-            }
-        }
-
-        return node.getUninitializedSpecialization();
-    }
-
-    private boolean needsPolymorphic() {
-        int signatureSize = node.getSignatureSize();
-        boolean allEvaluated = true;
-        for (ExecutableTypeData type : usedTypes) {
-            if (type.getEvaluatedCount() != signatureSize) {
-                allEvaluated = false;
-            }
-        }
-        if (allEvaluated) {
-            return false;
-        }
-
-        if (reachableSpecializations.size() != 1) {
-            return true;
-        }
-
-        SpecializationData specialization = reachableSpecializations.get(0);
-        for (Parameter parameter : specialization.getSignatureParameters()) {
-            TypeMirror type = parameter.getType();
-            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
-                return true;
-            }
-        }
-        if (specialization.hasMultipleInstances()) {
-            return true;
-        }
-        return false;
-
-    }
-
-    // create specialization
-
-    private CodeTypeElement createBaseSpecialization() {
-        CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), specializationTypeName(null), typeSystem.getContext().getType(SpecializationNode.class));
-
-        clazz.addOptional(createSpecializationConstructor(clazz, null, null));
-        clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root"));
-
-        clazz.addOptional(createUnsupported());
-        clazz.add(createGetSuppliedChildrenMethod());
-        clazz.add(createAcceptAndExecute());
-
-        for (ExecutableTypeData type : usedTypes) {
-            clazz.add(createFastPathExecuteMethod(null, type, usedTypes));
-        }
-
-        return clazz;
-    }
-
-    private Element createAcceptAndExecute() {
-        ExecutableTypeData executableElement = createSpecializationNodeSignature(node.getSignatureSize());
-        LocalContext currentLocals = LocalContext.load(this, executableElement, varArgsThreshold);
-        CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false, varArgsThreshold);
-
-        executable.getModifiers().add(FINAL);
-        CodeTreeBuilder builder = executable.createBuilder();
-
-        CodeTree receiver = CodeTreeBuilder.singleString("this");
-
-        builder.tree(createCallDelegateExecute(builder, receiver, currentLocals, executableElement, node.getGenericExecutableType(null)));
-
-        return executable;
-    }
-
-    private ExecutableTypeData createSpecializationNodeSignature(int argumentCount) {
-        TypeMirror[] parameters = new TypeMirror[argumentCount];
-        Arrays.fill(parameters, genericType);
-        return new ExecutableTypeData(node, genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters));
-    }
-
-    private boolean shouldImplementExecutableType(SpecializationData specialization, ExecutableTypeData executableType) {
-        // always implement the root execute method. they are declared abstract in the base node.
-        if (executableType.getDelegatedTo() == null) {
-            return true;
-        }
-
-        // specializations with more parameters are just ignored
-        if (executableType.getEvaluatedCount() > node.getExecutionCount()) {
-            return false;
-        }
-
-        if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) {
-            return false;
-        }
-
-        // the evaluated signature might be compatible to the specialization
-        boolean specializationCompatible = true;
-        List<TypeMirror> signatureParameters = executableType.getSignatureParameters();
-        for (int i = 0; i < signatureParameters.size(); i++) {
-            TypeMirror evaluatedType = signatureParameters.get(i);
-            TypeMirror specializedType = specialization.findParameterOrDie(node.getChildExecutions().get(i)).getType();
-
-            if (!isSubtypeBoxed(context, evaluatedType, specializedType) && !isSubtypeBoxed(context, specializedType, evaluatedType)) {
-                specializationCompatible = false;
-                break;
-            }
-        }
-        if (!specializationCompatible) {
-            return false;
-        }
-
-        // possibly trigger void optimization for a specialization if it is enabled
-        if (isVoid(executableType.getReturnType())) {
-            if (isTypeBoxingOptimized(options.voidBoxingOptimization(), specialization.getReturnType().getType())) {
-                return true;
-            }
-        }
-
-        // trigger type boxing elimination for unevaluated arguments
-        for (int i = executableType.getEvaluatedCount(); i < node.getExecutionCount(); i++) {
-            NodeExecutionData execution = node.getChildExecutions().get(i);
-            TypeMirror specializedType = specialization.findParameterOrDie(execution).getType();
-            if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), specializedType)) {
-                // it does not make sense to do type boxing elimination for children with
-                // no type specialized execute method
-                if (execution.getChild() != null) {
-                    ExecutableTypeData executedType = execution.getChild().findExecutableType(specializedType);
-                    if (executedType != null) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        // trigger type boxing elimination for return types
-        if (typeEquals(executableType.getReturnType(), specialization.getReturnType().getType())) {
-            if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), executableType.getReturnType())) {
-                return true;
-            }
-        }
-
-        // trigger generation for evaluated assignable type matches other than generic
-        for (int i = 0; i < signatureParameters.size(); i++) {
-            TypeMirror evaluatedType = signatureParameters.get(i);
-            NodeExecutionData execution = node.getChildExecutions().get(i);
-            TypeMirror specializedType = specialization.findParameterOrDie(execution).getType();
-
-            if (isSubtypeBoxed(context, evaluatedType, specializedType) && !isObject(specializedType)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private List<ExecutableTypeData> filterBaseExecutableTypes(List<ExecutableTypeData> executableTypes, List<SpecializationData> specializations) {
-        Set<TypeMirror> returnTypes = new HashSet<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            returnTypes.add(specialization.getReturnType().getType());
-        }
-
-        List<ExecutableTypeData> prefilteredTypes = new ArrayList<>();
-        for (ExecutableTypeData type : executableTypes) {
-            if (type.getDelegatedTo() == null || shouldAlwaysImplementExecutableType(type)) {
-                prefilteredTypes.add(type);
-            } else {
-                boolean foundSubtype = false;
-                for (TypeMirror returnType : returnTypes) {
-                    if (isSubtypeBoxed(context, returnType, type.getReturnType())) {
-                        foundSubtype = true;
-                    }
-                }
-                if (foundSubtype) {
-                    prefilteredTypes.add(type);
-                }
-            }
-        }
-
-        Set<ExecutableTypeData> types = new HashSet<>();
-        type: for (ExecutableTypeData type : prefilteredTypes) {
-            for (SpecializationData specialization : specializations) {
-                if (shouldImplementExecutableType(specialization, type) || shouldAlwaysImplementExecutableType(type)) {
-                    types.add(type);
-                    continue type;
-                }
-            }
-        }
-        Set<ExecutableTypeData> delegatesToAdd = new HashSet<>();
-        do {
-            delegatesToAdd.clear();
-            for (ExecutableTypeData type : types) {
-                ExecutableTypeData delegate = type.getDelegatedTo();
-                if (delegate != null && !types.contains(delegate)) {
-                    delegatesToAdd.add(delegate);
-                }
-            }
-            types.addAll(delegatesToAdd);
-        } while (!delegatesToAdd.isEmpty());
-        List<ExecutableTypeData> newUsedTypes = new ArrayList<>(types);
-        Collections.sort(newUsedTypes);
-        return newUsedTypes;
-    }
-
-    private boolean shouldAlwaysImplementExecutableType(ExecutableTypeData type) {
-        return type.isAbstract() || !(type.hasUnexpectedValue(context) && type.getMethod() != null);
-    }
-
-    private CodeTypeElement createSpecialization(SpecializationData specialization, TypeMirror baseType) {
-        CodeTypeElement clazz = createClass(node, specialization, modifiers(PRIVATE, STATIC, FINAL), specializationTypeName(specialization), baseType);
-
-        CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, specialization, null));
-
-        for (Parameter p : specialization.getSignatureParameters()) {
-            TypeMirror targetType = p.getType();
-            if (typeSystem.hasImplicitSourceTypes(targetType)) {
-                NodeExecutionData execution = p.getSpecification().getExecution();
-                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
-                if (implicitProfile != null) {
-                    implicitProfile.getModifiers().add(PRIVATE);
-                    implicitProfile.getModifiers().add(FINAL);
-                    clazz.add(implicitProfile);
-                }
-            }
-        }
-
-        if (specialization.isFallback()) {
-            clazz.add(createFallbackGuardMethod());
-        }
-
-        clazz.addOptional(createSpecializationCreateMethod(specialization, constructor));
-        clazz.addOptional(createMergeMethod(specialization));
-        clazz.addOptional(createIsSameMethod(specialization));
-        clazz.addOptional(createIsIdenticalMethod(specialization));
-
-        // get types that should get implemented
-        List<ExecutableTypeData> types = new ArrayList<>();
-        for (ExecutableTypeData type : node.getExecutableTypes()) {
-            if (shouldImplementExecutableType(specialization, type)) {
-                types.add(type);
-            }
-        }
-        for (ExecutableTypeData type : types) {
-            clazz.add(createFastPathExecuteMethod(specialization, type, types));
-        }
-
-        return clazz;
-    }
-
-    public static List<Parameter> getDynamicParameters(TemplateMethod method) {
-        List<Parameter> parameters = new ArrayList<>();
-        for (Parameter param : method.getReturnTypeAndParameters()) {
-            if (param.getSpecification().isLocal()) {
-                // ignore parameters passed by locals
-                continue;
-            } else if (param.getVariableElement() != null && param.getVariableElement().getAnnotation(Cached.class) != null) {
-                // ignore cached parameters
-                continue;
-            }
-            parameters.add(param);
-        }
-        return parameters;
-    }
-
-    private Element createDeepCopyMethod() {
-        if (singleSpecializable) {
-            return null;
-        }
-        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), getType(Node.class), "deepCopy");
-        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        CodeTreeBuilder builder = executable.createBuilder();
-        builder.startReturn().startStaticCall(getType(SpecializationNode.class), "updateRoot").string("super.deepCopy()").end().end();
-        return executable;
-    }
-
-    private Element createGetCostMethod() {
-        TypeMirror returnType = getType(NodeCost.class);
-        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
-        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        CodeTreeBuilder builder = executable.createBuilder();
-        if (singleSpecializable) {
-            builder.startReturn().staticReference(getType(NodeCost.class), "MONOMORPHIC").end().end();
-        } else {
-            builder.startReturn().startCall(specializationStartFieldName(), "getNodeCost").end().end();
-        }
-        return executable;
-
-    }
-
-    private Element createIsIdenticalMethod(SpecializationData specialization) {
-        boolean cacheBoundGuard = specialization.hasMultipleInstances();
-        if (!cacheBoundGuard) {
-            return null;
-        }
-
-        LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold);
-        currentLocals.loadFastPathState(specialization);
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical");
-        method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other"));
-        currentLocals.addParametersTo(method, varArgsThreshold, FRAME_VALUE);
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        final CodeTreeBuilder builder = method.createBuilder();
-
-        SpecializationGroup group = SpecializationGroup.create(specialization);
-        SpecializationBody executionFactory = new SpecializationBody(true, false) {
-            @Override
-            public CodeTree createBody(SpecializationData s, LocalContext values) {
-                return builder.create().returnTrue().build();
-            }
-        };
-
-        builder.tree(createGuardAndCast(group, genericType, currentLocals, executionFactory));
-        builder.returnFalse();
-        return method;
-    }
-
-    private CodeExecutableElement createIsSameMethod(SpecializationData specialization) {
-        if (!specialization.isSpecialized() || !options.implicitCastOptimization().isDuplicateTail()) {
-            return null;
-        }
-
-        List<CodeVariableElement> profiles = new ArrayList<>();
-        for (Parameter parameter : specialization.getSignatureParameters()) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null) {
-                continue;
-            }
-            CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getType());
-            if (var != null) {
-                profiles.add(var);
-            }
-        }
-
-        if (profiles.isEmpty()) {
-            return null;
-        }
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isSame");
-        method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other"));
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        CodeTreeBuilder builder = method.createBuilder();
-
-        builder.startReturn();
-        builder.string("super.isSame(other)");
-
-        for (CodeVariableElement profile : profiles) {
-            builder.string(" && ");
-            builder.string("this.").string(profile.getName()).string(" == ").string("(").cast(specializationType(specialization)).string("other).").string(profile.getName());
-        }
-
-        builder.end();
-        return method;
-    }
-
-    private Element createMergeMethod(SpecializationData specialization) {
-        if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) {
-            return null;
-        }
-        TypeMirror specializationNodeType = getType(SpecializationNode.class);
-        LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold);
-
-        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge");
-        executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode"));
-        currentLocals.addParametersTo(executable, varArgsThreshold, FRAME_VALUE);
-        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        CodeTreeBuilder builder = executable.createBuilder();
-
-        if (specialization.isPolymorphic()) {
-            builder.startReturn();
-            builder.startCall("polymorphicMerge");
-            builder.string("newNode");
-            builder.startCall("super", "merge");
-            builder.string("newNode");
-            currentLocals.addReferencesTo(builder, FRAME_VALUE);
-            builder.end();
-            builder.end();
-            builder.end();
-
-        } else {
-            boolean elseIf = false;
-            for (SpecializationData containedSpecialization : specialization.getExcludedBy()) {
-                elseIf = builder.startIf(elseIf);
-                builder.string("newNode.getClass() == ").typeLiteral(specializationType(containedSpecialization));
-                builder.end();
-                builder.startBlock();
-                builder.statement("removeSame(\"Contained by " + containedSpecialization.createReferenceName() + "\")");
-                builder.end();
-            }
-            builder.startReturn();
-            builder.startCall("super", "merge");
-            builder.string("newNode");
-            currentLocals.addReferencesTo(builder, FRAME_VALUE);
-            builder.end();
-            builder.end();
-        }
-
-        return executable;
-    }
-
-    private Element createCreateFallback(Map<SpecializationData, CodeTypeElement> generatedSpecializationClasses) {
-        SpecializationData fallback = node.getGenericSpecialization();
-        if (fallback == null) {
-            return null;
-        }
-        CodeTypeElement generatedType = generatedSpecializationClasses.get(fallback);
-        if (generatedType == null) {
-            return null;
-        }
-
-        TypeMirror returnType = getType(SpecializationNode.class);
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, "createFallback");
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        method.createBuilder().startReturn().tree(createCallCreateMethod(fallback, null, null)).end();
-        return method;
-    }
-
-    private Element createCreatePolymorphic(Map<SpecializationData, CodeTypeElement> generatedSpecializationClasses) {
-        SpecializationData polymorphic = node.getPolymorphicSpecialization();
-        CodeTypeElement generatedPolymorphic = generatedSpecializationClasses.get(polymorphic);
-        if (generatedPolymorphic == null) {
-            return null;
-        }
-        TypeMirror returnType = getType(SpecializationNode.class);
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, "createPolymorphic");
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        method.createBuilder().startReturn().tree(createCallCreateMethod(polymorphic, null, null)).end();
-        return method;
-    }
-
-    private CodeExecutableElement createCreateNext(final Map<SpecializationData, CodeTypeElement> specializationClasses) {
-        final LocalContext locals = LocalContext.load(this);
-
-        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", varArgsThreshold, FRAME_VALUE);
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-
-        CodeTreeBuilder builder = method.createBuilder();
-        SpecializationGroup group = createSpecializationGroups();
-        CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationBody(false, false) {
-            @Override
-            public CodeTree createBody(SpecializationData specialization, LocalContext values) {
-                CodeTypeElement generatedType = specializationClasses.get(specialization);
-                if (generatedType == null) {
-                    throw new AssertionError("No generated type for " + specialization);
-                }
-                return createSlowPathExecute(specialization, values);
-            }
-        });
-
-        builder.tree(execution);
-
-        if (hasFallthrough(group, genericType, locals, false, null)) {
-            builder.returnNull();
-        }
-        return method;
-    }
-
-    private CodeExecutableElement createFallbackGuardMethod() {
-        boolean frameUsed = node.isFrameUsedByAnyGuard();
-        LocalContext locals = LocalContext.load(this);
-
-        if (!frameUsed) {
-            locals.removeValue(FRAME_VALUE);
-        }
-
-        CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", varArgsThreshold, FRAME_VALUE);
-        if (!frameUsed) {
-            boundaryMethod.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(TruffleBoundary.class)));
-        }
-
-        CodeTreeBuilder builder = boundaryMethod.createBuilder();
-        builder.startReturn();
-        builder.startCall("createNext");
-        locals.addReferencesTo(builder, FRAME_VALUE);
-        builder.end();
-        builder.string(" == null");
-        builder.end();
-        return boundaryMethod;
-    }
-
-    private ExecutableElement createAccessChildMethod(NodeChildData child) {
-        if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
-            ExecutableElement getter = (ExecutableElement) child.getAccessElement();
-            CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), getter);
-            method.getModifiers().remove(Modifier.ABSTRACT);
-
-            List<NodeExecutionData> executions = new ArrayList<>();
-            for (NodeExecutionData execution : node.getChildExecutions()) {
-                if (execution.getChild() == child) {
-                    executions.add(execution);
-                }
-            }
-
-            CodeTreeBuilder builder = method.createBuilder();
-            if (child.getCardinality().isMany()) {
-                builder.startReturn().startNewArray((ArrayType) child.getOriginalType(), null);
-                for (NodeExecutionData execution : executions) {
-                    builder.string(nodeFieldName(execution));
-                }
-                builder.end().end();
-            } else {
-                for (NodeExecutionData execution : executions) {
-                    builder.startReturn().string("this.").string(nodeFieldName(execution)).end();
-                    break;
-                }
-            }
-            return method;
-        }
-        return null;
-    }
-
-    private Element createUnsupported() {
-        SpecializationData fallback = node.getGenericSpecialization();
-        if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) {
-            return null;
-        }
-        LocalContext locals = LocalContext.load(this);
-
-        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", varArgsThreshold, FRAME_VALUE);
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startReturn();
-        builder.tree(callTemplateMethod(accessParent(null), fallback, locals));
-        builder.end();
-
-        return method;
-    }
-
-    private boolean isSingleSpecializableImpl() {
-        if (reachableSpecializations.size() != 1) {
-            return false;
-        }
-
-        SpecializationData specialization = reachableSpecializations.get(0);
-
-        for (Parameter parameter : specialization.getSignatureParameters()) {
-            TypeMirror type = parameter.getType();
-            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
-                return false;
-            }
-        }
-
-        if (!specialization.getAssumptionExpressions().isEmpty()) {
-            return false;
-        }
-
-        if (specialization.getCaches().size() > 0) {
-            // TODO chumer: caches do not yet support single specialization.
-            // it could be worthwhile to explore if this is possible
-            return false;
-        }
-        return true;
-    }
-
-    private List<SpecializationData> calculateReachableSpecializations() {
-        List<SpecializationData> specializations = new ArrayList<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.isReachable() && //
-                            (specialization.isSpecialized() //
-                            || (specialization.isFallback() && optimizeFallback(specialization)))) {
-                specializations.add(specialization);
-            }
-        }
-        return specializations;
-    }
-
-    private boolean optimizeFallback(SpecializationData specialization) {
-        switch (options.optimizeFallback()) {
-            case NEVER:
-                return false;
-            case DECLARED:
-                return specialization.getMethod() != null;
-            case ALWAYS:
-                return true;
-            default:
-                throw new AssertionError();
-        }
-    }
-
-    private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> usedExecutables, ExecutableTypeData execType) {
-        LocalContext locals = LocalContext.load(this, execType, Integer.MAX_VALUE);
-        CodeExecutableElement method = createExecuteMethod(null, execType, locals, true, Integer.MAX_VALUE);
-
-        CodeTreeBuilder builder = method.createBuilder();
-        if (singleSpecializable) {
-            SpecializationData specialization = reachableSpecializations.iterator().next();
-            builder.tree(createFastPath(builder, specialization, execType, usedExecutables, locals));
-        } else {
-            // create acceptAndExecute
-            ExecutableTypeData delegate = execType;
-            CodeTree receiver = CodeTreeBuilder.singleString(specializationStartFieldName());
-            builder.tree(createCallDelegateExecute(builder, receiver, locals, execType, delegate));
-        }
-        return method;
-    }
-
-    private Element createMethodGetSpecializationNode() {
-        TypeMirror returntype = getType(SpecializationNode.class);
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returntype, "getSpecializationNode");
-        method.createBuilder().startReturn().string(specializationStartFieldName()).end();
-        return method;
-    }
-
-    private TypeMirror getType(Class<?> clazz) {
-        return context.getType(clazz);
-    }
-
-    private CodeVariableElement createNodeField(Modifier visibility, TypeMirror type, String name, Class<?> annotationType) {
-        CodeVariableElement childField = new CodeVariableElement(modifiers(), type, name);
-        childField.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(annotationType)));
-        setVisibility(childField.getModifiers(), visibility);
-        return childField;
-    }
-
-    private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeMirror> types, TypeBoxingOptimization optimization) {
-        if (optimization == TypeBoxingOptimization.NONE) {
-            return Collections.emptyList();
-        } else if (types.isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<ExecutableTypeData> executables = new ArrayList<>();
-        for (TypeMirror type : types) {
-            if (!isTypeBoxingOptimized(optimization, type)) {
-                continue;
-            }
-            if (execution.getChild() == null) {
-                continue;
-            }
-            ExecutableTypeData foundType = execution.getChild().getNodeData().findExecutableType(type, execution.getChild().getExecuteWith().size());
-            if (foundType != null) {
-                executables.add(foundType);
-            }
-        }
-        return executables;
-    }
-
-    private static CodeTree callMethod(CodeTree receiver, ExecutableElement method, CodeTree... boundValues) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (method.getModifiers().contains(STATIC)) {
-            builder.startStaticCall(method.getEnclosingElement().asType(), method.getSimpleName().toString());
-        } else {
-            builder.startCall(receiver, method.getSimpleName().toString());
-        }
-        int index = -1;
-        for (VariableElement parameter : method.getParameters()) {
-            index++;
-            if (index < boundValues.length) {
-                CodeTree tree = boundValues[index];
-                if (tree != null) {
-                    builder.tree(tree);
-                    continue;
-                }
-            }
-
-            builder.defaultValue(parameter.asType());
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    private CodeTree[] bindExecuteMethodParameters(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) {
-        List<NodeExecutionData> executeWith = execution != null ? execution.getChild().getExecuteWith() : null;
-
-        List<CodeTree> values = new ArrayList<>();
-        if (method.getFrameParameter() != null) {
-            LocalVariable frameLocal = currentValues.get(FRAME_VALUE);
-            if (frameLocal == null) {
-                values.add(CodeTreeBuilder.singleString("null"));
-            } else {
-                values.add(createTypeSafeReference(frameLocal, method.getFrameParameter()));
-            }
-        }
-
-        int evaluatedIndex = 0;
-        for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) {
-            NodeExecutionData parameterExecution;
-            if (executeWith != null && executionIndex < executeWith.size()) {
-                parameterExecution = executeWith.get(executionIndex);
-            } else {
-                parameterExecution = node.getChildExecutions().get(executionIndex);
-            }
-            if (parameterExecution.isShortCircuit()) {
-                if (evaluatedIndex < method.getEvaluatedCount()) {
-                    TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex);
-                    LocalVariable shortCircuit = currentValues.getShortCircuit(parameterExecution);
-                    if (shortCircuit != null) {
-                        values.add(createTypeSafeReference(shortCircuit, targetType));
-                    } else {
-                        values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build());
-                    }
-                    evaluatedIndex++;
-                }
-            }
-            if (evaluatedIndex < method.getEvaluatedCount()) {
-                TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex);
-                LocalVariable value = currentValues.getValue(parameterExecution);
-                if (value != null) {
-                    values.add(createTypeSafeReference(value, targetType));
-                } else {
-                    values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build());
-                }
-                evaluatedIndex++;
-            }
-        }
-        return values.toArray(new CodeTree[values.size()]);
-    }
-
-    private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) {
-        CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null;
-        return callMethod(receiver, method.getMethod(), bindExecuteMethodParameters(execution, method, currentValues));
-    }
-
-    private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
-        CodeTree[] bindings = new CodeTree[method.getParameters().size()];
-
-        int signatureIndex = 0;
-        for (int i = 0; i < bindings.length; i++) {
-            Parameter parameter = method.getParameters().get(i);
-
-            LocalVariable var = currentValues.get(parameter, signatureIndex);
-            if (var == null) {
-                var = currentValues.get(parameter.getLocalName());
-            }
-
-            if (var != null) {
-                bindings[i] = createTypeSafeReference(var, parameter.getType());
-            }
-
-            if (parameter.getSpecification().isSignature()) {
-                signatureIndex++;
-            }
-        }
-        return callMethod(receiver, method.getMethod(), bindings);
-    }
-
-    private CodeTree createTypeSafeReference(LocalVariable var, TypeMirror targetType) {
-        CodeTree valueReference = var.createReference();
-        TypeMirror sourceType = var.getTypeMirror();
-        if (targetType == null || sourceType == null) {
-            return valueReference;
-        }
-        if (needsCastTo(sourceType, targetType)) {
-            valueReference = TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference);
-        }
-        return valueReference;
-    }
-
-    private SpecializationGroup createSpecializationGroups() {
-        return SpecializationGroup.create(reachableSpecializations);
-    }
-
-    private CodeTree createSlowPathExecute(SpecializationData specialization, LocalContext currentValues) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (specialization.isFallback()) {
-            return builder.returnNull().build();
-        }
-
-        if (node.isFrameUsedByAnyGuard()) {
-            builder.tree(createTransferToInterpreterAndInvalidate());
-        }
-
-        // caches unbound to guards are invoked after all guards
-        for (CacheExpression cache : specialization.getCaches()) {
-            if (!specialization.isCacheBoundByGuard(cache)) {
-                initializeCache(builder, specialization, cache, currentValues);
-            }
-        }
-        boolean hasAssumptions = !specialization.getAssumptionExpressions().isEmpty();
-        if (hasAssumptions) {
-
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                CodeTree assumptions = DSLExpressionGenerator.write(assumption.getExpression(), accessParent(null),
-                                castBoundTypes(bindExpressionValues(assumption.getExpression(), specialization, currentValues)));
-                String name = assumptionName(assumption);
-                // needs specialization index for assumption to make unique
-                String varName = name + specialization.getIndex();
-                TypeMirror type = assumption.getExpression().getResolvedType();
-                builder.declaration(type, varName, assumptions);
-                currentValues.set(name, new LocalVariable(type, varName, null, null));
-            }
-
-            builder.startIf();
-            String sep = "";
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
-                if (assumptionVar == null) {
-                    throw new AssertionError("assumption var not resolved");
-                }
-                builder.string(sep);
-                builder.startCall("isValid").tree(assumptionVar.createReference()).end();
-                sep = " && ";
-            }
-            builder.end();
-            builder.startBlock();
-        }
-
-        for (SpecializationData otherSpeciailzation : node.getSpecializations()) {
-            if (otherSpeciailzation == specialization) {
-                continue;
-            }
-            if (otherSpeciailzation.getExcludedBy().contains(specialization)) {
-                builder.startStatement();
-                builder.tree(accessParent(excludedFieldName(otherSpeciailzation)));
-                builder.string(" = true");
-                builder.end();
-            }
-        }
-
-        CodeTree create = createCallCreateMethod(specialization, null, currentValues);
-
-        if (specialization.hasMultipleInstances()) {
-            builder.declaration(getType(SpecializationNode.class), "s", create);
-            DSLExpression limitExpression = specialization.getLimitExpression();
-            CodeTree limitExpressionTree;
-            if (limitExpression == null) {
-                limitExpressionTree = CodeTreeBuilder.singleString("3");
-            } else {
-                limitExpressionTree = DSLExpressionGenerator.write(limitExpression, accessParent(null), //
-                                castBoundTypes(bindExpressionValues(limitExpression, specialization, currentValues)));
-            }
-
-            builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock();
-            builder.statement("return s");
-            builder.end();
-        } else {
-            builder.startReturn().tree(create).end();
-        }
-
-        if (hasAssumptions) {
-            builder.end();
-        }
-
-        if (mayBeExcluded(specialization)) {
-            CodeTreeBuilder checkHasSeenBuilder = builder.create();
-            checkHasSeenBuilder.startIf().string("!").tree(accessParent(excludedFieldName(specialization))).end().startBlock();
-            checkHasSeenBuilder.tree(builder.build());
-            checkHasSeenBuilder.end();
-            return checkHasSeenBuilder.build();
-        }
-        return builder.build();
-    }
-
-    private boolean hasFallthrough(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) {
-        for (TypeGuard guard : group.getTypeGuards()) {
-            if (currentValues.getValue(guard.getSignatureIndex()) == null) {
-                // not evaluated
-                return true;
-            }
-            LocalVariable value = currentValues.getValue(guard.getSignatureIndex());
-            if (needsCastTo(value.getTypeMirror(), guard.getType())) {
-                return true;
-            }
-        }
-
-        List<GuardExpression> guards = new ArrayList<>(group.getGuards());
-        List<GuardExpression> elseConnectable = group.findElseConnectableGuards();
-        guards.removeAll(elseConnectable);
-        if (ignoreGuards != null) {
-            guards.removeAll(ignoreGuards);
-        }
-        SpecializationData specialization = group.getSpecialization();
-        if (specialization != null && fastPath) {
-            for (ListIterator<GuardExpression> iterator = guards.listIterator(); iterator.hasNext();) {
-                GuardExpression guard = iterator.next();
-                if (!specialization.isDynamicParameterBound(guard.getExpression())) {
-                    iterator.remove();
-                }
-            }
-        }
-
-        if (!guards.isEmpty()) {
-            return true;
-        }
-
-        if (!fastPath && specialization != null && !specialization.getAssumptionExpressions().isEmpty()) {
-            return true;
-        }
-
-        if (!fastPath && specialization != null && mayBeExcluded(specialization)) {
-            return true;
-        }
-
-        if (!elseConnectable.isEmpty()) {
-            SpecializationGroup previous = group.getPrevious();
-            if (previous != null && hasFallthrough(previous, forType, currentValues, fastPath, previous.getGuards())) {
-                return true;
-            }
-        }
-
-        List<SpecializationGroup> groupChildren = group.getChildren();
-        if (!groupChildren.isEmpty()) {
-            return hasFallthrough(groupChildren.get(groupChildren.size() - 1), forType, currentValues, fastPath, ignoreGuards);
-        }
-
-        return false;
-    }
-
-    private Element createGetNext(CodeTypeElement type) {
-        if (!nextUsed) {
-            return null;
-        }
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), type.asType(), "getNext");
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startReturn().cast(type.asType(), CodeTreeBuilder.singleString("this.next")).end();
-        return method;
-    }
-
-    private Element createGetSuppliedChildrenMethod() {
-        ArrayType nodeArray = context.getEnvironment().getTypeUtils().getArrayType(getType(Node.class));
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), nodeArray, "getSuppliedChildren");
-        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-
-        CodeTreeBuilder builder = method.createBuilder();
-        builder.startReturn().tree(createGetSuppliedChildren()).end();
-
-        return method;
-    }
-
-    private CodeTree createGetSuppliedChildren() {
-        ArrayType nodeArray = context.getEnvironment().getTypeUtils().getArrayType(getType(Node.class));
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startNewArray(nodeArray, null);
-        for (int i = 0; i < node.getChildExecutions().size(); i++) {
-            NodeExecutionData execution = node.getChildExecutions().get(i);
-            if (execution.isShortCircuit()) {
-                builder.nullLiteral();
-            }
-            if (execution.getChild() == null) {
-                builder.nullLiteral();
-            } else {
-                builder.tree(accessParent(nodeFieldName(execution)));
-            }
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    // create specialization
-
-    private CodeTree createCallCreateMethod(SpecializationData specialization, String rootName, LocalContext currentValues) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        TypeMirror specializationType = specializationType(specialization);
-        if (useLazyClassLoading()) {
-            builder.startStaticCall(specializationType(specialization), "create");
-        } else {
-            builder.startNew(specializationType);
-        }
-        if (rootName != null) {
-            builder.string(rootName);
-        } else {
-            builder.string("root");
-        }
-        if (currentValues != null) {
-            for (Parameter p : specialization.getSignatureParameters()) {
-                CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getType());
-                if (var != null) {
-                    LocalVariable variable = currentValues.get(p.getLocalName());
-                    if (variable == null) {
-                        throw new AssertionError("Could not bind cached value " + p.getLocalName() + ": " + currentValues);
-                    }
-                    builder.tree(variable.original().createReference());
-                }
-            }
-            for (CacheExpression cache : specialization.getCaches()) {
-                LocalVariable variable = currentValues.get(cache.getParameter().getLocalName());
-                if (variable == null) {
-                    throw new AssertionError("Could not bind cached value " + cache.getParameter().getLocalName() + ": " + currentValues);
-                }
-                builder.tree(variable.createReference());
-            }
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                LocalVariable variable = currentValues.get(assumptionName(assumption));
-                if (variable == null) {
-                    throw new AssertionError("Could not bind assumption value " + assumption.getId() + ": " + currentValues);
-                }
-                builder.tree(variable.createReference());
-            }
-        }
-        builder.end();
-
-        return builder.build();
-    }
-
-    private Element createSpecializationCreateMethod(SpecializationData specialization, CodeExecutableElement constructor) {
-        if (!useLazyClassLoading()) {
-            return null;
-        }
-
-        CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), constructor);
-        executable.setReturnType(specializationType(null));
-        executable.setSimpleName(CodeNames.of("create"));
-        executable.getModifiers().add(STATIC);
-
-        CodeTreeBuilder builder = executable.createBuilder();
-        builder.startReturn().startNew(specializationType(specialization));
-        for (VariableElement parameter : executable.getParameters()) {
-            builder.string(parameter.getSimpleName().toString());
-        }
-        builder.end().end();
-        return executable;
-    }
-
-    private boolean useLazyClassLoading() {
-        return options.useLazyClassLoading() && !singleSpecializable;
-    }
-
-    private static String implicitClassFieldName(NodeExecutionData execution) {
-        return execution.getName() + "ImplicitType";
-    }
-
-    private static String implicitNodeFieldName(NodeExecutionData execution) {
-        return execution.getName() + "Cast";
-    }
-
-    private CodeExecutableElement createSpecializationConstructor(CodeTypeElement clazz, SpecializationData specialization, String constantIndex) {
-        CodeExecutableElement constructor = new CodeExecutableElement(modifiers(), null, clazz.getSimpleName().toString());
-
-        constructor.addParameter(new CodeVariableElement(nodeType(node), "root"));
-        CodeTreeBuilder builder = constructor.createBuilder();
-
-        if (specialization == null) {
-            if (constantIndex == null) {
-                builder.statement("super(index)");
-                constructor.addParameter(new CodeVariableElement(getType(int.class), "index"));
-            } else {
-                builder.startStatement().startSuperCall().string(constantIndex).end().end();
-            }
-            builder.statement("this.root = root");
-        } else {
-            int index = resolveSpecializationIndex(specialization);
-            builder.startStatement().startSuperCall().string("root").string(String.valueOf(index)).end().end();
-
-            for (Parameter p : specialization.getSignatureParameters()) {
-                NodeExecutionData execution = p.getSpecification().getExecution();
-
-                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
-                if (implicitProfile != null) {
-                    LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(context);
-
-                    String implicitFieldName = implicitProfile.getName();
-                    if (options.implicitCastOptimization().isDuplicateTail()) {
-                        constructor.addParameter(var.createParameter());
-                        CodeTree implicitType = TypeSystemCodeGenerator.implicitType(typeSystem, p.getType(), var.createReference());
-                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(implicitType).end();
-                    } else if (options.implicitCastOptimization().isMergeCasts()) {
-                        // use node that supports polymorphism
-                        constructor.addParameter(var.createParameter());
-                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(typeSystem, p.getType(), var.createReference())).end();
-                    } else {
-                        throw new AssertionError();
-                    }
-                }
-            }
-            for (CacheExpression cache : specialization.getCaches()) {
-                String name = cache.getParameter().getLocalName();
-                TypeMirror type = cache.getParameter().getType();
-
-                if (ElementUtils.isAssignable(type, new ArrayCodeTypeMirror(getType(Node.class)))) {
-                    CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
-                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Children.class)));
-                } else if (ElementUtils.isAssignable(type, getType(Node.class))) {
-                    CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE), type, name));
-                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Child.class)));
-                } else {
-                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
-                }
-                constructor.addParameter(new CodeVariableElement(type, name));
-                builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
-            }
-
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                String name = assumptionName(assumption);
-                TypeMirror type = assumption.getExpression().getResolvedType();
-                CodeVariableElement field = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
-                field.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
-                constructor.addParameter(new CodeVariableElement(type, name));
-                builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
-            }
-        }
-
-        if (constructor.getParameters().isEmpty()) {
-            // do not generate default constructor
-            return null;
-        }
-        return constructor;
-    }
-
-    // TODO this logic can be inlined to the parser as soon as the old NodeGen layout is gone
-    private static int resolveSpecializationIndex(SpecializationData specialization) {
-        if (specialization.isFallback()) {
-            return Integer.MAX_VALUE - 1;
-        } else if (specialization.isUninitialized()) {
-            return Integer.MAX_VALUE;
-        } else if (specialization.isPolymorphic()) {
-            return 0;
-        } else {
-            return specialization.getIndex();
-        }
-    }
-
-    private CodeTree createThrowUnsupported(LocalContext currentValues) {
-        singleSpecializableUnsupportedUsed = true;
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startThrow().startCall("unsupported");
-        currentValues.addReferencesTo(builder);
-        builder.end().end();
-        return builder.build();
-    }
-
-    private CodeTree createCallNext(CodeTreeBuilder parent, ExecutableTypeData currentType, ExecutableTypeData callType, LocalContext currentValues) {
-        if (singleSpecializable) {
-            return createThrowUnsupported(currentValues);
-        }
-        CodeTreeBuilder callBuilder = parent.create();
-        callBuilder.tree(createCallDelegateExecute(callBuilder, CodeTreeBuilder.singleString("getNext()"), currentValues, currentType, callType));
-        nextUsed = true;
-        return callBuilder.build();
-    }
-
-    private CodeTree createCallRemove(String reason, ExecutableTypeData forType, LocalContext currentValues) {
-        if (singleSpecializable) {
-            return createThrowUnsupported(currentValues);
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startCall("remove");
-        builder.doubleQuote(reason);
-        currentValues.addReferencesTo(builder, FRAME_VALUE);
-        builder.end();
-        CodeTree call = builder.build();
-
-        builder = builder.create();
-        builder.startReturn();
-        builder.tree(expectOrCast(genericType, forType, call));
-        builder.end();
-        return builder.build();
-    }
-
-    private CodeTree createCallDelegate(String methodName, String reason, ExecutableTypeData forType, LocalContext currentValues) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startCall(methodName);
-        if (reason != null) {
-            builder.doubleQuote(reason);
-        }
-        currentValues.addReferencesTo(builder, FRAME_VALUE);
-        builder.end();
-
-        CodeTree expectOrCast = expectOrCast(genericType, forType, builder.build());
-        return expectOrCast;
-    }
-
-    private CodeTree expectOrCast(TypeMirror sourceType, ExecutableTypeData targetType, CodeTree content) {
-        if (needsUnexpectedResultException(targetType)) {
-            return expect(sourceType, targetType.getReturnType(), content);
-        } else {
-            return cast(sourceType, targetType.getReturnType(), content);
-        }
-    }
-
-    private CodeTree cast(TypeMirror sourceType, TypeMirror targetType, CodeTree content) {
-        if (ElementUtils.needsCastTo(sourceType, targetType) && !isVoid(sourceType)) {
-            return TypeSystemCodeGenerator.cast(typeSystem, targetType, content);
-        } else {
-            return content;
-        }
-    }
-
-    private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) {
-        if (sourceType == null || ElementUtils.needsCastTo(sourceType, forType)) {
-            expectedTypes.add(forType);
-            return TypeSystemCodeGenerator.expect(typeSystem, forType, tree);
-        }
-        return tree;
-    }
-
-    private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) {
-        if (execution.getChild() == null) {
-            return Collections.emptySet();
-        }
-        ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type);
-        Set<ExecutableTypeData> executedTypes = new HashSet<>();
-        executedTypes.add(executableType);
-        if (typeSystem.hasImplicitSourceTypes(type)) {
-            executedTypes.addAll(resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(type), options.implicitTypeBoxingOptimization()));
-        }
-        return executedTypes;
-    }
-
-    private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeMirror type) {
-        int executeWithCount = child.getExecuteWith().size();
-        ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount);
-        if (executableType == null) {
-            executableType = child.getNodeData().findAnyGenericExecutableType(context, executeWithCount);
-        }
-        return executableType;
-    }
-
-    private boolean hasChildUnexpectedResult(NodeExecutionData execution, TypeMirror type) {
-        for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) {
-            if (executableType != null && (executableType.hasUnexpectedValue(context) || needsCastTo(executableType.getReturnType(), type))) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private Element createFastPathExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, List<ExecutableTypeData> allTypes) {
-        LocalContext currentLocals = LocalContext.load(this, executedType, Integer.MAX_VALUE);
-        CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false, Integer.MAX_VALUE);
-        CodeTreeBuilder builder = executable.createBuilder();
-        if (specialization == null) {
-            if (executedType.getDelegatedTo() == null) {
-                executable.getModifiers().add(ABSTRACT);
-            }
-        } else {
-            executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
-        }
-        builder.tree(createFastPath(builder, specialization, executedType, allTypes, currentLocals));
-
-        return executable;
-    }
-
-    private static final String VARARGS_NAME = "args";
-
-    private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride, int varArgs) {
-        TypeMirror returnType = executedType.getReturnType();
-
-        if (specialization != null) {
-            currentLocals.loadFastPathState(specialization);
-        }
-
-        String methodName;
-        if (originalOverride && executedType.getMethod() != null) {
-            methodName = executedType.getMethod().getSimpleName().toString();
-        } else {
-            methodName = executedType.getUniqueName();
-        }
-
-        CodeExecutableElement executable;
-        if (originalOverride && executedType.getMethod() != null) {
-            executable = CodeExecutableElement.clone(context.getEnvironment(), executedType.getMethod());
-            executable.getAnnotationMirrors().clear();
-            executable.getModifiers().remove(ABSTRACT);
-            for (VariableElement var : executable.getParameters()) {
-                ((CodeVariableElement) var).getAnnotationMirrors().clear();
-            }
-            if (executedType.getFrameParameter() != null) {
-                ((CodeVariableElement) executable.getParameters().get(0)).setName(FRAME_VALUE);
-            }
-
-            if (executable.isVarArgs()) {
-                ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(VARARGS_NAME);
-            }
-
-            renameOriginalParameters(executedType, executable, currentLocals);
-        } else {
-            executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, varArgs, FRAME_VALUE);
-        }
-        executable.getThrownTypes().clear();
-
-        if (needsUnexpectedResultException(executedType)) {
-            executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class));
-        }
-
-        return executable;
-    }
-
-    private void renameOriginalParameters(ExecutableTypeData executedType, CodeExecutableElement executable, LocalContext currentLocals) {
-        // rename varargs parameter
-        int evaluatedIndex = 0;
-        for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) {
-            NodeExecutionData execution = node.getChildExecutions().get(executionIndex);
-            if (execution.isShortCircuit()) {
-                if (evaluatedIndex < executedType.getEvaluatedCount()) {
-                    TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex);
-                    LocalVariable shortCircuit = currentLocals.getShortCircuit(execution);
-                    if (shortCircuit != null) {
-                        currentLocals.setShortCircuitValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, shortCircuit));
-                    }
-                    evaluatedIndex++;
-                }
-            }
-            if (evaluatedIndex < executedType.getEvaluatedCount()) {
-                TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex);
-                LocalVariable value = currentLocals.getValue(execution);
-                if (value != null) {
-                    currentLocals.setValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, value));
-                }
-                evaluatedIndex++;
-            }
-        }
-    }
-
-    private static LocalVariable renameExecutableTypeParameter(CodeExecutableElement method, ExecutableTypeData executedType, int evaluatedIndex, TypeMirror targetType, LocalVariable var) {
-        int parameterIndex = executedType.getParameterIndex(evaluatedIndex);
-        int varArgsIndex = executedType.getVarArgsIndex(parameterIndex);
-        LocalVariable returnVar = var;
-        if (varArgsIndex >= 0) {
-            returnVar = returnVar.accessWith(CodeTreeBuilder.singleString(VARARGS_NAME + "[" + varArgsIndex + "]"));
-        } else {
-            ((CodeVariableElement) method.getParameters().get(parameterIndex)).setName(returnVar.getName());
-        }
-        if (!isObject(targetType)) {
-            returnVar = returnVar.newType(targetType);
-        }
-        return returnVar;
-    }
-
-    private boolean needsUnexpectedResultException(ExecutableTypeData executedType) {
-        if (!executedType.hasUnexpectedValue(context)) {
-            return false;
-        }
-
-        SpecializationData polymorphicSpecialization = node.getPolymorphicSpecialization();
-        if (polymorphicSpecialization != null && isSubtypeBoxed(context, polymorphicSpecialization.getReturnType().getType(), executedType.getReturnType())) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, final ExecutableTypeData executableType, List<ExecutableTypeData> allTypes, LocalContext currentLocals) {
-        final CodeTreeBuilder builder = parent.create();
-        TypeMirror returnType = executableType.getReturnType();
-
-        ExecutableTypeData delegate = null;
-        if (specialization == null) {
-            delegate = executableType.getDelegatedTo();
-        }
-
-        if (delegate == null) {
-            delegate = findFastPathDelegate((specialization != null ? specialization.getReturnType().getType() : genericType), executableType, allTypes);
-        }
-
-        int delegateSignatureCount = delegate != null ? delegate.getSignatureParameters().size() : 0;
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (specialization == null && delegate != null && execution.getIndex() >= delegateSignatureCount) {
-                // we just evaluate children for the next delegate
-                continue;
-            } else if (specialization != null && delegate != null) {
-                // skip if already delegated
-                break;
-            }
-
-            LocalVariable var = currentLocals.getValue(execution);
-            if (var == null) {
-                TypeMirror targetType;
-                if (specialization == null) {
-                    targetType = node.getGenericType(execution);
-                } else {
-                    targetType = specialization.findParameterOrDie(execution).getType();
-                }
-                LocalVariable shortCircuit = resolveShortCircuit(specialization, execution, currentLocals);
-                var = currentLocals.createValue(execution, targetType).nextName();
-                builder.tree(createAssignExecuteChild(builder, execution, executableType, var, shortCircuit, currentLocals));
-                currentLocals.setValue(execution, var);
-            }
-        }
-
-        LocalContext originalValues = currentLocals.copy();
-        if (delegate != null) {
-            builder.tree(createCallDelegateExecute(builder, null, currentLocals, executableType, delegate));
-        } else if (specialization == null) {
-            // nothing to do. abstract anyway
-        } else if (specialization.isPolymorphic()) {
-            builder.tree(createCallNext(builder, executableType, node.getGenericExecutableType(executableType), currentLocals));
-        } else if (specialization.isUninitialized()) {
-            builder.startReturn().tree(createCallDelegate("uninitialized", null, executableType, currentLocals)).end();
-        } else {
-            SpecializationGroup group = SpecializationGroup.create(specialization);
-            SpecializationBody executionFactory = new SpecializationBody(true, true) {
-                @Override
-                public CodeTree createBody(SpecializationData s, LocalContext values) {
-                    return createFastPathExecute(builder, executableType, s, values);
-                }
-            };
-            builder.tree(createGuardAndCast(group, returnType, currentLocals, executionFactory));
-            if (hasFallthrough(group, returnType, originalValues, true, null) || group.getSpecialization().isFallback()) {
-                builder.tree(createCallNext(builder, executableType, node.getGenericExecutableType(executableType), originalValues));
-            }
-        }
-        return builder.build();
-    }
-
-    private CodeTree createCallDelegateExecute(final CodeTreeBuilder parent, CodeTree receiver, LocalContext currentLocals, ExecutableTypeData source, ExecutableTypeData delegate) {
-        CodeTreeBuilder callBuilder = parent.create();
-
-        if (singleSpecializable && delegate.getMethod() != null) {
-            callBuilder.startCall(receiver, delegate.getMethod().getSimpleName().toString());
-        } else {
-            callBuilder.startCall(receiver, delegate.getUniqueName());
-        }
-        callBuilder.trees(bindExecuteMethodParameters(null, delegate, currentLocals));
-        callBuilder.end();
-        CodeTree call = expectOrCast(delegate.getReturnType(), source, callBuilder.build());
-
-        CodeTreeBuilder returnBuilder = parent.create();
-        if (isVoid(source.getReturnType())) {
-            returnBuilder.statement(call);
-            returnBuilder.returnStatement();
-        } else if (isVoid(delegate.getReturnType())) {
-            returnBuilder.statement(call);
-            returnBuilder.returnDefault();
-        } else {
-            returnBuilder.startReturn().tree(call).end();
-        }
-
-        CodeTreeBuilder builder = parent.create();
-
-        if (!needsUnexpectedResultException(source) && needsUnexpectedResultException(delegate)) {
-            builder.startTryBlock();
-            builder.tree(returnBuilder.build());
-            builder.end().startCatchBlock(context.getType(UnexpectedResultException.class), "ex");
-            if (!isVoid(source.getReturnType())) {
-                builder.startReturn().tree(cast(context.getType(Object.class), source.getReturnType(), CodeTreeBuilder.singleString("ex.getResult()"))).end();
-            }
-            builder.end();
-        } else {
-            builder.tree(returnBuilder.build());
-        }
-        return builder.build();
-    }
-
-    private ExecutableTypeData findFastPathDelegate(TypeMirror targetType, ExecutableTypeData executableType, List<ExecutableTypeData> allTypes) {
-        if (typeEquals(executableType.getReturnType(), targetType)) {
-            // type matches look for even better delegates
-            for (ExecutableTypeData type : allTypes) {
-                if (typeEquals(type.getReturnType(), targetType) && executableType.sameParameters(type)) {
-                    if (type != executableType) {
-                        return type;
-                    }
-                }
-            }
-            return null;
-        } else {
-            for (ExecutableTypeData type : allTypes) {
-                if (typeEquals(type.getReturnType(), targetType) && executableType.sameParameters(type)) {
-                    return type;
-                }
-            }
-            int executableIndex = allTypes.indexOf(executableType);
-            int compareIndex = 0;
-            for (ExecutableTypeData type : allTypes) {
-                if (executableIndex != compareIndex && executableType.sameParameters(type)) {
-                    int result = ExecutableTypeData.compareType(context, type.getReturnType(), executableType.getReturnType());
-                    if (result < 0) {
-                        return type;
-                    } else if (result == 0 && executableIndex < compareIndex) {
-                        return type;
-                    }
-                }
-                compareIndex++;
-            }
-            return null;
-        }
-    }
-
-    private LocalVariable resolveShortCircuit(SpecializationData specialization, NodeExecutionData execution, LocalContext currentLocals) {
-        LocalVariable shortCircuit = null;
-        if (execution.isShortCircuit()) {
-            shortCircuit = currentLocals.getShortCircuit(execution);
-
-            if (shortCircuit == null) {
-                SpecializationData resolvedSpecialization = specialization;
-                if (specialization == null) {
-                    resolvedSpecialization = node.getGenericSpecialization();
-                }
-                ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution));
-                CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals);
-                shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access);
-            } else {
-                CodeTree access = shortCircuit.createReference();
-                shortCircuit = shortCircuit.nextName().accessWith(access);
-            }
-        }
-        return shortCircuit;
-    }
-
-    private int calculateShortCircuitIndex(NodeExecutionData execution) {
-        int shortCircuitIndex = 0;
-        for (NodeExecutionData otherExectuion : node.getChildExecutions()) {
-            if (otherExectuion.isShortCircuit()) {
-                if (otherExectuion == execution) {
-                    break;
-                }
-                shortCircuitIndex++;
-            }
-        }
-        return shortCircuitIndex;
-    }
-
-    private CodeTree createFastPathExecute(CodeTreeBuilder parent, final ExecutableTypeData forType, SpecializationData specialization, LocalContext currentValues) {
-        CodeTreeBuilder builder = parent.create();
-        int ifCount = 0;
-        if (specialization.isFallback()) {
-            builder.startIf().startCall("guardFallback");
-            if (node.isFrameUsedByAnyGuard()) {
-                if (currentValues.get(FRAME_VALUE) != null) {
-                    builder.string(FRAME_VALUE);
-                } else {
-                    builder.nullLiteral();
-                }
-            }
-            currentValues.addReferencesTo(builder);
-
-            builder.end();
-            builder.end();
-            builder.startBlock();
-            ifCount++;
-        }
-        CodeTreeBuilder execute = builder.create();
-
-        if (!specialization.getAssumptionExpressions().isEmpty()) {
-            builder.startTryBlock();
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
-                if (assumptionVar == null) {
-                    throw new AssertionError("Could not resolve assumption var " + currentValues);
-                }
-                builder.startStatement().startCall("check").tree(assumptionVar.createReference()).end().end();
-            }
-            builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
-            builder.startReturn();
-            List<String> assumptionIds = new ArrayList<>();
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                assumptionIds.add(assumption.getId());
-            }
-            builder.tree(createCallDelegate("removeThis", String.format("Assumption %s invalidated", assumptionIds), forType, currentValues));
-            builder.end();
-            builder.end();
-        }
-
-        if (specialization.getMethod() == null) {
-            execute.startReturn();
-            execute.startCall("unsupported");
-            currentValues.addReferencesTo(execute, FRAME_VALUE);
-            execute.end();
-            execute.end();
-        } else {
-            boolean doReturn = !isVoid(specialization.getMethod().getReturnType());
-            if (doReturn) {
-                execute.startReturn();
-            } else {
-                execute.startStatement();
-            }
-            execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues));
-            execute.end();
-            if (!doReturn) {
-                if (isVoid(forType.getReturnType())) {
-                    execute.returnStatement();
-                } else {
-                    execute.startReturn();
-                    execute.defaultValue(forType.getReturnType());
-                    execute.end();
-                }
-            }
-        }
-        builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build()));
-        builder.end(ifCount);
-        return builder.build();
-    }
-
-    private CodeTree createGuardAndCast(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, SpecializationBody execution) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        Set<TypeGuard> castGuards;
-        if (execution.needsCastedValues()) {
-            castGuards = null; // cast all
-        } else {
-            castGuards = new HashSet<>();
-            for (TypeGuard castGuard : group.getTypeGuards()) {
-                if (isTypeGuardUsedInAnyGuardOrCacheBelow(group, currentValues, castGuard, execution.isFastPath())) {
-                    castGuards.add(castGuard);
-                }
-            }
-        }
-
-        SpecializationData specialization = group.getSpecialization();
-        CodeTree[] checkAndCast = createTypeCheckAndLocals(specialization, group.getTypeGuards(), castGuards, currentValues, execution);
-
-        CodeTree check = checkAndCast[0];
-        CodeTree cast = checkAndCast[1];
-
-        List<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards();
-        List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards());
-        guardExpressions.removeAll(elseGuardExpressions);
-        CodeTree[] methodGuardAndAssertions = createMethodGuardCheck(guardExpressions, specialization, currentValues, execution.isFastPath());
-        CodeTree methodGuards = methodGuardAndAssertions[0];
-        CodeTree guardAssertions = methodGuardAndAssertions[1];
-
-        int ifCount = 0;
-        if (!check.isEmpty()) {
-            builder.startIf();
-            builder.tree(check).end();
-            builder.startBlock();
-            ifCount++;
-        }
-        if (!cast.isEmpty()) {
-            builder.tree(cast);
-        }
-        boolean elseIf = !elseGuardExpressions.isEmpty();
-        if (!methodGuards.isEmpty()) {
-            builder.startIf(elseIf);
-            builder.tree(methodGuards).end();
-            builder.startBlock();
-            ifCount++;
-        } else if (elseIf) {
-            builder.startElseBlock();
-            ifCount++;
-        }
-        if (!guardAssertions.isEmpty()) {
-            builder.tree(guardAssertions);
-        }
-
-        boolean reachable = isReachableGroup(group, ifCount);
-        if (reachable) {
-            for (SpecializationGroup child : group.getChildren()) {
-                builder.tree(createGuardAndCast(child, forType, currentValues.copy(), execution));
-            }
-            if (specialization != null) {
-                builder.tree(execution.createBody(specialization, currentValues));
-            }
-        }
-        builder.end(ifCount);
-
-        return builder.build();
-    }
-
-    private static boolean isReachableGroup(SpecializationGroup group, int ifCount) {
-        if (ifCount != 0) {
-            return true;
-        }
-        SpecializationGroup previous = group.getPreviousGroup();
-        if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
-            return true;
-        }
-
-        /*
-         * Hacky else case. In this case the specialization is not reachable due to previous else
-         * branch. This is only true if the minimum state is not checked.
-         */
-        if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() &&
-                        (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private boolean isTypeGuardUsedInAnyGuardOrCacheBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard, boolean fastPath) {
-        String localName = currentValues.getValue(typeGuard.getSignatureIndex()).getName();
-
-        SpecializationData specialization = group.getSpecialization();
-        for (GuardExpression guard : group.getGuards()) {
-            if (isVariableBoundIn(specialization, guard.getExpression(), localName, currentValues)) {
-                return true;
-            }
-        }
-        if (!fastPath && specialization != null) {
-            for (CacheExpression cache : specialization.getCaches()) {
-                if (isVariableBoundIn(specialization, cache.getExpression(), localName, currentValues)) {
-                    return true;
-                }
-            }
-        }
-
-        for (SpecializationGroup child : group.getChildren()) {
-            if (isTypeGuardUsedInAnyGuardOrCacheBelow(child, currentValues, typeGuard, fastPath)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    private static boolean isVariableBoundIn(SpecializationData specialization, DSLExpression expression, String localName, LocalContext currentValues) throws AssertionError {
-        Map<Variable, LocalVariable> boundValues = bindExpressionValues(expression, specialization, currentValues);
-        for (Variable var : expression.findBoundVariables()) {
-            LocalVariable target = boundValues.get(var);
-            if (target != null && localName.equals(target.getName())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) {
-        if (!usedExecuteChildMethods.contains(execution)) {
-            return null;
-        }
-
-        LocalContext locals = LocalContext.load(this, createSpecializationNodeSignature(0), Integer.MAX_VALUE);
-
-        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), Integer.MAX_VALUE, FRAME_VALUE);
-        if (hasChildUnexpectedResult(execution, targetType)) {
-            method.getThrownTypes().add(getType(UnexpectedResultException.class));
-        }
-
-        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetType);
-        if (implicitProfile != null) {
-            method.addParameter(implicitProfile);
-        }
-
-        for (int i = 0; i < execution.getChild().getExecuteWith().size(); i++) {
-            NodeExecutionData executeWith = node.getChildExecutions().get(i);
-            LocalVariable var = locals.createValue(executeWith, genericType);
-            method.addParameter(var.createParameter());
-            locals.setValue(executeWith, var);
-        }
-
-        CodeTreeBuilder builder = method.createBuilder();
-        CodeTree executeChild = createExecuteChild(execution, locals.createValue(execution, targetType), locals, true);
-        if (executeChild.isSingleLine()) {
-            builder.statement(executeChild);
-        } else {
-            builder.tree(executeChild);
-        }
-        return method;
-    }
-
-    private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) {
-        if (typeSystem.hasImplicitSourceTypes(targetType)) {
-            if (typeEquals(node.getGenericType(execution), targetType)) {
-                return null;
-            }
-
-            switch (options.implicitCastOptimization()) {
-                case NONE:
-                    return null;
-                case DUPLICATE_TAIL:
-                    return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution));
-                case MERGE_CASTS:
-                    return new CodeVariableElement(ImplicitCastNodeFactory.type(typeSystem, targetType), implicitNodeFieldName(execution));
-            }
-        }
-        return null;
-    }
-
-    private boolean isExecuteChildShared(NodeExecutionData execution, TypeMirror targetType) {
-        if (isVoid(targetType)) {
-            return false;
-        } else if (isObject(targetType)) {
-            return resolvePolymorphicExecutables(execution).size() >= 1;
-        } else {
-            if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) {
-                return false;
-            }
-            if (!typeSystem.hasImplicitSourceTypes(targetType)) {
-                return false;
-            }
-
-            int uses = 0;
-            for (SpecializationData specialization : node.getSpecializations()) {
-                List<Parameter> parameters = specialization.findByExecutionData(execution);
-                for (Parameter parameter : parameters) {
-                    if (targetType.equals(parameter.getType())) {
-                        uses++;
-                    }
-                }
-            }
-            if (uses > 1) {
-                return resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(targetType), options.implicitTypeBoxingOptimization()).size() > 1;
-            } else {
-                return false;
-            }
-        }
-    }
-
-    private CodeTree createAssignExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData type, LocalVariable targetValue, LocalVariable shortCircuit,
-                    LocalContext currentValues) {
-        CodeTreeBuilder builder = parent.create();
-        boolean hasUnexpected = hasChildUnexpectedResult(execution, targetValue.getTypeMirror());
-
-        CodeTree executeChild;
-        if (isExecuteChildShared(execution, targetValue.getTypeMirror())) {
-            executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues);
-        } else {
-            executeChild = createExecuteChild(execution, targetValue, currentValues, false);
-        }
-
-        builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected));
-
-        if (shortCircuit != null) {
-            currentValues.setShortCircuitValue(execution, shortCircuit.accessWith(null));
-        }
-
-        builder.end();
-        if (hasUnexpected) {
-            builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
-            LocalContext slowPathValues = currentValues.copy();
-            slowPathValues.setValue(execution, targetValue.makeGeneric(context).accessWith(CodeTreeBuilder.singleString("ex.getResult()")));
-
-            ExecutableTypeData delegateType = node.getGenericExecutableType(type);
-            boolean found = false;
-            for (NodeExecutionData otherExecution : node.getChildExecutions()) {
-                if (found) {
-                    LocalVariable childEvaluatedValue = slowPathValues.createValue(otherExecution, genericType);
-                    LocalVariable genericShortCircuit = resolveShortCircuit(null, otherExecution, slowPathValues);
-                    builder.tree(createAssignExecuteChild(builder, otherExecution, delegateType, childEvaluatedValue, genericShortCircuit, slowPathValues));
-                    slowPathValues.setValue(otherExecution, childEvaluatedValue);
-                } else {
-                    // skip forward already evaluated
-                    found = execution == otherExecution;
-                }
-            }
-            builder.tree(createCallNext(builder, type, delegateType, slowPathValues));
-            builder.end();
-        }
-
-        return createShortCircuit(targetValue, shortCircuit, builder.build());
-    }
-
-    private static CodeTree createShortCircuit(LocalVariable targetValue, LocalVariable shortCircuitValue, CodeTree tryExecute) {
-        if (shortCircuitValue == null) {
-            return tryExecute;
-        }
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        builder.tree(shortCircuitValue.createDeclaration(shortCircuitValue.createReference()));
-        builder.tree(targetValue.createDeclaration(builder.create().defaultValue(targetValue.getTypeMirror()).build()));
-
-        builder.startIf().string(shortCircuitValue.getName()).end().startBlock();
-        builder.tree(tryExecute);
-        builder.end();
-
-        return builder.build();
-    }
-
-    private static CodeTree createTryExecuteChild(LocalVariable value, CodeTree executeChild, boolean needDeclaration, boolean hasTry) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        boolean hasDeclaration = false;
-        if ((hasTry || !executeChild.isSingleLine()) && needDeclaration) {
-            builder.tree(value.createDeclaration(null));
-            hasDeclaration = true;
-        }
-
-        if (hasTry) {
-            builder.startTryBlock();
-        } else {
-            builder.startGroup();
-        }
-
-        if (executeChild.isSingleLine()) {
-            builder.startStatement();
-            if (hasDeclaration || !needDeclaration) {
-                builder.tree(executeChild);
-            } else {
-                builder.type(value.getTypeMirror()).string(" ").tree(executeChild);
-            }
-            builder.end();
-        } else {
-            builder.tree(executeChild);
-        }
-
-        builder.end();
-
-        return builder.build();
-    }
-
-    private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) {
-        if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) {
-            throw new AssertionError("Execute child not shared with method but called.");
-        }
-        usedExecuteChildMethods.add(execution);
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.tree(targetValue.createReference()).string(" = ");
-        builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror()));
-        if (currentValues.get(FRAME_VALUE) == null) {
-            builder.nullLiteral();
-        } else {
-            builder.string(FRAME_VALUE);
-        }
-
-        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getTypeMirror());
-        if (implicitProfile != null) {
-            builder.string(implicitProfile.getName());
-        }
-        for (int i = 0; i < execution.getChild().getExecuteWith().size(); i++) {
-            builder.tree(currentValues.getValue(i).createReference());
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    private CodeTree createExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) {
-        final CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        CodeTree assignment = createAssignmentStart(target, shared);
-
-        final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getTypeMirror());
-        if (executableTypes.isEmpty()) {
-            throw new AssertionError(); // cannot execute child
-        } else if (executableTypes.size() == 1 && !typeSystem.hasImplicitSourceTypes(target.getTypeMirror())) {
-            ExecutableTypeData executableType = executableTypes.iterator().next();
-            if (isObject(target.getTypeMirror()) && executableType.getEvaluatedCount() == 0) {
-                return createPolymorphicExecuteChild(execution, target, currentValues, shared);
-            } else {
-                builder.tree(assignment);
-                builder.tree(createSingleExecute(execution, target, currentValues, executableType));
-            }
-        } else {
-            if (options.implicitCastOptimization().isNone()) {
-                throw new AssertionError("findSpecializedExecutableTypes is always 1 if implicit cast opt is disabled");
-            } else if (options.implicitCastOptimization().isDuplicateTail()) {
-                builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues));
-            } else if (options.implicitCastOptimization().isMergeCasts()) {
-                // TODO
-                throw new UnsupportedOperationException();
-            } else {
-                throw new AssertionError();
-            }
-        }
-        return builder.build();
-    }
-
-    private CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) {
-        CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
-        return expect(executableType.getReturnType(), target.getTypeMirror(), execute);
-    }
-
-    private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError {
-        ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size());
-        if (genericExecutableType == null) {
-            throw new AssertionError("At least one generic executable method must be available.");
-        }
-
-        List<ExecutableTypeData> specializedExecutables = resolvePolymorphicExecutables(execution);
-        Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() {
-            public int compare(ExecutableTypeData o1, ExecutableTypeData o2) {
-                return compareType(o1.getReturnType(), o2.getReturnType());
-            }
-        });
-
-        CodeTree assignment = createAssignmentStart(target, shared);
-        CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType);
-
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (specializedExecutables.isEmpty()) {
-            builder.tree(assignment);
-            builder.tree(executeGeneric);
-        } else {
-            final CodeTreeBuilder polyChainBuilder = builder.create();
-            final String profileField = polymorphicTypeProfileFieldName(execution);
-            final String valueFieldName = "_value";
-            final String typeFieldName = "_type";
-
-            builder.declaration(getType(Class.class), profileField, accessParent(profileField));
-
-            boolean encounteredUnexpectedResult = false;
-            boolean hasSpecializedTypes = false;
-            for (ExecutableTypeData executableType : specializedExecutables) {
-                hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
-                polyChainBuilder.string(profileField);
-                polyChainBuilder.string(" == ").typeLiteral(executableType.getReturnType());
-                polyChainBuilder.end();
-                polyChainBuilder.startBlock();
-                polyChainBuilder.startStatement();
-                polyChainBuilder.tree(assignment);
-                polyChainBuilder.tree(createSingleExecute(execution, target, currentValues, executableType)).end();
-                polyChainBuilder.end();
-                encounteredUnexpectedResult |= executableType.hasUnexpectedValue(context);
-            }
-
-            // else if null -> specialize
-            polyChainBuilder.startElseIf().string(profileField).string(" == null").end();
-            polyChainBuilder.startBlock();
-            polyChainBuilder.tree(createTransferToInterpreterAndInvalidate());
-            polyChainBuilder.declaration(context.getType(Class.class), typeFieldName, polyChainBuilder.create().typeLiteral(genericType).build());
-            polyChainBuilder.startTryBlock();
-            polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric);
-
-            hasSpecializedTypes = false;
-            for (ExecutableTypeData executableType : specializedExecutables) {
-                hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
-                polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName)));
-                polyChainBuilder.end();
-                polyChainBuilder.startBlock();
-                polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(executableType.getReturnType()).end();
-                polyChainBuilder.end();
-            }
-            polyChainBuilder.startElseBlock();
-            polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(genericType).end();
-            polyChainBuilder.end();
-            polyChainBuilder.startReturn().string(valueFieldName).end();
-
-            polyChainBuilder.end().startFinallyBlock();
-            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").string(typeFieldName).end();
-            polyChainBuilder.end();
-            polyChainBuilder.end();
-
-            // else -> execute generic
-            polyChainBuilder.startElseBlock();
-            polyChainBuilder.startStatement().tree(assignment).tree(executeGeneric).end();
-            polyChainBuilder.end();
-
-            CodeTree executePolymorphic = polyChainBuilder.build();
-            if (encounteredUnexpectedResult) {
-                builder.startTryBlock();
-                builder.tree(executePolymorphic);
-                builder.end();
-                builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
-                builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end();
-                builder.startReturn().string("ex.getResult()").end();
-                builder.end();
-            } else {
-                builder.tree(executePolymorphic);
-            }
-        }
-        return builder.build();
-    }
-
-    private List<ExecutableTypeData> resolvePolymorphicExecutables(NodeExecutionData execution) {
-        if (singleSpecializable) {
-            return Collections.emptyList();
-        }
-        Set<TypeMirror> specializedTypes = new HashSet<>();
-        for (TypeMirror type : node.findSpecializedTypes(execution)) {
-            specializedTypes.addAll(typeSystem.lookupSourceTypes(type));
-        }
-        return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
-    }
-
-    private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (shared) {
-            builder.string("return ");
-        } else {
-            builder.string(target.getName()).string(" = ");
-        }
-        return builder.build();
-    }
-
-    private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) {
-        CodeTreeBuilder builder = parent.create();
-        List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror());
-        String implicitClassFieldName = implicitClassFieldName(execution);
-        List<ExecutableTypeData> executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization());
-
-        boolean elseIf = false;
-        for (ExecutableTypeData executableType : executableTypes) {
-            elseIf = builder.startIf(elseIf);
-            builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getReturnType());
-            builder.end();
-            builder.startBlock();
-            builder.startStatement().tree(assignment);
-
-            CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
-            ImplicitCastData cast = typeSystem.lookupCast(executableType.getReturnType(), target.getTypeMirror());
-            if (cast != null) {
-                execute = callMethod(null, cast.getMethod(), execute);
-            }
-            builder.tree(execute);
-            builder.end();
-            builder.end();
-        }
-
-        if (!executableTypes.isEmpty()) {
-            builder.startElseBlock();
-        }
-
-        LocalVariable genericValue = target.makeGeneric(context).nextName();
-        builder.tree(createAssignExecuteChild(builder, execution, node.getGenericExecutableType(null), genericValue, null, currentValues));
-        if (executableTypes.size() == sourceTypes.size()) {
-            builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end();
-        } else {
-            builder.startStatement().tree(assignment);
-            builder.tree(TypeSystemCodeGenerator.implicitExpect(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitClassFieldName));
-            builder.end();
-        }
-
-        if (!executableTypes.isEmpty()) {
-            builder.end();
-        }
-        return builder.build();
-    }
-
-    private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, ExecutableTypeData forType, LocalContext currentValues, CodeTree execution) {
-        if (specialization.getExceptions().isEmpty()) {
-            return execution;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startTryBlock();
-        builder.tree(execution);
-        TypeMirror[] exceptionTypes = new TypeMirror[specialization.getExceptions().size()];
-        for (int i = 0; i < exceptionTypes.length; i++) {
-            exceptionTypes[i] = specialization.getExceptions().get(i).getJavaClass();
-        }
-        builder.end().startCatchBlock(exceptionTypes, "ex");
-        builder.startStatement().tree(accessParent(excludedFieldName(specialization))).string(" = true").end();
-        builder.tree(createCallRemove("threw rewrite exception", forType, currentValues));
-        builder.end();
-        return builder.build();
-    }
-
-    private CodeTree[] createMethodGuardCheck(List<GuardExpression> guardExpressions, SpecializationData specialization, LocalContext currentValues, boolean fastPath) {
-        CodeTreeBuilder expressionBuilder = CodeTreeBuilder.createBuilder();
-        CodeTreeBuilder assertionBuilder = CodeTreeBuilder.createBuilder();
-        String and = "";
-        for (GuardExpression guard : guardExpressions) {
-            DSLExpression expression = guard.getExpression();
-
-            Map<Variable, CodeTree> resolvedBindings = castBoundTypes(bindExpressionValues(expression, specialization, currentValues));
-            CodeTree expressionCode = DSLExpressionGenerator.write(expression, accessParent(null), resolvedBindings);
-
-            if (!specialization.isDynamicParameterBound(expression) && fastPath) {
-                /*
-                 * Guards where no dynamic parameters are bound can just be executed on the fast
-                 * path.
-                 */
-                assertionBuilder.startAssert().tree(expressionCode).end();
-            } else {
-                expressionBuilder.string(and);
-                expressionBuilder.tree(expressionCode);
-                and = " && ";
-            }
-        }
-        return new CodeTree[]{expressionBuilder.build(), assertionBuilder.build()};
-    }
-
-    private static Map<Variable, CodeTree> castBoundTypes(Map<Variable, LocalVariable> bindings) {
-        Map<Variable, CodeTree> resolvedBindings = new HashMap<>();
-        for (Variable variable : bindings.keySet()) {
-            LocalVariable localVariable = bindings.get(variable);
-            CodeTree resolved = localVariable.createReference();
-            TypeMirror sourceType = localVariable.getTypeMirror();
-            TypeMirror targetType = variable.getResolvedTargetType();
-            if (targetType == null) {
-                targetType = variable.getResolvedType();
-            }
-            if (!ElementUtils.isAssignable(sourceType, targetType)) {
-                resolved = CodeTreeBuilder.createBuilder().cast(targetType, resolved).build();
-            }
-            resolvedBindings.put(variable, resolved);
-        }
-        return resolvedBindings;
-    }
-
-    private static Map<Variable, LocalVariable> bindExpressionValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError {
-        Map<Variable, LocalVariable> bindings = new HashMap<>();
-
-        Set<Variable> boundVariables = expression.findBoundVariables();
-        if (specialization == null && !boundVariables.isEmpty()) {
-            throw new AssertionError("Cannot bind guard variable in non-specialization group. yet.");
-        }
-
-        // resolve bindings for local context
-        for (Variable variable : boundVariables) {
-            Parameter resolvedParameter = specialization.findByVariable(variable.getResolvedVariable());
-            if (resolvedParameter != null) {
-                LocalVariable localVariable;
-                if (resolvedParameter.getSpecification().isSignature()) {
-                    NodeExecutionData execution = resolvedParameter.getSpecification().getExecution();
-                    localVariable = currentValues.getValue(execution);
-                } else {
-                    localVariable = currentValues.get(resolvedParameter.getLocalName());
-                }
-                if (localVariable != null) {
-                    bindings.put(variable, localVariable);
-                }
-            }
-        }
-        return bindings;
-    }
-
-    private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues,
-                    SpecializationBody specializationExecution) {
-        CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder();
-        CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder();
-        for (TypeGuard typeGuard : typeGuards) {
-            int signatureIndex = typeGuard.getSignatureIndex();
-            LocalVariable value = currentValues.getValue(signatureIndex);
-            TypeMirror targetType = typeGuard.getType();
-            if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) {
-                continue;
-            }
-            NodeExecutionData execution = node.getChildExecutions().get(signatureIndex);
-            if (!checksBuilder.isEmpty()) {
-                checksBuilder.string(" && ");
-            }
-
-            CodeTreeBuilder checkBuilder = checksBuilder.create();
-            CodeTreeBuilder castBuilder = checksBuilder.create();
-
-            LocalVariable shortCircuit = currentValues.getShortCircuit(execution);
-            if (shortCircuit != null) {
-                checkBuilder.string("(");
-                CodeTreeBuilder referenceBuilder = checkBuilder.create();
-                if (!ElementUtils.isPrimitive(shortCircuit.getTypeMirror())) {
-                    referenceBuilder.string("(boolean) ");
-                }
-                referenceBuilder.tree(shortCircuit.createReference());
-                checkBuilder.string("!").tree(referenceBuilder.build());
-                checkBuilder.string(" || ");
-                castBuilder.tree(referenceBuilder.build()).string(" ? ");
-            }
-
-            List<ImplicitCastData> sourceTypes = typeSystem.lookupByTargetType(targetType);
-            CodeTree valueReference = value.createReference();
-            if (sourceTypes.isEmpty()) {
-                checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, value.createReference()));
-                castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference));
-            } else {
-                ImplicitCastOptimization opt = options.implicitCastOptimization();
-                if (specializationExecution.isFastPath() && !opt.isNone()) {
-                    if (opt.isDuplicateTail()) {
-                        String typeHintField = implicitClassFieldName(execution);
-                        checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, typeHintField));
-                        castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, typeHintField));
-                    } else if (opt.isMergeCasts()) {
-                        checkBuilder.tree(ImplicitCastNodeFactory.check(implicitNodeFieldName(execution), valueReference));
-                        castBuilder.tree(ImplicitCastNodeFactory.cast(implicitNodeFieldName(execution), valueReference));
-                    } else {
-                        throw new AssertionError("implicit cast opt");
-                    }
-                } else {
-                    checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, null));
-                    castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, null));
-                }
-            }
-
-            if (shortCircuit != null) {
-                checkBuilder.string(")");
-                castBuilder.string(" : ").defaultValue(targetType);
-            }
-
-            if (castGuards == null || castGuards.contains(typeGuard)) {
-                LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null);
-                currentValues.setValue(execution, castVariable);
-                localsBuilder.tree(castVariable.createDeclaration(castBuilder.build()));
-            }
-
-            checksBuilder.tree(checkBuilder.build());
-        }
-
-        if (specialization != null && !specializationExecution.isFastPath()) {
-            for (CacheExpression cache : specialization.getCaches()) {
-                if (specialization.isCacheBoundByGuard(cache)) {
-                    initializeCache(localsBuilder, specialization, cache, currentValues);
-                }
-            }
-        }
-
-        return new CodeTree[]{checksBuilder.build(), localsBuilder.build()};
-    }
-
-    private void initializeCache(CodeTreeBuilder builder, SpecializationData specialization, CacheExpression cache, LocalContext currentValues) {
-        CodeTree initializer = DSLExpressionGenerator.write(cache.getExpression(), accessParent(null), castBoundTypes(bindExpressionValues(cache.getExpression(), specialization, currentValues)));
-        String name = cache.getParameter().getLocalName();
-        // multiple specializations might use the same name
-        String varName = name + specialization.getIndex();
-        TypeMirror type = cache.getParameter().getType();
-        builder.declaration(type, varName, initializer);
-        currentValues.set(name, new LocalVariable(type, varName, null, null));
-    }
-
-    public static final class LocalContext {
-
-        private final NodeGenFactory factory;
-        private final Map<String, LocalVariable> values = new HashMap<>();
-
-        private LocalContext(NodeGenFactory factory) {
-            this.factory = factory;
-        }
-
-        public void loadFastPathState(SpecializationData specialization) {
-            for (CacheExpression cache : specialization.getCaches()) {
-                Parameter cacheParameter = cache.getParameter();
-                String name = cacheParameter.getVariableElement().getSimpleName().toString();
-                set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null));
-            }
-
-            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
-                String name = assumptionName(assumption);
-                TypeMirror type = assumption.getExpression().getResolvedType();
-                set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null));
-            }
-        }
-
-        public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, int varArgsThreshold, String... optionalArguments) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name);
-            addParametersTo(method, varArgsThreshold, optionalArguments);
-            return method;
-        }
-
-        public static LocalContext load(NodeGenFactory factory, ExecutableTypeData type, int varargsThreshold) {
-            LocalContext context = new LocalContext(factory);
-            context.loadEvaluatedValues(type, varargsThreshold);
-            return context;
-        }
-
-        private void loadEvaluatedValues(ExecutableTypeData executedType, int varargsThreshold) {
-            TypeMirror frame = executedType.getFrameParameter();
-            if (frame == null) {
-                removeValue(FRAME_VALUE);
-            } else {
-                set(FRAME_VALUE, new LocalVariable(frame, FRAME_VALUE, null, null));
-            }
-            for (NodeFieldData field : factory.node.getFields()) {
-                String fieldName = fieldValueName(field);
-                values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null));
-            }
-            boolean varargs = needsVarargs(false, varargsThreshold);
-            List<TypeMirror> evaluatedParameter = executedType.getEvaluatedParameters();
-            int evaluatedIndex = 0;
-            for (int executionIndex = 0; executionIndex < factory.node.getExecutionCount(); executionIndex++) {
-                NodeExecutionData execution = factory.node.getChildExecutions().get(executionIndex);
-                if (execution.isShortCircuit()) {
-                    if (evaluatedIndex < executedType.getEvaluatedCount()) {
-                        TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex);
-                        LocalVariable shortCircuit = createShortCircuitValue(execution).newType(evaluatedType);
-                        if (varargs) {
-                            shortCircuit = shortCircuit.accessWith(createReadVarargs(evaluatedIndex));
-                        }
-                        values.put(shortCircuit.getName(), shortCircuit.makeOriginal());
-                        evaluatedIndex++;
-                    }
-                }
-                if (evaluatedIndex < executedType.getEvaluatedCount()) {
-                    TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex);
-                    LocalVariable value = createValue(execution, evaluatedType);
-                    if (varargs) {
-                        value = value.accessWith(createReadVarargs(evaluatedIndex));
-                    }
-                    values.put(value.getName(), value.makeOriginal());
-                    evaluatedIndex++;
-                }
-            }
-        }
-
-        public static LocalContext load(NodeGenFactory factory) {
-            return load(factory, factory.createSpecializationNodeSignature(factory.node.getSignatureSize()), factory.varArgsThreshold);
-        }
-
-        public LocalContext copy() {
-            LocalContext copy = new LocalContext(factory);
-            copy.values.putAll(values);
-            return copy;
-        }
-
-        private static String fieldValueName(NodeFieldData field) {
-            return field.getName() + "Value";
-        }
-
-        @SuppressWarnings("static-method")
-        public LocalVariable createValue(NodeExecutionData execution, TypeMirror type) {
-            return new LocalVariable(type, valueName(execution), null, null);
-        }
-
-        public LocalVariable createShortCircuitValue(NodeExecutionData execution) {
-            return new LocalVariable(factory.getType(boolean.class), shortCircuitName(execution), null, null);
-        }
-
-        private static String valueName(NodeExecutionData execution) {
-            return execution.getName() + "Value";
-        }
-
-        private static String shortCircuitName(NodeExecutionData execution) {
-            return "has" + ElementUtils.firstLetterUpperCase(valueName(execution));
-        }
-
-        public void set(String id, LocalVariable var) {
-            values.put(id, var);
-        }
-
-        public LocalVariable get(String id) {
-            return values.get(id);
-        }
-
-        public LocalVariable get(Parameter parameter, int signatureIndex) {
-            LocalVariable var = get(parameter.getLocalName());
-            if (var == null && parameter.getSpecification().isSignature()) {
-                // lookup by signature index for executeWith
-                List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
-                if (signatureIndex < childExecutions.size() && signatureIndex >= 0) {
-                    NodeExecutionData execution = childExecutions.get(signatureIndex);
-                    var = getValue(execution);
-                }
-            }
-            return var;
-        }
-
-        public LocalVariable getValue(NodeExecutionData execution) {
-            return get(valueName(execution));
-        }
-
-        public LocalVariable getValue(int signatureIndex) {
-            List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
-            if (signatureIndex < childExecutions.size()) {
-                return getValue(childExecutions.get(signatureIndex));
-            } else {
-                return null;
-            }
-        }
-
-        public void removeValue(String id) {
-            values.remove(id);
-        }
-
-        public void setValue(NodeExecutionData execution, LocalVariable var) {
-            values.put(valueName(execution), var);
-        }
-
-        public void setShortCircuitValue(NodeExecutionData execution, LocalVariable var) {
-            if (var == null) {
-                return;
-            }
-            values.put(shortCircuitName(execution), var);
-        }
-
-        private boolean needsVarargs(boolean requireLoaded, int varArgsThreshold) {
-            int size = 0;
-            for (NodeExecutionData execution : factory.node.getChildExecutions()) {
-                if (requireLoaded && getValue(execution) == null) {
-                    continue;
-                }
-                if (execution.isShortCircuit()) {
-                    size += 2;
-                } else {
-                    size++;
-                }
-            }
-            return size >= varArgsThreshold;
-        }
-
-        private static CodeTree createReadVarargs(int i) {
-            return CodeTreeBuilder.createBuilder().string("args_[").string(String.valueOf(i)).string("]").build();
-        }
-
-        public void addReferencesTo(CodeTreeBuilder builder, String... optionalNames) {
-            for (String var : optionalNames) {
-                LocalVariable local = values.get(var);
-                if (local == null) {
-                    builder.nullLiteral();
-                } else {
-                    builder.tree(local.createReference());
-                }
-            }
-
-            List<NodeExecutionData> executions = factory.node.getChildExecutions();
-            for (NodeExecutionData execution : executions) {
-                if (execution.isShortCircuit()) {
-                    LocalVariable shortCircuitVar = getShortCircuit(execution);
-                    if (shortCircuitVar != null) {
-                        builder.tree(shortCircuitVar.createReference());
-                    }
-                }
-                LocalVariable var = getValue(execution);
-                if (var != null) {
-                    builder.startGroup();
-                    if (executions.size() == 1 && ElementUtils.typeEquals(var.getTypeMirror(), factory.getType(Object[].class))) {
-                        // if the current type is Object[] do not use varargs for a single argument
-                        builder.string("(Object) ");
-                    }
-                    builder.tree(var.createReference());
-                    builder.end();
-                }
-            }
-        }
-
-        public void addParametersTo(CodeExecutableElement method, int varArgsThreshold, String... optionalNames) {
-            for (String var : optionalNames) {
-                LocalVariable local = values.get(var);
-                if (local != null) {
-                    method.addParameter(local.createParameter());
-                }
-            }
-            if (needsVarargs(true, varArgsThreshold)) {
-                method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_"));
-                method.setVarArgs(true);
-            } else {
-                for (NodeExecutionData execution : factory.node.getChildExecutions()) {
-                    if (execution.isShortCircuit()) {
-                        LocalVariable shortCircuitVar = getShortCircuit(execution);
-                        if (shortCircuitVar != null) {
-                            method.addParameter(shortCircuitVar.createParameter());
-                        }
-                    }
-
-                    LocalVariable var = getValue(execution);
-                    if (var != null) {
-                        method.addParameter(var.createParameter());
-                    }
-                }
-            }
-        }
-
-        private LocalVariable getShortCircuit(NodeExecutionData execution) {
-            return values.get(shortCircuitName(execution));
-        }
-
-        @Override
-        public String toString() {
-            return "LocalContext [values=" + values + "]";
-        }
-
-    }
-
-    public static final class LocalVariable {
-
-        private final TypeMirror typeMirror;
-        private final CodeTree accessorTree;
-        private final String name;
-        private final LocalVariable previous;
-
-        public static LocalVariable fromParameter(Parameter parameter) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            String name = null;
-            if (execution == null) {
-                name = parameter.getLocalName();
-            } else {
-                name = createName(execution);
-            }
-            return new LocalVariable(parameter.getType(), name, null, null);
-        }
-
-        private LocalVariable(TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) {
-            Objects.requireNonNull(typeMirror);
-            this.typeMirror = typeMirror;
-            this.accessorTree = accessorTree;
-            this.name = name;
-            this.previous = previous;
-        }
-
-        public String getShortCircuitName() {
-            return "has" + ElementUtils.firstLetterUpperCase(getName());
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        private static String createNextName(String name) {
-            return name + "_";
-        }
-
-        private static String createName(NodeExecutionData execution) {
-            if (execution == null) {
-                return "<error>";
-            }
-            return execution.getName() + "Value";
-        }
-
-        public TypeMirror getTypeMirror() {
-            return typeMirror;
-        }
-
-        public CodeVariableElement createParameter() {
-            return new CodeVariableElement(getTypeMirror(), getName());
-        }
-
-        public CodeTree createDeclaration(CodeTree init) {
-            return CodeTreeBuilder.createBuilder().declaration(getTypeMirror(), getName(), init).build();
-        }
-
-        public CodeTree createReference() {
-            if (accessorTree != null) {
-                return accessorTree;
-            } else {
-                return CodeTreeBuilder.singleString(getName());
-            }
-        }
-
-        public LocalVariable newType(TypeMirror newType) {
-            return new LocalVariable(newType, name, accessorTree, this);
-        }
-
-        public LocalVariable accessWith(CodeTree tree) {
-            return new LocalVariable(typeMirror, name, tree, this);
-        }
-
-        public LocalVariable nextName() {
-            return new LocalVariable(typeMirror, createNextName(name), accessorTree, this);
-        }
-
-        public LocalVariable makeOriginal() {
-            return new LocalVariable(typeMirror, name, accessorTree, null);
-        }
-
-        public LocalVariable original() {
-            LocalVariable variable = this;
-            while (variable.previous != null) {
-                variable = variable.previous;
-            }
-            return variable;
-        }
-
-        public LocalVariable makeGeneric(ProcessorContext context) {
-            return newType(context.getType(Object.class));
-        }
-
-        @Override
-        public String toString() {
-            return "Local[type = " + getTypeMirror() + ", name = " + name + ", accessWith = " + accessorTree + "]";
-        }
-
-    }
-
-    private abstract class SpecializationBody {
-
-        private final boolean fastPath;
-        private final boolean needsCastedValues;
-
-        public SpecializationBody(boolean fastPath, boolean needsCastedValues) {
-            this.fastPath = fastPath;
-            this.needsCastedValues = needsCastedValues;
-        }
-
-        public final boolean isFastPath() {
-            return fastPath;
-        }
-
-        public final boolean needsCastedValues() {
-            return needsCastedValues;
-        }
-
-        public abstract CodeTree createBody(SpecializationData specialization, LocalContext currentValues);
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,461 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.generator;
-
-import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> {
-
-    private static final String LOCAL_VALUE = "value";
-
-    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, String content) {
-        return cast(typeSystem, type, CodeTreeBuilder.singleString(content));
-    }
-
-    public static CodeTree implicitType(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
-        if (ElementUtils.isObject(type)) {
-            return value;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(typeSystem, type)).tree(value);
-        builder.end();
-        return builder.build();
-    }
-
-    public static CodeTree invokeImplicitCast(TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression);
-        builder.end();
-        return builder.build();
-    }
-
-    public static CodeTree implicitCheck(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
-        return callImplictMethod(typeSystem, type, isImplicitTypeMethodName(typeSystem, type), value, typeHint);
-    }
-
-    public static CodeTree implicitExpect(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
-        return callImplictMethod(typeSystem, type, expectImplicitTypeMethodName(typeSystem, type), value, typeHint);
-    }
-
-    public static CodeTree implicitCast(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
-        return callImplictMethod(typeSystem, type, asImplicitTypeMethodName(typeSystem, type), value, typeHint);
-    }
-
-    private static CodeTree callImplictMethod(TypeSystemData typeSystem, TypeMirror type, String methodName, CodeTree value, String typeHint) {
-        if (ElementUtils.isObject(type)) {
-            return value;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        builder.startStaticCall(createTypeSystemGen(typeSystem), methodName).tree(value);
-        if (typeHint != null) {
-            builder.string(typeHint);
-        }
-        builder.end();
-        return builder.build();
-    }
-
-    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
-        if (ElementUtils.isObject(type)) {
-            return content;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        TypeCastData cast = typeSystem.getCast(type);
-        if (cast == null) {
-            builder.cast(ElementUtils.fillInGenericWildcards(type), content);
-        } else {
-            builder.startStaticCall(typeSystem.getTemplateType().asType(), cast.getMethodName()).tree(content).end();
-        }
-        return builder.build();
-    }
-
-    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
-        if (ElementUtils.isObject(type) || ElementUtils.isVoid(type)) {
-            return content;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-        if (typeSystem.hasType(type)) {
-            builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(typeSystem, type)).tree(content).end();
-        } else {
-            builder.startCall(expectTypeMethodName(typeSystem, type)).tree(content).end();
-        }
-
-        return builder.build();
-    }
-
-    public static CodeExecutableElement createExpectMethod(Modifier visibility, TypeSystemData typeSystem, TypeMirror sourceTypeOriginal, TypeMirror expectedTypeOriginal) {
-        TypeMirror expectedType = ElementUtils.fillInGenericWildcards(expectedTypeOriginal);
-        TypeMirror sourceType = ElementUtils.fillInGenericWildcards(sourceTypeOriginal);
-        if (ElementUtils.isObject(expectedType) || ElementUtils.isVoid(expectedType)) {
-            return null;
-        }
-
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), expectedType, TypeSystemCodeGenerator.expectTypeMethodName(typeSystem, expectedType));
-        method.setVisibility(visibility);
-        method.addParameter(new CodeVariableElement(sourceType, LOCAL_VALUE));
-        method.addThrownType(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException());
-
-        CodeTreeBuilder body = method.createBuilder();
-        body.startIf().tree(check(typeSystem, expectedType, LOCAL_VALUE)).end().startBlock();
-        body.startReturn().tree(cast(typeSystem, expectedType, LOCAL_VALUE)).end();
-        body.end();
-        body.startThrow().startNew(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
-        return method;
-    }
-
-    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror targetType, CodeTree content) {
-        if (sourceType != null && !ElementUtils.needsCastTo(sourceType, targetType)) {
-            return content;
-        } else {
-            return expect(typeSystem, targetType, content);
-        }
-    }
-
-    public static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) {
-        return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem));
-    }
-
-    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, String content) {
-        return check(typeSystem, type, CodeTreeBuilder.singleString(content));
-    }
-
-    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
-        if (ElementUtils.isObject(type)) {
-            return content;
-        }
-        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
-
-        TypeCheckData check = typeSystem.getCheck(type);
-        if (check == null) {
-            builder.instanceOf(content, ElementUtils.boxType(typeSystem.getContext(), type));
-        } else {
-            builder.startStaticCall(typeSystem.getTemplateType().asType(), check.getMethodName()).tree(content).end();
-        }
-        return builder.build();
-    }
-
-    public static String isTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "is" + getTypeId(typeSystem, type);
-    }
-
-    private static String getTypeId(TypeSystemData typeSystem, TypeMirror type) {
-        return ElementUtils.getTypeId(typeSystem.boxType(type));
-    }
-
-    static String isImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "isImplicit" + getTypeId(typeSystem, type);
-    }
-
-    public static String asTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "as" + getTypeId(typeSystem, type);
-    }
-
-    static String asImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "asImplicit" + getTypeId(typeSystem, type);
-    }
-
-    static String expectImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "expectImplicit" + getTypeId(typeSystem, type);
-    }
-
-    static String getImplicitClass(TypeSystemData typeSystem, TypeMirror type) {
-        return "getImplicit" + getTypeId(typeSystem, type) + "Class";
-    }
-
-    public static String expectTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
-        return "expect" + getTypeId(typeSystem, type);
-    }
-
-    static String typeName(TypeSystemData typeSystem) {
-        String name = getSimpleName(typeSystem.getTemplateType());
-        return name + "Gen";
-    }
-
-    static String singletonName(TypeSystemData type) {
-        return createConstantName(getSimpleName(type.getTemplateType().asType()));
-    }
-
-    @Override
-    public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) {
-        CodeTypeElement clazz = new TypeClassFactory(context, typeSystem).create();
-
-        if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) {
-            for (TypeMirror type : typeSystem.lookupTargetTypes()) {
-                clazz.add(new ImplicitCastNodeFactory(context, typeSystem, type).create());
-            }
-        }
-        return clazz;
-    }
-
-    private static class TypeClassFactory {
-
-        private final ProcessorContext context;
-        private final TypeSystemData typeSystem;
-
-        public TypeClassFactory(ProcessorContext context, TypeSystemData typeSystem) {
-            this.context = context;
-            this.typeSystem = typeSystem;
-        }
-
-        public CodeTypeElement create() {
-            String name = typeName(typeSystem);
-            CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType());
-
-            clazz.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), clazz));
-            CodeVariableElement singleton = createSingleton(clazz);
-            clazz.add(singleton);
-
-            for (TypeMirror type : typeSystem.getLegacyTypes()) {
-                if (ElementUtils.isVoid(type) || ElementUtils.isObject(type)) {
-                    continue;
-                }
-
-                clazz.addOptional(createIsTypeMethod(type));
-                clazz.addOptional(createAsTypeMethod(type));
-                clazz.addOptional(createExpectTypeMethod(type, context.getType(Object.class)));
-
-            }
-
-            List<TypeMirror> lookupTargetTypes = typeSystem.lookupTargetTypes();
-            for (TypeMirror type : lookupTargetTypes) {
-                clazz.add(createAsImplicitTypeMethod(type, false));
-                if (typeSystem.getOptions().implicitCastOptimization().isNone()) {
-                    clazz.add(createExpectImplicitTypeMethod(type, false));
-                }
-                clazz.add(createIsImplicitTypeMethod(type, false));
-
-                if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) {
-                    clazz.add(createAsImplicitTypeMethod(type, true));
-                    clazz.add(createExpectImplicitTypeMethod(type, true));
-                    clazz.add(createIsImplicitTypeMethod(type, true));
-                    clazz.add(createGetImplicitClass(type));
-                }
-            }
-            return clazz;
-        }
-
-        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
-            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem));
-            field.createInitBuilder().startNew(clazz.asType()).end();
-
-            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror((DeclaredType) context.getType(Deprecated.class));
-            field.getAnnotationMirrors().add(annotationMirror);
-
-            return field;
-        }
-
-        private CodeExecutableElement createIsImplicitTypeMethod(TypeMirror type, boolean typed) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(typeSystem, type));
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-            if (typed) {
-                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
-            }
-            CodeTreeBuilder builder = method.createBuilder();
-
-            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            builder.startReturn();
-            String sep = "";
-            for (TypeMirror sourceType : sourceTypes) {
-                builder.string(sep);
-                if (typed) {
-                    builder.string("(typeHint == ").typeLiteral(sourceType).string(" && ");
-                }
-                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
-                if (typed) {
-                    builder.string(")");
-                }
-                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
-                    builder.newLine();
-                }
-                if (sep.equals("")) {
-                    builder.startIndention();
-                }
-                sep = " || ";
-            }
-            builder.end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createAsImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
-            String name = asImplicitTypeMethodName(typeSystem, type);
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-            if (useTypeHint) {
-                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
-            }
-
-            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeMirror sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                if (useTypeHint) {
-                    builder.string("typeHint == ").typeLiteral(sourceType);
-                } else {
-                    builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
-                }
-
-                builder.end().startBlock();
-
-                builder.startReturn();
-                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
-                if (cast != null) {
-                    builder.startCall(cast.getMethodName());
-                }
-                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
-                if (cast != null) {
-                    builder.end();
-                }
-                builder.end();
-                builder.end();
-            }
-
-            builder.startElseBlock();
-            builder.tree(createTransferToInterpreterAndInvalidate());
-            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createExpectImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
-            String name = expectImplicitTypeMethodName(typeSystem, type);
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-            if (useTypeHint) {
-                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
-            }
-            method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
-
-            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
-
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeMirror sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                if (useTypeHint) {
-                    builder.string("typeHint == ").typeLiteral(sourceType);
-                    builder.string(" && ");
-                }
-                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
-
-                builder.end().startBlock();
-
-                builder.startReturn();
-                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
-                if (cast != null) {
-                    builder.startCall(cast.getMethodName());
-                }
-                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
-                if (cast != null) {
-                    builder.end();
-                }
-                builder.end();
-                builder.end();
-            }
-
-            builder.startElseBlock();
-            builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string(LOCAL_VALUE).end().end();
-            builder.end();
-            return method;
-        }
-
-        private CodeExecutableElement createGetImplicitClass(TypeMirror type) {
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(typeSystem, type));
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-
-            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
-            CodeTreeBuilder builder = method.createBuilder();
-            boolean elseIf = false;
-            for (TypeMirror sourceType : sourceTypes) {
-                elseIf = builder.startIf(elseIf);
-                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)).end();
-                builder.end().startBlock();
-                builder.startReturn().typeLiteral(sourceType).end();
-                builder.end();
-            }
-
-            builder.startElseIf().string(LOCAL_VALUE).string(" == ").nullLiteral().end();
-            builder.startBlock();
-            builder.startReturn().typeLiteral(context.getType(Object.class)).end();
-            builder.end();
-
-            builder.startElseBlock();
-            builder.tree(createTransferToInterpreterAndInvalidate());
-            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
-            builder.end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createIsTypeMethod(TypeMirror type) {
-            if (typeSystem.getCheck(type) != null) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(typeSystem, type));
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-
-            CodeTreeBuilder body = method.createBuilder();
-            body.startReturn().tree(check(typeSystem, type, LOCAL_VALUE)).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createAsTypeMethod(TypeMirror type) {
-            if (typeSystem.getCast(type) != null) {
-                return null;
-            }
-
-            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, TypeSystemCodeGenerator.asTypeMethodName(typeSystem, type));
-            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
-
-            CodeTreeBuilder body = method.createBuilder();
-            String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(typeSystem, type) + ": " + ElementUtils.getSimpleName(type) + " expected";
-            body.startAssert().tree(check(typeSystem, type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end();
-            body.startReturn().tree(cast(typeSystem, type, LOCAL_VALUE)).end();
-
-            return method;
-        }
-
-        private CodeExecutableElement createExpectTypeMethod(TypeMirror expectedType, TypeMirror sourceType) {
-            return createExpectMethod(Modifier.PUBLIC, typeSystem, sourceType, expectedType);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1256 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public class ElementUtils {
-
-    public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) {
-        if (element.isArray()) {
-            return processingEnv.getTypeUtils().getArrayType(getType(processingEnv, element.getComponentType()));
-        }
-        if (element.isPrimitive()) {
-            if (element == void.class) {
-                return processingEnv.getTypeUtils().getNoType(TypeKind.VOID);
-            }
-            TypeKind typeKind;
-            if (element == boolean.class) {
-                typeKind = TypeKind.BOOLEAN;
-            } else if (element == byte.class) {
-                typeKind = TypeKind.BYTE;
-            } else if (element == short.class) {
-                typeKind = TypeKind.SHORT;
-            } else if (element == char.class) {
-                typeKind = TypeKind.CHAR;
-            } else if (element == int.class) {
-                typeKind = TypeKind.INT;
-            } else if (element == long.class) {
-                typeKind = TypeKind.LONG;
-            } else if (element == float.class) {
-                typeKind = TypeKind.FLOAT;
-            } else if (element == double.class) {
-                typeKind = TypeKind.DOUBLE;
-            } else {
-                assert false;
-                return null;
-            }
-            return processingEnv.getTypeUtils().getPrimitiveType(typeKind);
-        } else {
-            TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(element.getCanonicalName());
-            if (typeElement == null) {
-                return null;
-            }
-            return typeElement.asType();
-        }
-    }
-
-    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) {
-        if (typeEquals(sourceType, targetType)) {
-            return false;
-        } else if (isObject(targetType)) {
-            return false;
-        } else if (isVoid(targetType)) {
-            return false;
-        } else if (isAssignable(sourceType, targetType)) {
-            return false;
-        }
-        return true;
-    }
-
-    public static String createReferenceName(ExecutableElement method) {
-        StringBuilder b = new StringBuilder();
-
-        b.append(method.getSimpleName().toString());
-        b.append("(");
-
-        String sep = "";
-        for (VariableElement parameter : method.getParameters()) {
-            b.append(sep);
-            b.append(ElementUtils.getSimpleName(parameter.asType()));
-            sep = ", ";
-        }
-
-        b.append(")");
-        return b.toString();
-    }
-
-    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
-        if (primitiveType == null) {
-            return null;
-        }
-        TypeMirror boxedType = primitiveType;
-        if (boxedType.getKind().isPrimitive()) {
-            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
-        }
-        return boxedType;
-    }
-
-    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
-        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
-    }
-
-    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
-                    Class<? extends Annotation> annotationClass) {
-        List<AnnotationMirror> result = new ArrayList<>();
-        if (markerAnnotation != null) {
-            result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
-        }
-        AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
-        if (explicit != null) {
-            result.add(explicit);
-        }
-        return result;
-    }
-
-    public static TypeMirror getCommonSuperType(ProcessorContext context, Collection<TypeMirror> types) {
-        if (types.isEmpty()) {
-            return context.getType(Object.class);
-        }
-        Iterator<TypeMirror> typesIterator = types.iterator();
-        TypeMirror prev = typesIterator.next();
-        while (typesIterator.hasNext()) {
-            prev = getCommonSuperType(context, prev, typesIterator.next());
-        }
-        return prev;
-    }
-
-    private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
-        if (typeEquals(type1, type2)) {
-            return type1;
-        }
-        if (isVoid(type1)) {
-            return type2;
-        } else if (isVoid(type2)) {
-            return type1;
-        }
-        if (isObject(type1)) {
-            return type1;
-        } else if (isObject(type2)) {
-            return type2;
-        }
-
-        if (isPrimitive(type1) || isPrimitive(type2)) {
-            return context.getType(Object.class);
-        }
-
-        if (isSubtype(type1, type2)) {
-            return type2;
-        } else if (isSubtype(type2, type1)) {
-            return type1;
-        }
-
-        TypeElement element1 = fromTypeMirror(type1);
-        TypeElement element2 = fromTypeMirror(type2);
-
-        if (element1 == null || element2 == null) {
-            return context.getType(Object.class);
-        }
-
-        List<TypeElement> element1Types = getSuperTypes(element1);
-        List<TypeElement> element2Types = getSuperTypes(element2);
-
-        for (TypeElement superType1 : element1Types) {
-            for (TypeElement superType2 : element2Types) {
-                if (typeEquals(superType1.asType(), superType2.asType())) {
-                    return superType2.asType();
-                }
-            }
-        }
-
-        return context.getType(Object.class);
-    }
-
-    public static String getReadableSignature(ExecutableElement method) {
-        StringBuilder builder = new StringBuilder();
-        builder.append(method.getSimpleName().toString());
-        builder.append("(");
-        String sep = "";
-        for (VariableElement var : method.getParameters()) {
-            builder.append(sep);
-            builder.append(getSimpleName(var.asType()));
-            sep = ", ";
-        }
-        builder.append(")");
-        return builder.toString();
-    }
-
-    public static boolean hasError(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case INT:
-            case SHORT:
-            case LONG:
-            case DECLARED:
-            case VOID:
-            case TYPEVAR:
-                return false;
-            case ARRAY:
-                return hasError(((ArrayType) mirror).getComponentType());
-            case ERROR:
-                return true;
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isSubtypeBoxed(ProcessorContext context, TypeMirror from, TypeMirror to) {
-        return isSubtype(boxType(context, from), boxType(context, to));
-    }
-
-    public static boolean isSubtype(TypeMirror type1, TypeMirror type2) {
-        if (type1 instanceof CodeTypeMirror || type2 instanceof CodeTypeMirror) {
-            throw new UnsupportedOperationException();
-        }
-        return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2);
-    }
-
-    public static boolean isAssignable(TypeMirror from, TypeMirror to) {
-        if (typeEquals(from, to)) {
-            return true;
-        } else if (isVoid(to)) {
-            return true;
-        } else if (isObject(to)) {
-            return true;
-        }
-        ProcessorContext context = ProcessorContext.getInstance();
-        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
-            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
-        } else {
-            return isAssignableImpl(from, to);
-        }
-    }
-
-    private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) {
-        // JLS 5.1.1 identity conversion
-        if (ElementUtils.typeEquals(from, to)) {
-            return true;
-        }
-
-        if (isObject(to)) {
-            return true;
-        }
-
-        // JLS 5.1.2 widening primitives
-        if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) {
-            TypeKind fromKind = from.getKind();
-            TypeKind toKind = to.getKind();
-            switch (fromKind) {
-                case BYTE:
-                    switch (toKind) {
-                        case SHORT:
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case SHORT:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case CHAR:
-                    switch (toKind) {
-                        case INT:
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case INT:
-                    switch (toKind) {
-                        case LONG:
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case LONG:
-                    switch (toKind) {
-                        case FLOAT:
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-                case FLOAT:
-                    switch (toKind) {
-                        case DOUBLE:
-                            return true;
-                    }
-                    break;
-
-            }
-            return false;
-        } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) {
-            return false;
-        }
-
-        if (from instanceof ArrayType && to instanceof ArrayType) {
-            return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
-        }
-
-        if (from instanceof ArrayType || to instanceof ArrayType) {
-            return false;
-        }
-
-        TypeElement fromType = ElementUtils.fromTypeMirror(from);
-        TypeElement toType = ElementUtils.fromTypeMirror(to);
-        if (fromType == null || toType == null) {
-            return false;
-        }
-        // JLS 5.1.6 narrowing reference conversion
-
-        List<TypeElement> superTypes = ElementUtils.getSuperTypes(fromType);
-        for (TypeElement superType : superTypes) {
-            if (ElementUtils.typeEquals(superType.asType(), to)) {
-                return true;
-            }
-        }
-
-        // TODO more spec
-        return false;
-    }
-
-    public static Set<Modifier> modifiers(Modifier... modifier) {
-        return new LinkedHashSet<>(Arrays.asList(modifier));
-    }
-
-    public static String getTypeId(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "Boolean";
-            case BYTE:
-                return "Byte";
-            case CHAR:
-                return "Char";
-            case DOUBLE:
-                return "Double";
-            case FLOAT:
-                return "Float";
-            case SHORT:
-                return "Short";
-            case INT:
-                return "Int";
-            case LONG:
-                return "Long";
-            case DECLARED:
-                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
-            case ARRAY:
-                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
-            case VOID:
-                return "Void";
-            case NULL:
-                return "Null";
-            case WILDCARD:
-                StringBuilder b = new StringBuilder();
-                WildcardType type = (WildcardType) mirror;
-                if (type.getExtendsBound() != null) {
-                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
-                } else if (type.getSuperBound() != null) {
-                    b.append("Super").append(getTypeId(type.getExtendsBound()));
-                }
-                return b.toString();
-            case TYPEVAR:
-                return "Any";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    public static String getSimpleName(TypeElement element) {
-        return getSimpleName(element.asType());
-    }
-
-    public static String getSimpleName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case FLOAT:
-                return "float";
-            case SHORT:
-                return "short";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getDeclaredName((DeclaredType) mirror, true);
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
-            case VOID:
-                return "void";
-            case NULL:
-                return "null";
-            case WILDCARD:
-                return getWildcardName((WildcardType) mirror);
-            case TYPEVAR:
-                return "?";
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
-        }
-    }
-
-    private static String getWildcardName(WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
-        }
-        return b.toString();
-    }
-
-    public static String getDeclaredName(DeclaredType element, boolean includeTypeVariables) {
-        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
-
-        if (!includeTypeVariables || element.getTypeArguments().size() == 0) {
-            return simpleName;
-        }
-
-        StringBuilder b = new StringBuilder(simpleName);
-        b.append("<");
-        if (element.getTypeArguments().size() > 0) {
-            for (int i = 0; i < element.getTypeArguments().size(); i++) {
-                b.append(getSimpleName(element.getTypeArguments().get(i)));
-                if (i < element.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public static String fixECJBinaryNameIssue(String name) {
-        if (name.contains("$")) {
-            int lastIndex = name.lastIndexOf('$');
-            return name.substring(lastIndex + 1, name.length());
-        }
-        return name;
-    }
-
-    public static String getQualifiedName(TypeElement element) {
-        String qualifiedName = element.getQualifiedName().toString();
-        if (qualifiedName.contains("$")) {
-            /*
-             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
-             * proper canonical class name. It leaves the $ in the qualified name of the class. So
-             * one instance of a TypeElement may be loaded in binary and one in source form. The
-             * current type comparison in #typeEquals compares by the qualified name so the
-             * qualified name must match. This is basically a hack to fix the returned qualified
-             * name of eclipse.
-             */
-            qualifiedName = qualifiedName.replace('$', '.');
-        }
-        return qualifiedName;
-    }
-
-    public static String getQualifiedName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-                return "boolean";
-            case BYTE:
-                return "byte";
-            case CHAR:
-                return "char";
-            case DOUBLE:
-                return "double";
-            case SHORT:
-                return "short";
-            case FLOAT:
-                return "float";
-            case INT:
-                return "int";
-            case LONG:
-                return "long";
-            case DECLARED:
-                return getQualifiedName(fromTypeMirror(mirror));
-            case ARRAY:
-                return getQualifiedName(((ArrayType) mirror).getComponentType());
-            case VOID:
-                return "void";
-            case NULL:
-                return "null";
-            case TYPEVAR:
-                return getSimpleName(mirror);
-            case ERROR:
-                throw new CompileErrorException("Type error " + mirror);
-            case EXECUTABLE:
-                return ((ExecutableType) mirror).toString();
-            case NONE:
-                return "$none";
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
-        }
-    }
-
-    public static boolean isVoid(TypeMirror mirror) {
-        return mirror != null && mirror.getKind() == TypeKind.VOID;
-    }
-
-    public static boolean isPrimitive(TypeMirror mirror) {
-        return mirror != null && mirror.getKind().isPrimitive();
-    }
-
-    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
-        List<TypeElement> types = getSuperTypes(element);
-        List<String> qualifiedNames = new ArrayList<>();
-        for (TypeElement type : types) {
-            qualifiedNames.add(getQualifiedName(type));
-        }
-        return qualifiedNames;
-    }
-
-    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
-        return ElementFilter.typesIn(element.getEnclosedElements());
-    }
-
-    public static boolean isEnclosedIn(Element enclosedIn, Element element) {
-        if (element == null) {
-            return false;
-        } else if (typeEquals(enclosedIn.asType(), element.asType())) {
-            return true;
-        } else {
-            return isEnclosedIn(enclosedIn, element.getEnclosingElement());
-        }
-    }
-
-    public static TypeElement findRootEnclosingType(Element element) {
-        List<Element> elements = getElementHierarchy(element);
-
-        for (int i = elements.size() - 1; i >= 0; i--) {
-            if (elements.get(i).getKind().isClass()) {
-                return (TypeElement) elements.get(i);
-            }
-        }
-
-        return null;
-    }
-
-    public static List<Element> getElementHierarchy(Element e) {
-        List<Element> elements = new ArrayList<>();
-        elements.add(e);
-
-        Element enclosing = e.getEnclosingElement();
-        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
-            elements.add(enclosing);
-            enclosing = enclosing.getEnclosingElement();
-        }
-        if (enclosing != null) {
-            elements.add(enclosing);
-        }
-        return elements;
-    }
-
-    public static TypeElement findNearestEnclosingType(Element element) {
-        List<Element> elements = getElementHierarchy(element);
-        for (Element e : elements) {
-            if (e.getKind().isClass() || e.getKind().isInterface()) {
-                return (TypeElement) e;
-            }
-        }
-        return null;
-    }
-
-    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        TypeElement superElement = getSuperType(element);
-        if (superElement != null) {
-            types.add(superElement);
-            types.addAll(getDirectSuperTypes(superElement));
-        }
-
-        return types;
-    }
-
-    /**
-     * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a
-     * given type element.
-     */
-    public static TypeElement getSuperType(TypeElement element) {
-        if (element.getSuperclass() != null) {
-            return fromTypeMirror(element.getSuperclass());
-        }
-        return null;
-    }
-
-    public static List<TypeElement> getSuperTypes(TypeElement element) {
-        List<TypeElement> types = new ArrayList<>();
-        List<TypeElement> superTypes = null;
-        List<TypeElement> superInterfaces = null;
-        TypeElement superElement = getSuperType(element);
-        if (superElement != null) {
-            types.add(superElement);
-            superTypes = getSuperTypes(superElement);
-        }
-        for (TypeMirror interfaceMirror : element.getInterfaces()) {
-            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
-            if (interfaceElement != null) {
-                types.add(interfaceElement);
-                if (superInterfaces == null) {
-                    superInterfaces = getSuperTypes(interfaceElement);
-                } else {
-                    superInterfaces.addAll(getSuperTypes(interfaceElement));
-                }
-            }
-        }
-
-        if (superTypes != null) {
-            types.addAll(superTypes);
-        }
-
-        if (superInterfaces != null) {
-            types.addAll(superInterfaces);
-        }
-
-        return types;
-    }
-
-    public static String getPackageName(TypeElement element) {
-        return findPackageElement(element).getQualifiedName().toString();
-    }
-
-    public static String getEnclosedQualifiedName(DeclaredType mirror) {
-        Element e = ((TypeElement) mirror.asElement()).getEnclosingElement();
-        if (e.getKind() == ElementKind.PACKAGE) {
-            return ((PackageElement) e).getQualifiedName().toString();
-        } else if (e.getKind().isInterface() || e.getKind().isClass()) {
-            return getQualifiedName((TypeElement) e);
-        } else {
-            return null;
-        }
-    }
-
-    public static String getPackageName(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-            case NULL:
-            case TYPEVAR:
-                return null;
-            case DECLARED:
-                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
-                if (pack == null) {
-                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
-                }
-                return pack.getQualifiedName().toString();
-            case ARRAY:
-                return getSimpleName(((ArrayType) mirror).getComponentType());
-            case EXECUTABLE:
-                return null;
-            default:
-                throw new RuntimeException("Unknown type specified " + mirror.getKind());
-        }
-    }
-
-    public static String createConstantName(String simpleName) {
-        // TODO use camel case to produce underscores.
-        return simpleName.toString().toUpperCase();
-    }
-
-    public static TypeElement fromTypeMirror(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case DECLARED:
-                return (TypeElement) ((DeclaredType) mirror).asElement();
-            case ARRAY:
-                return fromTypeMirror(((ArrayType) mirror).getComponentType());
-            default:
-                return null;
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
-        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
-        List<T> result = new ArrayList<>();
-
-        if (values != null) {
-            for (AnnotationValue value : values) {
-                T annotationValue = resolveAnnotationValue(expectedListType, value);
-                if (annotationValue != null) {
-                    result.add(annotationValue);
-                }
-            }
-        }
-        return result;
-    }
-
-    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
-        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
-    }
-
-    @SuppressWarnings({"unchecked"})
-    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
-        if (value == null) {
-            return null;
-        }
-
-        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
-        if (unboxedValue != null) {
-            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
-                return null;
-            }
-            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
-                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
-            }
-        }
-        return (T) unboxedValue;
-    }
-
-    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
-        ExecutableElement valueMethod = null;
-        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
-            if (method.getSimpleName().toString().equals(name)) {
-                valueMethod = method;
-                break;
-            }
-        }
-
-        if (valueMethod == null) {
-            return null;
-        }
-
-        AnnotationValue value = mirror.getElementValues().get(valueMethod);
-        if (value == null) {
-            value = valueMethod.getDefaultValue();
-        }
-
-        return value;
-    }
-
-    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
-
-        @Override
-        public Object visitBoolean(boolean b, Void p) {
-            return Boolean.valueOf(b);
-        }
-
-        @Override
-        public Object visitByte(byte b, Void p) {
-            return Byte.valueOf(b);
-        }
-
-        @Override
-        public Object visitChar(char c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitDouble(double d, Void p) {
-            return d;
-        }
-
-        @Override
-        public Object visitFloat(float f, Void p) {
-            return f;
-        }
-
-        @Override
-        public Object visitInt(int i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitLong(long i, Void p) {
-            return i;
-        }
-
-        @Override
-        public Object visitShort(short s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitString(String s, Void p) {
-            return s;
-        }
-
-        @Override
-        public Object visitType(TypeMirror t, Void p) {
-            return t;
-        }
-
-        @Override
-        public Object visitEnumConstant(VariableElement c, Void p) {
-            return c;
-        }
-
-        @Override
-        public Object visitAnnotation(AnnotationMirror a, Void p) {
-            return a;
-        }
-
-        @Override
-        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
-            return vals;
-        }
-
-    }
-
-    public static String printException(Throwable e) {
-        StringWriter string = new StringWriter();
-        PrintWriter writer = new PrintWriter(string);
-        e.printStackTrace(writer);
-        writer.flush();
-        string.flush();
-        return e.getMessage() + "\r\n" + string.toString();
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
-        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
-    }
-
-    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
-        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
-        return findAnnotationMirror(mirrors, expectedAnnotationType.asType());
-    }
-
-    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
-        return findAnnotationMirror(mirrors, expectedAnnotationType.asType());
-    }
-
-    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeMirror expectedAnnotationType) {
-        for (AnnotationMirror mirror : mirrors) {
-            if (typeEquals(mirror.getAnnotationType(), expectedAnnotationType)) {
-                return mirror;
-            }
-        }
-        return null;
-    }
-
-    public static PackageElement findPackageElement(Element type) {
-        List<Element> hierarchy = getElementHierarchy(type);
-        for (Element element : hierarchy) {
-            if (element.getKind() == ElementKind.PACKAGE) {
-                return (PackageElement) element;
-            }
-        }
-        return null;
-    }
-
-    public static String firstLetterUpperCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    public static String firstLetterLowerCase(String name) {
-        if (name == null || name.isEmpty()) {
-            return name;
-        }
-        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
-    }
-
-    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
-        method: for (ExecutableElement method : methods) {
-            if (!method.getSimpleName().toString().equals(name)) {
-                continue;
-            }
-            if (method.getParameters().size() != params.length) {
-                continue;
-            }
-            for (int i = 0; i < params.length; i++) {
-                TypeMirror param1 = params[i];
-                TypeMirror param2 = method.getParameters().get(i).asType();
-                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
-                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
-                        continue method;
-                    }
-                }
-            }
-            return method;
-        }
-        return null;
-    }
-
-    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
-        return !getDeclaredMethodsInSuperTypes(element, name, params).isEmpty();
-    }
-
-    /**
-     * Gets the methods in the super type hierarchy (excluding interfaces) that are overridden by a
-     * method in a subtype.
-     *
-     * @param declaringElement the subtype element declaring the method
-     * @param name the name of the method
-     * @param params the signature of the method
-     */
-    public static List<ExecutableElement> getDeclaredMethodsInSuperTypes(TypeElement declaringElement, String name, TypeMirror... params) {
-        List<ExecutableElement> superMethods = new ArrayList<>();
-        List<TypeElement> superElements = getSuperTypes(declaringElement);
-
-        for (TypeElement superElement : superElements) {
-            ExecutableElement superMethod = getDeclaredMethod(superElement, name, params);
-            if (superMethod != null) {
-                superMethods.add(superMethod);
-            }
-        }
-        return superMethods;
-    }
-
-    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
-        if (type1 == type2) {
-            return true;
-        } else if (type1 == null || type2 == null) {
-            return false;
-        } else {
-            if (type1.getKind() == type2.getKind()) {
-                return getUniqueIdentifier(type1).equals(getUniqueIdentifier(type2));
-            } else {
-                return false;
-            }
-        }
-    }
-
-    public static boolean areTypesCompatible(TypeMirror type1, TypeMirror type2) {
-        if (typeEquals(type1, type2)) {
-            return true;
-        } else if (kindIsIntegral(type1.getKind())) {
-            return kindIsIntegral(type2.getKind());
-        } else if (type1.getKind() == TypeKind.NULL) {
-            if (type2.getKind() == TypeKind.NULL) {
-                return false;
-            }
-            return true;
-        } else if (type2.getKind() == TypeKind.NULL) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private static boolean kindIsIntegral(TypeKind kind) {
-        return kind == TypeKind.BYTE || kind == TypeKind.SHORT || kind == TypeKind.INT || kind == TypeKind.LONG;
-    }
-
-    public static List<String> getUniqueIdentifiers(List<TypeMirror> typeMirror) {
-        List<String> ids = new ArrayList<>();
-        for (TypeMirror type : typeMirror) {
-            ids.add(getUniqueIdentifier(type));
-        }
-        return ids;
-    }
-
-    public static String getUniqueIdentifier(TypeMirror typeMirror) {
-        if (typeMirror.getKind() == TypeKind.ARRAY) {
-            return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]";
-        } else {
-            return getQualifiedName(typeMirror);
-        }
-    }
-
-    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
-        if (typeEquals(t1, t2)) {
-            return 0;
-        }
-        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
-        if (t1SuperSet.contains(getQualifiedName(t2))) {
-            return -1;
-        }
-
-        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
-        if (t2SuperSet.contains(getQualifiedName(t1))) {
-            return 1;
-        }
-        return 0;
-    }
-
-    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
-        if (ElementUtils.containsType(thrownTypes, exceptionType)) {
-            return true;
-        }
-
-        if (isRuntimeException(exceptionType)) {
-            return true;
-        }
-
-        // search for any super types
-        for (TypeElement typeElement : getSuperTypes(fromTypeMirror(exceptionType))) {
-            if (ElementUtils.containsType(thrownTypes, typeElement.asType())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public static void setVisibility(Set<Modifier> modifiers, Modifier visibility) {
-        Modifier current = getVisibility(modifiers);
-        if (current != visibility) {
-            if (current != null) {
-                modifiers.remove(current);
-            }
-            if (visibility != null) {
-                modifiers.add(visibility);
-            }
-        }
-    }
-
-    public static Modifier getVisibility(Set<Modifier> modifier) {
-        for (Modifier mod : modifier) {
-            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) {
-                return mod;
-            }
-        }
-        return null;
-    }
-
-    private static boolean isRuntimeException(TypeMirror type) {
-        Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
-        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || getQualifiedName(type).equals(RuntimeException.class.getCanonicalName());
-    }
-
-    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
-        for (TypeMirror otherTypeMirror : collection) {
-            if (typeEquals(otherTypeMirror, type)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean isTopLevelClass(TypeMirror importType) {
-        TypeElement type = fromTypeMirror(importType);
-        if (type != null && type.getEnclosingElement() != null) {
-            return !type.getEnclosingElement().getKind().isClass();
-        }
-        return true;
-    }
-
-    public static boolean isObject(TypeMirror actualType) {
-        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
-    }
-
-    public static TypeMirror fillInGenericWildcards(TypeMirror type) {
-        if (type.getKind() != TypeKind.DECLARED) {
-            return type;
-        }
-        DeclaredType declaredType = (DeclaredType) type;
-        TypeElement element = (TypeElement) declaredType.asElement();
-        if (element == null) {
-            return type;
-        }
-        int typeParameters = element.getTypeParameters().size();
-        if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) {
-            return ProcessorContext.getInstance().getEnvironment().getTypeUtils().erasure(type);
-        }
-        return type;
-    }
-
-    public static TypeMirror eraseGenericTypes(TypeMirror type) {
-        if (type.getKind() != TypeKind.DECLARED) {
-            return type;
-        }
-        DeclaredType declaredType = (DeclaredType) type;
-        if (declaredType.getTypeArguments().size() == 0) {
-            return type;
-        }
-        return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement());
-    }
-
-    public static boolean variableEquals(VariableElement var1, VariableElement var2) {
-        if (!var1.getSimpleName().equals(var2.getSimpleName())) {
-            return false;
-        }
-        if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) {
-            return false;
-        }
-        if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) {
-            return false;
-        }
-        return true;
-    }
-
-    public static boolean executableEquals(ExecutableElement var1, ExecutableElement var2) {
-        if (!var1.getSimpleName().equals(var2.getSimpleName())) {
-            return false;
-        }
-        if (var1.getParameters().size() != var2.getParameters().size()) {
-            return false;
-        }
-        if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) {
-            return false;
-        }
-        if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) {
-            return false;
-        }
-        for (int i = 0; i < var1.getParameters().size(); i++) {
-            if (!typeEquals(var1.getParameters().get(i).asType(), var2.getParameters().get(i).asType())) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public static boolean elementEquals(Element element1, Element element2) {
-        if (element1.getKind() != element2.getKind()) {
-            return false;
-        } else if (element1 instanceof VariableElement) {
-            return variableEquals((VariableElement) element1, (VariableElement) element2);
-        } else if (element1 instanceof ExecutableElement) {
-            return executableEquals((ExecutableElement) element1, (ExecutableElement) element2);
-        } else if (element1 instanceof TypeElement) {
-            return typeEquals(element1.asType(), element2.asType());
-        } else if (element1 instanceof PackageElement) {
-            return element1.getSimpleName().equals(element2.getSimpleName());
-        } else {
-            throw new AssertionError("unsupported element type");
-        }
-    }
-
-    public static List<TypeMirror> sortTypes(List<TypeMirror> list, final boolean reverse) {
-        Collections.sort(list, new Comparator<TypeMirror>() {
-            public int compare(TypeMirror o1, TypeMirror o2) {
-                if (reverse) {
-                    return compareType(o2, o1);
-                } else {
-                    return compareType(o1, o2);
-                }
-            }
-        });
-        return list;
-    }
-
-    public static int compareType(TypeMirror signature1, TypeMirror signature2) {
-        if (signature1 == null) {
-            return 1;
-        } else if (signature2 == null) {
-            return -1;
-        }
-
-        if (ElementUtils.typeEquals(signature1, signature2)) {
-            return 0;
-        }
-
-        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
-            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
-            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
-
-            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
-                return -1;
-            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
-                return 1;
-            }
-        }
-        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
-    }
-
-    public static List<TypeMirror> uniqueSortedTypes(Collection<TypeMirror> types, boolean reverse) {
-        if (types.isEmpty()) {
-            return new ArrayList<>(0);
-        } else if (types.size() <= 1) {
-            if (types instanceof List) {
-                return (List<TypeMirror>) types;
-            } else {
-                return new ArrayList<>(types);
-            }
-        }
-        Map<String, TypeMirror> sourceTypes = new HashMap<>();
-        for (TypeMirror type : types) {
-            sourceTypes.put(ElementUtils.getTypeId(type), type);
-        }
-        return sortTypes(new ArrayList<>(sourceTypes.values()), reverse);
-    }
-
-    public static int compareMethod(ExecutableElement method1, ExecutableElement method2) {
-        List<? extends VariableElement> parameters1 = method1.getParameters();
-        List<? extends VariableElement> parameters2 = method2.getParameters();
-        if (parameters1.size() != parameters2.size()) {
-            return Integer.compare(parameters1.size(), parameters2.size());
-        }
-
-        int result = 0;
-        for (int i = 0; i < parameters1.size(); i++) {
-            VariableElement var1 = parameters1.get(i);
-            VariableElement var2 = parameters2.get(i);
-            result = compareType(var1.asType(), var2.asType());
-            if (result != 0) {
-                return result;
-            }
-        }
-
-        result = method1.getSimpleName().toString().compareTo(method2.getSimpleName().toString());
-        if (result == 0) {
-            // if still no difference sort by enclosing type name
-            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(method1);
-            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(method2);
-            result = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
-        }
-        return result;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.compiler;
-
-import java.lang.reflect.*;
-
-public abstract class AbstractCompiler implements Compiler {
-
-    protected static Object method(Object o, String methodName) throws Exception {
-        Method method = o.getClass().getMethod(methodName);
-        method.setAccessible(true);
-        return method.invoke(o);
-    }
-
-    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
-        Method method = o.getClass().getMethod(methodName, paramTypes);
-        method.setAccessible(true);
-        return method.invoke(o, values);
-    }
-
-    protected static Object field(Object o, String fieldName) throws Exception {
-        if (o == null) {
-            return null;
-        }
-        Class<?> clazz = o.getClass();
-        Field field = null;
-        try {
-            field = clazz.getField(fieldName);
-        } catch (NoSuchFieldException e) {
-            while (clazz != null) {
-                try {
-                    field = clazz.getDeclaredField(fieldName);
-                    break;
-                } catch (NoSuchFieldException e1) {
-                    clazz = clazz.getSuperclass();
-                }
-            }
-            if (field == null) {
-                throw e;
-            }
-        }
-        field.setAccessible(true);
-        return field.get(o);
-    }
-
-    protected static String parseHeader(String content) {
-        int index = content.indexOf("/*");
-        if (index == -1) {
-            return null;
-        }
-        if (!content.substring(0, index).trim().equals("")) {
-            // just whitespace before
-            return null;
-        }
-
-        int endIndex = content.indexOf("*/", index);
-        if (endIndex == -1) {
-            return null;
-        }
-        return content.substring(index, endIndex + 2);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-public interface Compiler {
-
-    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
-
-    String getHeaderComment(ProcessingEnvironment env, Element type);
-
-    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
-
-    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.compiler;
-
-import javax.lang.model.element.*;
-
-public class CompilerFactory {
-
-    private static Compiler javac;
-    private static Compiler jdt;
-
-    public static Compiler getCompiler(Element currentElement) {
-        if (JavaCCompiler.isValidElement(currentElement)) {
-            if (javac == null) {
-                javac = new JavaCCompiler();
-            }
-            return javac;
-        } else if (JDTCompiler.isValidElement(currentElement)) {
-            if (jdt == null) {
-                jdt = new JDTCompiler();
-            }
-            return jdt;
-        } else {
-            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class JDTCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
-
-    }
-
-    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
-        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
-    }
-
-    private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
-        Map<TypeElement, List<Element>> groupedByEnclosing = new HashMap<>();
-        for (Element element : elements) {
-            Element enclosing = element.getEnclosingElement();
-            List<Element> grouped = groupedByEnclosing.get(enclosing);
-            if (grouped == null) {
-                grouped = new ArrayList<>();
-                groupedByEnclosing.put((TypeElement) enclosing, grouped);
-            }
-            grouped.add(element);
-        }
-
-        for (TypeElement enclosing : groupedByEnclosing.keySet()) {
-            Collections.sort(groupedByEnclosing.get(enclosing), createSourceOrderComparator(enclosing));
-        }
-
-        if (groupedByEnclosing.size() == 1) {
-            return groupedByEnclosing.get(groupedByEnclosing.keySet().iterator().next());
-        } else {
-            List<TypeElement> enclosingTypes = new ArrayList<>(groupedByEnclosing.keySet());
-
-            Collections.sort(enclosingTypes, new Comparator<TypeElement>() {
-                public int compare(TypeElement o1, TypeElement o2) {
-                    if (ElementUtils.isSubtype(o1.asType(), o2.asType())) {
-                        return 1;
-                    } else {
-                        return -1;
-                    }
-                }
-            });
-
-            List<Element> sourceOrderElements = new ArrayList<>();
-            for (TypeElement typeElement : enclosingTypes) {
-                sourceOrderElements.addAll(groupedByEnclosing.get(typeElement));
-            }
-            return sourceOrderElements;
-        }
-
-    }
-
-    private static Comparator<Element> createSourceOrderComparator(final TypeElement enclosing) {
-
-        Comparator<Element> comparator = new Comparator<Element>() {
-
-            final List<Object> declarationOrder = lookupDeclarationOrder(enclosing);
-
-            public int compare(Element o1, Element o2) {
-                try {
-                    Element enclosing1Element = o1.getEnclosingElement();
-                    Element enclosing2Element = o2.getEnclosingElement();
-
-                    if (!ElementUtils.typeEquals(enclosing1Element.asType(), enclosing2Element.asType())) {
-                        throw new AssertionError();
-                    }
-
-                    Object o1Binding = field(o1, "_binding");
-                    Object o2Binding = field(o2, "_binding");
-
-                    int i1 = declarationOrder.indexOf(o1Binding);
-                    int i2 = declarationOrder.indexOf(o2Binding);
-
-                    if (i1 == -1 || i2 == -1) {
-                        return 0;
-                    }
-
-                    return i1 - i2;
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        };
-        return comparator;
-    }
-
-    private static List<Object> lookupDeclarationOrder(TypeElement type) {
-
-        List<Object> declarationOrder;
-        try {
-            Object binding = field(type, "_binding");
-            Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
-            Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding");
-
-            declarationOrder = null;
-            if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
-                declarationOrder = findSourceTypeOrder(binding);
-            } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) {
-                declarationOrder = findBinaryTypeOrder(binding);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-
-        return declarationOrder;
-    }
-
-    private static List<Object> findBinaryTypeOrder(Object binding) throws Exception {
-        Object binaryType = lookupBinaryType(binding);
-        final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods");
-
-        List<Object> sortedElements = new ArrayList<>();
-        if (sortedMethods != null) {
-            sortedElements.addAll(Arrays.asList(sortedMethods));
-        }
-        final Object[] sortedFields = (Object[]) method(binaryType, "getFields");
-        if (sortedFields != null) {
-            sortedElements.addAll(Arrays.asList(sortedFields));
-        }
-        final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]);
-        if (sortedTypes != null) {
-            sortedElements.addAll(Arrays.asList(sortedTypes));
-        }
-
-        Collections.sort(sortedElements, new Comparator<Object>() {
-            public int compare(Object o1, Object o2) {
-                try {
-                    int structOffset1 = (int) field(o1, "structOffset");
-                    int structOffset2 = (int) field(o2, "structOffset");
-                    return structOffset1 - structOffset2;
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        });
-
-        Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod");
-        Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField");
-        Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType");
-
-        List<Object> bindings = new ArrayList<>();
-        for (Object sortedElement : sortedElements) {
-            Class<?> elementClass = sortedElement.getClass();
-            if (binaryMethod.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getSelector");
-                Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector);
-                if (foundBindings == null || foundBindings.length == 0) {
-                    continue;
-                } else if (foundBindings.length == 1) {
-                    bindings.add(foundBindings[0]);
-                } else {
-                    char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor");
-                    for (Object foundBinding : foundBindings) {
-                        char[] descriptor = (char[]) method(foundBinding, "signature");
-                        if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) {
-                            bindings.add(foundBinding);
-                            break;
-                        }
-                    }
-                }
-            } else if (binaryField.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getName");
-                Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true);
-                if (foundField != null) {
-                    bindings.add(foundField);
-                }
-            } else if (nestedType.isAssignableFrom(elementClass)) {
-                char[] selector = (char[]) method(sortedElement, "getSourceName");
-                Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector);
-                if (foundType != null) {
-                    bindings.add(foundType);
-                }
-            } else {
-                throw new AssertionError("Unexpected encountered type " + elementClass);
-            }
-        }
-
-        return bindings;
-    }
-
-    private static Object lookupBinaryType(Object binding) throws Exception {
-        Object lookupEnvironment = field(binding, "environment");
-        Object compoundClassName = field(binding, "compoundName");
-        Object nameEnvironment = field(lookupEnvironment, "nameEnvironment");
-        Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName);
-        Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]);
-        return binaryType;
-    }
-
-    private static List<Object> findSourceTypeOrder(Object binding) throws Exception {
-        Object referenceContext = field(field(binding, "scope"), "referenceContext");
-
-        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
-
-        collectSourceOrder(orderedBindings, referenceContext, "methods");
-        collectSourceOrder(orderedBindings, referenceContext, "fields");
-        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
-
-        return new ArrayList<>(orderedBindings.values());
-    }
-
-    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
-        Object[] declarations = (Object[]) field(referenceContext, fieldName);
-        if (declarations != null) {
-            for (int i = 0; i < declarations.length; i++) {
-                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
-                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
-            }
-        }
-    }
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-
-            char[] source = getSource(method);
-            if (source == null) {
-                return null;
-            }
-
-            /*
-             * AbstractMethodDeclaration decl =
-             * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart =
-             * decl.bodyStart; int bodyEnd = decl.bodyEnd;
-             */
-            Object decl = method(field(method, "_binding"), "sourceMethod");
-            int bodyStart = (int) field(decl, "bodyStart");
-            int bodyEnd = (int) field(decl, "bodyEnd");
-
-            int length = bodyEnd - bodyStart;
-            char[] target = new char[length];
-            System.arraycopy(source, bodyStart, target, 0, length);
-
-            return new String(target);
-        } catch (Exception e) {
-            return ElementUtils.printException(e);
-        }
-    }
-
-    private static char[] getSource(Element element) throws Exception {
-        /*
-         * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding
-         * instanceof MethodBinding) { source = ((MethodBinding)
-         * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if
-         * (binding instanceof SourceTypeBinding) { source =
-         * ((SourceTypeBinding)binding).scope.referenceContext
-         * .compilationResult.compilationUnit.getContents(); } return source;
-         */
-
-        Object binding = field(element, "_binding");
-        Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
-        Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
-
-        char[] source = null;
-        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
-            Object sourceMethod = method(binding, "sourceMethod");
-            if (sourceMethod == null) {
-                return null;
-            }
-            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
-        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
-            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
-        }
-        return source;
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            char[] source = getSource(type);
-            if (source == null) {
-                return null;
-            }
-            return parseHeader(new String(source));
-        } catch (Exception e) {
-            return ElementUtils.printException(e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.compiler;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class JavaCCompiler extends AbstractCompiler {
-
-    public static boolean isValidElement(Element currentElement) {
-        try {
-            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
-            return elementClass.isAssignableFrom(currentElement.getClass());
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
-    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
-        return type.getEnclosedElements();
-    }
-
-    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
-        return environment.getElementUtils().getAllMembers(type);
-    }
-
-    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
-    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
-
-    @Override
-    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
-        try {
-            /*
-             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
-             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
-             * = block.endpos; String methodBody =
-             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
-             * endPos).toString(); return methodBody; }
-             */
-
-            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
-            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
-            int startPos = (int) field(block, "pos");
-            int endPos = (int) field(block, "endpos");
-            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
-        } catch (Exception e) {
-            return ElementUtils.printException(e);
-        }
-    }
-
-    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
-        /*
-         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
-         */
-        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
-    }
-
-    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
-        /*
-         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
-         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
-         */
-        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
-    }
-
-    @Override
-    public String getHeaderComment(ProcessingEnvironment env, Element type) {
-        try {
-            String content = getContent(getTreeAndTopLevel(env, type)).toString();
-            return parseHeader(content);
-        } catch (Exception e) {
-            return ElementUtils.printException(e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class CodeAnnotationMirror implements AnnotationMirror {
-
-    private final DeclaredType annotationType;
-    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
-
-    public CodeAnnotationMirror(DeclaredType annotationType) {
-        this.annotationType = annotationType;
-    }
-
-    @Override
-    public DeclaredType getAnnotationType() {
-        return annotationType;
-    }
-
-    @Override
-    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
-        return values;
-    }
-
-    public void setElementValue(ExecutableElement method, AnnotationValue value) {
-        values.put(method, value);
-    }
-
-    public ExecutableElement findExecutableElement(String name) {
-        return ElementUtils.findExecutableElement(annotationType, name);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeAnnotationValue implements AnnotationValue {
-
-    private final Object value;
-
-    public CodeAnnotationValue(Object value) {
-        Objects.requireNonNull(value);
-        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
-                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
-                        (value instanceof String) || (value instanceof TypeMirror)) {
-            this.value = value;
-        } else {
-            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
-        }
-    }
-
-    @Override
-    public Object getValue() {
-        return value;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
-        if (value instanceof AnnotationMirror) {
-            return v.visitAnnotation((AnnotationMirror) value, p);
-        } else if (value instanceof List<?>) {
-            return v.visitArray((List<? extends AnnotationValue>) value, p);
-        } else if (value instanceof Boolean) {
-            return v.visitBoolean((boolean) value, p);
-        } else if (value instanceof Byte) {
-            return v.visitByte((byte) value, p);
-        } else if (value instanceof Character) {
-            return v.visitChar((char) value, p);
-        } else if (value instanceof Double) {
-            return v.visitDouble((double) value, p);
-        } else if (value instanceof VariableElement) {
-            return v.visitEnumConstant((VariableElement) value, p);
-        } else if (value instanceof Float) {
-            return v.visitFloat((float) value, p);
-        } else if (value instanceof Integer) {
-            return v.visitInt((int) value, p);
-        } else if (value instanceof Long) {
-            return v.visitLong((long) value, p);
-        } else if (value instanceof Short) {
-            return v.visitShort((short) value, p);
-        } else if (value instanceof String) {
-            return v.visitString((String) value, p);
-        } else if (value instanceof TypeMirror) {
-            return v.visitType((TypeMirror) value, p);
-        } else {
-            return v.visitUnknown(this, p);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeCompilationUnit extends CodeElement<TypeElement> {
-
-    public CodeCompilationUnit() {
-        super(Collections.<Modifier> emptySet());
-    }
-
-    @Override
-    public TypeMirror asType() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return ElementKind.OTHER;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        for (Element type : getEnclosedElements()) {
-            if (type.getKind().isClass()) {
-                type.accept(v, p);
-            } else {
-                throw new ClassCastException(type.getClass().getName());
-            }
-        }
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.io.*;
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.java.transform.*;
-
-public abstract class CodeElement<E extends Element> implements Element, GeneratedElement {
-
-    private final Set<Modifier> modifiers;
-    private List<AnnotationMirror> annotations;
-    private List<E> enclosedElements;
-
-    private Element enclosingElement;
-
-    private Element generatorElement;
-    private AnnotationMirror generatorAnnotationMirror;
-
-    public CodeElement(Set<Modifier> modifiers) {
-        this.modifiers = new LinkedHashSet<>(modifiers);
-    }
-
-    @Override
-    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
-        this.generatorAnnotationMirror = mirror;
-    }
-
-    @Override
-    public void setGeneratorElement(Element element) {
-        this.generatorElement = element;
-    }
-
-    @Override
-    public AnnotationMirror getGeneratorAnnotationMirror() {
-        return generatorAnnotationMirror;
-    }
-
-    @Override
-    public Element getGeneratorElement() {
-        return generatorElement;
-    }
-
-    public <T extends E> T add(T element) {
-        if (element == null) {
-            throw new NullPointerException();
-        }
-        getEnclosedElements().add(element);
-        return element;
-    }
-
-    public <T extends E> T addOptional(T element) {
-        if (element != null) {
-            add(element);
-        }
-        return element;
-    }
-
-    public void remove(E element) {
-        getEnclosedElements().remove(element);
-    }
-
-    @Override
-    public Set<Modifier> getModifiers() {
-        return modifiers;
-    }
-
-    @Override
-    public List<E> getEnclosedElements() {
-        if (enclosedElements == null) {
-            enclosedElements = parentableList(this, new ArrayList<E>());
-        }
-        return enclosedElements;
-    }
-
-    @Override
-    public List<AnnotationMirror> getAnnotationMirrors() {
-        if (annotations == null) {
-            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
-        }
-        return annotations;
-    }
-
-    /**
-     * Support JDK8 langtools.
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Support for some JDK8 builds. (remove after jdk8 is released)
-     *
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
-        getAnnotationMirrors().add(annotationMirror);
-    }
-
-    public void setEnclosingElement(Element parent) {
-        this.enclosingElement = parent;
-    }
-
-    public Element getEnclosingElement() {
-        return enclosingElement;
-    }
-
-    public CodeTypeElement getEnclosingClass() {
-        Element p = enclosingElement;
-        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
-            p = p.getEnclosingElement();
-        }
-        return (CodeTypeElement) p;
-    }
-
-    <T> List<T> parentableList(Element parent, List<T> list) {
-        return new ParentableList<>(parent, list);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
-        accept(codeWriter, null);
-        return codeWriter.getString();
-    }
-
-    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
-
-        public StringBuilderCodeWriter() {
-            this.writer = new CharArrayWriter();
-        }
-
-        @Override
-        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
-            return writer;
-        }
-
-        public String getString() {
-            return new String(((CharArrayWriter) writer).toCharArray()).trim();
-        }
-
-    }
-
-    private static class ParentableList<T> implements List<T> {
-
-        private final Element parent;
-        private final List<T> delegate;
-
-        public ParentableList(Element parent, List<T> delegate) {
-            this.parent = parent;
-            this.delegate = delegate;
-        }
-
-        private void addImpl(T element) {
-            if (element != null) {
-                if (element instanceof CodeElement<?>) {
-                    ((CodeElement<?>) element).setEnclosingElement(parent);
-                }
-            }
-        }
-
-        private static void removeImpl(Object element) {
-            if (element instanceof CodeElement<?>) {
-                ((CodeElement<?>) element).setEnclosingElement(null);
-            }
-        }
-
-        @Override
-        public int size() {
-            return delegate.size();
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return delegate.isEmpty();
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return delegate.contains(o);
-        }
-
-        @Override
-        public Iterator<T> iterator() {
-            return delegate.iterator();
-        }
-
-        @Override
-        public Object[] toArray() {
-            return delegate.toArray();
-        }
-
-        @Override
-        public <E> E[] toArray(E[] a) {
-            return delegate.toArray(a);
-        }
-
-        @Override
-        public boolean add(T e) {
-            addImpl(e);
-            return delegate.add(e);
-        }
-
-        @Override
-        public boolean remove(Object o) {
-            boolean removed = delegate.remove(o);
-            if (removed) {
-                removeImpl(o);
-            }
-            return removed;
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> c) {
-            return delegate.containsAll(c);
-        }
-
-        @Override
-        public boolean addAll(Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(c);
-        }
-
-        @Override
-        public boolean addAll(int index, Collection<? extends T> c) {
-            if (c != null) {
-                for (T t : c) {
-                    addImpl(t);
-                }
-            }
-            return delegate.addAll(index, c);
-        }
-
-        @Override
-        public boolean removeAll(Collection<?> c) {
-            if (c != null) {
-                for (Object t : c) {
-                    removeImpl(t);
-                }
-            }
-            return delegate.removeAll(c);
-        }
-
-        @Override
-        public String toString() {
-            return delegate.toString();
-        }
-
-        @Override
-        public boolean retainAll(Collection<?> c) {
-            throw new UnsupportedOperationException("Not supported by parentable list");
-        }
-
-        @Override
-        public void clear() {
-            for (Object e : this) {
-                removeImpl(e);
-            }
-            delegate.clear();
-        }
-
-        @Override
-        public T get(int index) {
-            return delegate.get(index);
-        }
-
-        @Override
-        public T set(int index, T element) {
-            removeImpl(delegate.get(index));
-            addImpl(element);
-            return delegate.set(index, element);
-        }
-
-        @Override
-        public void add(int index, T element) {
-            addImpl(element);
-            delegate.add(index, element);
-        }
-
-        @Override
-        public T remove(int index) {
-            T element = delegate.remove(index);
-            removeImpl(element);
-            return element;
-        }
-
-        @Override
-        public int indexOf(Object o) {
-            return delegate.indexOf(o);
-        }
-
-        @Override
-        public int lastIndexOf(Object o) {
-            return delegate.lastIndexOf(o);
-        }
-
-        @Override
-        public ListIterator<T> listIterator() {
-            return delegate.listIterator();
-        }
-
-        @Override
-        public ListIterator<T> listIterator(int index) {
-            return delegate.listIterator(index);
-        }
-
-        @Override
-        public List<T> subList(int fromIndex, int toIndex) {
-            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.util.*;
-
-public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
-
-    @Override
-    public final R visitExecutable(ExecutableElement e, P p) {
-        if (!(e instanceof CodeExecutableElement)) {
-            throw new ClassCastException(e.toString());
-        }
-        return visitExecutable(cast(e, CodeExecutableElement.class), p);
-    }
-
-    public R visitExecutable(CodeExecutableElement e, P p) {
-        R ret = super.visitExecutable(e, p);
-        if (e.getBodyTree() != null) {
-            visitTree(e.getBodyTree(), p, e);
-        }
-        return ret;
-    }
-
-    @Override
-    public R visitVariable(VariableElement e, P p) {
-        if (e instanceof CodeVariableElement) {
-            CodeTree init = ((CodeVariableElement) e).getInit();
-            if (init != null) {
-                visitTree(init, p, e);
-            }
-        }
-        return super.visitVariable(e, p);
-    }
-
-    @Override
-    public R visitPackage(PackageElement e, P p) {
-        return super.visitPackage(e, p);
-    }
-
-    @Override
-    public final R visitType(TypeElement e, P p) {
-        return visitType(cast(e, CodeTypeElement.class), p);
-    }
-
-    public R visitType(CodeTypeElement e, P p) {
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public R visitTypeParameter(TypeParameterElement e, P p) {
-        return super.visitTypeParameter(e, p);
-    }
-
-    private static <E> E cast(Element element, Class<E> clazz) {
-        return clazz.cast(element);
-    }
-
-    public void visitTree(CodeTree e, P p, Element parent) {
-        List<CodeTree> elements = e.getEnclosedElements();
-        if (elements != null) {
-            for (CodeTree tree : e.getEnclosedElements()) {
-                visitTree(tree, p, parent);
-            }
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public void visitImport(CodeImport e, P p) {
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class CodeExecutableElement extends CodeElement<Element> implements ExecutableElement {
-
-    private final List<TypeMirror> throwables = new ArrayList<>();
-    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
-
-    private TypeMirror returnType;
-    private Name name;
-
-    private CodeTree bodyTree;
-    private String body;
-    private AnnotationValue defaultValue;
-    private boolean varArgs;
-
-    public CodeExecutableElement(TypeMirror returnType, String name) {
-        super(ElementUtils.modifiers());
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
-        super(modifiers);
-        this.returnType = returnType;
-        this.name = CodeNames.of(name);
-        for (CodeVariableElement codeParameter : parameters) {
-            addParameter(codeParameter);
-        }
-    }
-
-    public void setVisibility(Modifier visibility) {
-        ElementUtils.setVisibility(getModifiers(), visibility);
-    }
-
-    public Modifier getVisibility() {
-        return ElementUtils.getVisibility(getModifiers());
-    }
-
-    /* Support JDK8 langtools. */
-    public boolean isDefault() {
-        return false;
-    }
-
-    @Override
-    public List<TypeMirror> getThrownTypes() {
-        return throwables;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return returnType;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getReturnType() == null) {
-            return ElementKind.CONSTRUCTOR;
-        } else {
-            return ElementKind.METHOD;
-        }
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    public void setVarArgs(boolean varargs) {
-        this.varArgs = varargs;
-    }
-
-    @Override
-    public boolean isVarArgs() {
-        return varArgs;
-    }
-
-    public void setDefaultValue(AnnotationValue defaultValue) {
-        this.defaultValue = defaultValue;
-    }
-
-    @Override
-    public AnnotationValue getDefaultValue() {
-        return defaultValue;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public CodeTreeBuilder getBuilder() {
-        CodeTree tree = this.bodyTree;
-        return createBuilder().tree(tree);
-    }
-
-    public CodeTreeBuilder createBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        builder.setEnclosingElement(this);
-        this.bodyTree = builder.getTree();
-        this.body = null;
-        return builder;
-    }
-
-    public CodeTreeBuilder appendBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        builder.setEnclosingElement(this);
-        if (bodyTree != null) {
-            builder.tree(bodyTree);
-        }
-        this.bodyTree = builder.getTree();
-        this.body = null;
-        return builder;
-    }
-
-    public void setBodyTree(CodeTree body) {
-        this.bodyTree = body;
-    }
-
-    public CodeTree getBodyTree() {
-        return bodyTree;
-    }
-
-    public TypeMirror getReturnType() {
-        return returnType;
-    }
-
-    @Override
-    public List<VariableElement> getParameters() {
-        return parameters;
-    }
-
-    public TypeMirror[] getParameterTypes() {
-        TypeMirror[] types = new TypeMirror[getParameters().size()];
-        for (int i = 0; i < types.length; i++) {
-            types[i] = parameters.get(i).asType();
-        }
-        return types;
-    }
-
-    public void setReturnType(TypeMirror type) {
-        returnType = type;
-    }
-
-    public void addParameter(VariableElement parameter) {
-        parameters.add(parameter);
-    }
-
-    public void addThrownType(TypeMirror thrownType) {
-        throwables.add(thrownType);
-    }
-
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    public void setBody(String body) {
-        this.body = body;
-    }
-
-    public String getBody() {
-        return body;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitExecutable(this, p);
-    }
-
-    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
-        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
-        for (TypeMirror thrownType : method.getThrownTypes()) {
-            copy.addThrownType(thrownType);
-        }
-        copy.setDefaultValue(method.getDefaultValue());
-
-        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (VariableElement var : method.getParameters()) {
-            copy.addParameter(CodeVariableElement.clone(var));
-        }
-        for (Element element : method.getEnclosedElements()) {
-            copy.add(element);
-        }
-        copy.getModifiers().addAll(method.getModifiers());
-        copy.setVarArgs(method.isVarArgs());
-        return copy;
-    }
-
-    public TypeMirror getReceiverType() {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-public class CodeImport implements Comparable<CodeImport> {
-
-    private final String packageName;
-    private final String symbolName;
-    private final boolean staticImport;
-
-    public CodeImport(String packageName, String symbolName, boolean staticImport) {
-        this.packageName = packageName;
-        this.symbolName = symbolName;
-        this.staticImport = staticImport;
-    }
-
-    public String getPackageName() {
-        return packageName;
-    }
-
-    public String getSymbolName() {
-        return symbolName;
-    }
-
-    public boolean isStaticImport() {
-        return staticImport;
-    }
-
-    @Override
-    public int compareTo(CodeImport o) {
-        if (staticImport && !o.staticImport) {
-            return 1;
-        } else if (!staticImport && o.staticImport) {
-            return -1;
-        } else {
-            int result = getPackageName().compareTo(o.getPackageName());
-            if (result == 0) {
-                return getSymbolName().compareTo(o.getSymbolName());
-            }
-            return result;
-        }
-    }
-
-    public <P> void accept(CodeElementScanner<?, P> s, P p) {
-        s.visitImport(this, p);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(packageName, symbolName, staticImport);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof CodeImport) {
-            CodeImport otherImport = (CodeImport) obj;
-            return getPackageName().equals(otherImport.getPackageName()) && getSymbolName().equals(otherImport.getSymbolName()) //
-                            && staticImport == otherImport.staticImport;
-        }
-        return super.equals(obj);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-public abstract class CodeNames {
-
-    private static Map<String, Name> names = new HashMap<>();
-
-    public static Name of(String value) {
-        Name name = names.get(value);
-        if (name == null) {
-            name = new NameImpl(value);
-            names.put(value, name);
-        }
-        return name;
-    }
-
-    private static class NameImpl implements Name {
-
-        private final String name;
-
-        public NameImpl(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public int length() {
-            return name.length();
-        }
-
-        @Override
-        public char charAt(int index) {
-            return name.charAt(index);
-        }
-
-        @Override
-        public CharSequence subSequence(int start, int end) {
-            return name.subSequence(start, end);
-        }
-
-        @Override
-        public boolean contentEquals(CharSequence cs) {
-            return name.contentEquals(cs);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Name) {
-                return ((Name) obj).contentEquals(name);
-            }
-            return super.equals(obj);
-        }
-
-        @Override
-        public int hashCode() {
-            return name.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-public class CodeTree {
-
-    private final CodeTreeKind kind;
-
-    private CodeTree parent;
-
-    private TypeMirror type;
-    private final String string;
-
-    private List<CodeTree> children;
-
-    CodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
-        this.parent = parent;
-        this.kind = kind;
-        this.type = type;
-        this.string = string;
-    }
-
-    public void setParent(CodeTree parent) {
-        this.parent = parent;
-    }
-
-    public CodeTree getParent() {
-        return parent;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public void add(CodeTree element) {
-        if (children == null) {
-            children = new ArrayList<>();
-        }
-        element.setParent(this);
-        children.add(element);
-    }
-
-    public final List<CodeTree> getEnclosedElements() {
-        return children;
-    }
-
-    public final CodeTreeKind getCodeKind() {
-        return kind;
-    }
-
-    public String getString() {
-        return string;
-    }
-
-    public void setType(TypeMirror type) {
-        this.type = type;
-    }
-
-    public boolean isEmpty() {
-        return children == null || children.isEmpty();
-    }
-
-    public boolean containsKind(CodeTreeKind k) {
-        if (this.kind == k) {
-            return true;
-        }
-        if (children != null) {
-            for (CodeTree child : children) {
-                if (child.containsKind(k)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public boolean isSingleLine() {
-        return !containsKind(CodeTreeKind.NEW_LINE);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,882 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class CodeTreeBuilder {
-
-    private BuilderCodeTree currentElement;
-    private final BuilderCodeTree root;
-
-    private int treeCount;
-    private Element enclosingElement;
-
-    public CodeTreeBuilder(CodeTreeBuilder parent) {
-        this.root = new BuilderCodeTree(null, GROUP, null, null);
-        this.currentElement = root;
-        if (parent != null) {
-            this.enclosingElement = parent.enclosingElement;
-        }
-    }
-
-    public void setEnclosingElement(Element enclosingElement) {
-        this.enclosingElement = enclosingElement;
-    }
-
-    @Override
-    public String toString() {
-        return root.toString();
-    }
-
-    public int getTreeCount() {
-        return treeCount;
-    }
-
-    public boolean isEmpty() {
-        return treeCount == 0;
-    }
-
-    public CodeTreeBuilder statement(String statement) {
-        return startStatement().string(statement).end();
-    }
-
-    public CodeTreeBuilder statement(CodeTree statement) {
-        return startStatement().tree(statement).end();
-    }
-
-    public static CodeTreeBuilder createBuilder() {
-        return new CodeTreeBuilder(null);
-    }
-
-    public static CodeTree singleString(String s) {
-        return createBuilder().string(s).build();
-    }
-
-    public static CodeTree singleType(TypeMirror s) {
-        return createBuilder().type(s).build();
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind) {
-        return push(new BuilderCodeTree(currentElement, kind, null, null), kind == NEW_LINE);
-    }
-
-    private CodeTreeBuilder push(String string) {
-        return push(new BuilderCodeTree(currentElement, CodeTreeKind.STRING, null, string), false);
-    }
-
-    private CodeTreeBuilder push(TypeMirror type) {
-        return push(new BuilderCodeTree(currentElement, CodeTreeKind.TYPE, type, null), false);
-    }
-
-    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
-        return push(new BuilderCodeTree(currentElement, kind, type, string), kind == NEW_LINE);
-    }
-
-    private CodeTreeBuilder push(BuilderCodeTree tree, boolean removeLast) {
-        if (currentElement != null) {
-            if (removeLast && !removeLastIfEnqueued(tree)) {
-                return this;
-            }
-            currentElement.add(tree);
-        }
-        switch (tree.getCodeKind()) {
-            case COMMA_GROUP:
-            case GROUP:
-            case INDENT:
-                currentElement = tree;
-                break;
-        }
-        treeCount++;
-        return this;
-    }
-
-    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
-        if (tree.getCodeKind() == REMOVE_LAST) {
-            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
-        }
-        List<CodeTree> childTree = tree.getEnclosedElements();
-        if (childTree != null && !childTree.isEmpty()) {
-            CodeTree last = childTree.get(0);
-            if (last instanceof BuilderCodeTree) {
-                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
-                    childTree.remove(0);
-                }
-            }
-        }
-        return true;
-    }
-
-    private void clearLast(CodeTreeKind kind) {
-        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
-            treeCount--;
-        } else {
-            // delay clearing the last
-            BuilderCodeTree tree = new BuilderCodeTree(currentElement, REMOVE_LAST, null, null);
-            tree.removeLast = kind;
-            push(tree, false);
-        }
-    }
-
-    public CodeTreeBuilder startStatement() {
-        startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(";").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder startGroup() {
-        return push(CodeTreeKind.GROUP);
-    }
-
-    public CodeTreeBuilder startCommaGroup() {
-        return push(CodeTreeKind.COMMA_GROUP);
-    }
-
-    public CodeTreeBuilder startCall(String callSite) {
-        return startCall((CodeTree) null, callSite);
-    }
-
-    public CodeTreeBuilder startCall(String receiver, String callSite) {
-        if (receiver != null) {
-            return startCall(singleString(receiver), callSite);
-        } else {
-            return startCall(callSite);
-        }
-    }
-
-    public CodeTreeBuilder startCall(CodeTree receiver, String callSite) {
-        if (receiver == null) {
-            return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
-        } else {
-            return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
-        }
-    }
-
-    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
-        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
-        return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
-    }
-
-    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
-        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
-    }
-
-    private CodeTreeBuilder endAndWhitespaceAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(" ");
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder endAfter() {
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                end();
-            }
-        });
-        return this;
-    }
-
-    private CodeTreeBuilder startParanthesesCommaGroup() {
-        startGroup();
-        string("(").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private CodeTreeBuilder startCurlyBracesCommaGroup() {
-        startGroup();
-        string("{").startCommaGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder startParantheses() {
-        startGroup();
-        string("(").startGroup();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string(")");
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    public CodeTreeBuilder doubleQuote(String s) {
-        return startGroup().string("\"" + s + "\"").end();
-    }
-
-    public CodeTreeBuilder string(String chunk1) {
-        return push(chunk1);
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2) {
-        return push(GROUP).string(chunk1).string(chunk2).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
-        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
-    }
-
-    public CodeTreeBuilder tree(CodeTree treeToAdd) {
-        if (treeToAdd instanceof BuilderCodeTree) {
-            return push((BuilderCodeTree) treeToAdd, true).end();
-        } else {
-            BuilderCodeTree tree = new BuilderCodeTree(currentElement, GROUP, null, null);
-            currentElement.add(treeToAdd);
-            return push(tree, true).end();
-        }
-    }
-
-    public CodeTreeBuilder trees(CodeTree... trees) {
-        for (CodeTree tree : trees) {
-            tree(tree);
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
-        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
-        for (int i = 0; i < chunks.length; i++) {
-            string(chunks[i]);
-        }
-        return end();
-    }
-
-    public CodeTreeBuilder newLine() {
-        return push(NEW_LINE);
-    }
-
-    public CodeTreeBuilder startWhile() {
-        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startDoBlock() {
-        return startGroup().string("do ").startBlock();
-    }
-
-    public CodeTreeBuilder startDoWhile() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIf() {
-        return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startFor() {
-        return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public boolean startIf(boolean elseIf) {
-        if (elseIf) {
-            startElseIf();
-        } else {
-            startIf();
-        }
-        return true;
-    }
-
-    public CodeTreeBuilder startElseIf() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startElseBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        return startGroup().string(" else ").startBlock().endAfter();
-    }
-
-    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
-        if (children == null) {
-            return false;
-        }
-        for (int i = children.size() - 1; i >= 0; i--) {
-            CodeTree child = children.get(i);
-            if (child.getCodeKind() == kind) {
-                children.remove(children.get(i));
-                return true;
-            } else {
-                if (clearLastRec(kind, child.getEnclosedElements())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public CodeTreeBuilder startCase() {
-        startGroup().string("case ");
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-                string(" :").newLine();
-            }
-
-            @Override
-            public void afterEnd() {
-            }
-        });
-        return this;
-    }
-
-    public CodeTreeBuilder caseDefault() {
-        return startGroup().string("default :").newLine().end();
-    }
-
-    public CodeTreeBuilder startSwitch() {
-        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
-    }
-
-    public CodeTreeBuilder startReturn() {
-        ExecutableElement method = findMethod();
-        if (method != null && ElementUtils.isVoid(method.getReturnType())) {
-            startGroup();
-            registerCallBack(new EndCallback() {
-
-                @Override
-                public void beforeEnd() {
-                    string(";").newLine(); // complete statement to execute
-                }
-
-                @Override
-                public void afterEnd() {
-                    string("return").string(";").newLine(); // emit a return;
-                }
-            });
-            return this;
-        } else {
-            return startStatement().string("return ");
-        }
-    }
-
-    public CodeTreeBuilder startAssert() {
-        return startStatement().string("assert ");
-    }
-
-    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
-        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
-        if (size != null) {
-            tree(size);
-        }
-        string("]");
-        if (size == null) {
-            string(" ");
-            startCurlyBracesCommaGroup().endAfter();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
-        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startNew(String typeName) {
-        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
-    }
-
-    public CodeTreeBuilder startIndention() {
-        return push(CodeTreeKind.INDENT);
-    }
-
-    public CodeTreeBuilder end(int times) {
-        for (int i = 0; i < times; i++) {
-            end();
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder end() {
-        BuilderCodeTree tree = currentElement;
-        EndCallback callback = tree.getAtEndListener();
-        if (callback != null) {
-            callback.beforeEnd();
-            toParent();
-            callback.afterEnd();
-        } else {
-            toParent();
-        }
-        return this;
-    }
-
-    private void toParent() {
-        CodeTree parentElement = currentElement.getParent();
-        if (currentElement != root) {
-            this.currentElement = (BuilderCodeTree) parentElement;
-        } else {
-            this.currentElement = root;
-        }
-    }
-
-    public CodeTreeBuilder startBlock() {
-        startGroup();
-        string("{").newLine().startIndention();
-        registerCallBack(new EndCallback() {
-
-            @Override
-            public void beforeEnd() {
-            }
-
-            @Override
-            public void afterEnd() {
-                string("}").newLine();
-            }
-        });
-        endAfter();
-        return this;
-    }
-
-    private void registerCallBack(EndCallback callback) {
-        currentElement.registerAtEnd(callback);
-    }
-
-    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
-        if (!ElementUtils.isVoid(type)) {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            string(" = ");
-            defaultValue(type);
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
-        startStatement();
-        string(type);
-        string(" ");
-        string(name);
-        if (init != null) {
-            string(" = ");
-            tree(init);
-        }
-        end(); // statement
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(String type, String name, String init) {
-        return declaration(type, name, singleString(init));
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
-        if (ElementUtils.isVoid(type)) {
-            startStatement();
-            tree(init);
-            end();
-        } else {
-            startStatement();
-            type(type);
-            string(" ");
-            string(name);
-            if (init != null) {
-                string(" = ");
-                tree(init);
-            }
-            end(); // statement
-        }
-        return this;
-    }
-
-    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
-        if (init == this) {
-            throw new IllegalArgumentException("Recursive builder usage.");
-        }
-        return declaration(type, name, init.getTree());
-    }
-
-    public CodeTreeBuilder create() {
-        return new CodeTreeBuilder(this);
-    }
-
-    public CodeTreeBuilder type(TypeMirror type) {
-        return push(type);
-    }
-
-    public CodeTreeBuilder typeLiteral(TypeMirror type) {
-        return startGroup().type(ElementUtils.eraseGenericTypes(type)).string(".class").end();
-    }
-
-    private void assertRoot() {
-        if (currentElement != root) {
-            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
-        }
-    }
-
-    public CodeTreeBuilder startCaseBlock() {
-        return startIndention();
-    }
-
-    public CodeTreeBuilder startThrow() {
-        return startStatement().string("throw ");
-    }
-
-    public CodeTree getTree() {
-        assertRoot();
-        return root;
-    }
-
-    public CodeTree build() {
-        return root;
-    }
-
-    public CodeTreeBuilder cast(TypeMirror type) {
-        string("(").type(type).string(") ");
-        return this;
-    }
-
-    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
-        if (ElementUtils.isVoid(type)) {
-            tree(content);
-            return this;
-        } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) {
-            tree(content);
-            return this;
-        } else {
-            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
-        }
-    }
-
-    public CodeTreeBuilder startSuperCall() {
-        return string("super").startParanthesesCommaGroup();
-    }
-
-    public CodeTreeBuilder returnFalse() {
-        return startReturn().string("false").end();
-    }
-
-    public CodeTreeBuilder returnStatement() {
-        return statement("return");
-    }
-
-    public ExecutableElement findMethod() {
-        if (enclosingElement != null && (enclosingElement.getKind() == ElementKind.METHOD || enclosingElement.getKind() == ElementKind.CONSTRUCTOR)) {
-            return (ExecutableElement) enclosingElement;
-        }
-        return null;
-    }
-
-    public CodeTreeBuilder returnNull() {
-        return startReturn().string("null").end();
-    }
-
-    public CodeTreeBuilder returnTrue() {
-        return startReturn().string("true").end();
-    }
-
-    public CodeTreeBuilder instanceOf(CodeTree var, TypeMirror type) {
-        return tree(var).string(" instanceof ").type(type);
-    }
-
-    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
-        switch (mirror.getKind()) {
-            case VOID:
-                return string("");
-            case ARRAY:
-            case DECLARED:
-            case PACKAGE:
-            case NULL:
-                return string("null");
-            case BOOLEAN:
-                return string("false");
-            case BYTE:
-                return string("(byte) 0");
-            case CHAR:
-                return string("(char) 0");
-            case DOUBLE:
-                return string("0.0D");
-            case LONG:
-                return string("0L");
-            case INT:
-                return string("0");
-            case FLOAT:
-                return string("0.0F");
-            case SHORT:
-                return string("(short) 0");
-            default:
-                throw new AssertionError();
-        }
-    }
-
-    public CodeTreeBuilder startTryBlock() {
-        return string("try ").startBlock();
-    }
-
-    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder startCatchBlock(TypeMirror[] exceptionTypes, String localVarName) {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" catch (");
-
-        for (int i = 0; i < exceptionTypes.length; i++) {
-            if (i != 0) {
-                string(" | ");
-            }
-            type(exceptionTypes[i]);
-        }
-
-        string(" ").string(localVarName).string(") ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder startFinallyBlock() {
-        clearLast(CodeTreeKind.NEW_LINE);
-        string(" finally ");
-        return startBlock();
-    }
-
-    public CodeTreeBuilder nullLiteral() {
-        return string("null");
-    }
-
-    private static class BuilderCodeTree extends CodeTree {
-
-        private EndCallback atEndListener;
-        private CodeTreeKind removeLast;
-
-        public BuilderCodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
-            super(parent, kind, type, string);
-        }
-
-        public void registerAtEnd(EndCallback atEnd) {
-            if (this.atEndListener != null) {
-                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
-            } else {
-                this.atEndListener = atEnd;
-            }
-        }
-
-        public EndCallback getAtEndListener() {
-            return atEndListener;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder b = new StringBuilder();
-            new Printer(b).visitTree(this, null, null);
-            return b.toString();
-        }
-
-        private static class CompoundCallback implements EndCallback {
-
-            private final EndCallback callback1;
-            private final EndCallback callback2;
-
-            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
-                this.callback1 = callback1;
-                this.callback2 = callback2;
-            }
-
-            @Override
-            public void afterEnd() {
-                callback1.afterEnd();
-                callback2.afterEnd();
-            }
-
-            @Override
-            public void beforeEnd() {
-                callback1.beforeEnd();
-                callback1.beforeEnd();
-            }
-        }
-
-    }
-
-    private interface EndCallback {
-
-        void beforeEnd();
-
-        void afterEnd();
-    }
-
-    private static class Printer extends CodeElementScanner<Void, Void> {
-
-        private int indent;
-        private boolean newLine;
-        private final String ln = "\n";
-
-        private final StringBuilder b;
-
-        Printer(StringBuilder b) {
-            this.b = b;
-        }
-
-        @Override
-        public void visitTree(CodeTree e, Void p, Element enclosingElement) {
-            switch (e.getCodeKind()) {
-                case COMMA_GROUP:
-                    List<CodeTree> children = e.getEnclosedElements();
-                    if (children != null) {
-                        for (int i = 0; i < children.size(); i++) {
-                            visitTree(children.get(i), p, enclosingElement);
-                            if (i < e.getEnclosedElements().size() - 1) {
-                                b.append(", ");
-                            }
-                        }
-                    }
-                    break;
-                case GROUP:
-                    super.visitTree(e, p, enclosingElement);
-                    break;
-                case INDENT:
-                    indent();
-                    super.visitTree(e, p, enclosingElement);
-                    dedent();
-                    break;
-                case NEW_LINE:
-                    writeLn();
-                    break;
-                case STRING:
-                    if (e.getString() != null) {
-                        write(e.getString());
-                    } else {
-                        write("null");
-                    }
-                    break;
-                case TYPE:
-                    write(ElementUtils.getSimpleName(e.getType()));
-                    break;
-                default:
-                    assert false;
-                    return;
-            }
-        }
-
-        private void indent() {
-            indent++;
-        }
-
-        private void dedent() {
-            indent--;
-        }
-
-        private void writeLn() {
-            write(ln);
-            newLine = true;
-        }
-
-        private void write(String m) {
-            if (newLine && m != ln) {
-                writeIndent();
-                newLine = false;
-            }
-            b.append(m);
-        }
-
-        private void writeIndent() {
-            for (int i = 0; i < indent; i++) {
-                b.append("    ");
-            }
-        }
-    }
-
-    public CodeTreeBuilder returnDefault() {
-        ExecutableElement method = findMethod();
-        if (ElementUtils.isVoid(method.getReturnType())) {
-            returnStatement();
-        } else {
-            startReturn().defaultValue(method.getReturnType()).end();
-        }
-        return this;
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-public enum CodeTreeKind {
-    STATIC_FIELD_REFERENCE,
-    STATIC_METHOD_REFERENCE,
-    GROUP,
-    COMMA_GROUP,
-    REMOVE_LAST,
-    INDENT,
-    STRING,
-    NEW_LINE,
-    TYPE;
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
-
-    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
-
-    private final PackageElement packageElement;
-
-    private final Name simpleName;
-    private final Name packageName;
-    private Name qualifiedName;
-
-    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
-    private final ElementKind kind;
-    private TypeMirror superClass;
-
-    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
-
-    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
-        super(modifiers);
-        this.kind = kind;
-        this.packageElement = packageElement;
-        this.simpleName = CodeNames.of(simpleName);
-        if (this.packageElement != null) {
-            this.packageName = packageElement.getQualifiedName();
-        } else {
-            this.packageName = CodeNames.of("default");
-        }
-        this.qualifiedName = createQualifiedName();
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return mirror;
-    }
-
-    @Override
-    public ElementKind getKind() {
-        return kind;
-    }
-
-    public boolean containsField(String name) {
-        for (VariableElement field : getFields()) {
-            if (field.getSimpleName().toString().equals(name)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public NestingKind getNestingKind() {
-        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
-    }
-
-    @Override
-    public Element getEnclosingElement() {
-        if (isTopLevelClass()) {
-            return packageElement;
-        } else {
-            return super.getEnclosingElement();
-        }
-    }
-
-    @Override
-    public TypeMirror getSuperclass() {
-        return superClass;
-    }
-
-    @Override
-    public List<TypeMirror> getInterfaces() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public List<? extends TypeParameterElement> getTypeParameters() {
-        return Collections.emptyList();
-    }
-
-    public boolean isTopLevelClass() {
-        return super.getEnclosingElement() instanceof CodeCompilationUnit || super.getEnclosingElement() == null;
-    }
-
-    private Name createQualifiedName() {
-        TypeElement enclosingType = getEnclosingClass();
-        if (enclosingType == null) {
-            return CodeNames.of(packageName + "." + simpleName);
-        } else {
-            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
-        }
-    }
-
-    @Override
-    public void setEnclosingElement(Element element) {
-        super.setEnclosingElement(element);
-
-        // update qualified name on container change
-        this.qualifiedName = createQualifiedName();
-    }
-
-    public Name getPackageName() {
-        return packageName;
-    }
-
-    @Override
-    public Name getQualifiedName() {
-        return qualifiedName;
-    }
-
-    @Override
-    public Name getSimpleName() {
-        return simpleName;
-    }
-
-    public void setSuperClass(TypeMirror superType) {
-        this.superClass = superType;
-    }
-
-    public List<? extends CodeImport> getImports() {
-        return imports;
-    }
-
-    public List<TypeMirror> getImplements() {
-        return implementsInterfaces;
-    }
-
-    @Override
-    public int hashCode() {
-        return getQualifiedName().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        } else if (obj instanceof TypeElement) {
-            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
-        }
-        return false;
-    }
-
-    public List<VariableElement> getFields() {
-        return ElementFilter.fieldsIn(getEnclosedElements());
-    }
-
-    public List<ExecutableElement> getMethods() {
-        return ElementFilter.methodsIn(getEnclosedElements());
-    }
-
-    public List<TypeElement> getInnerClasses() {
-        return ElementFilter.typesIn(getEnclosedElements());
-    }
-
-    @Override
-    public String toString() {
-        return getQualifiedName().toString();
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitType(this, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class CodeTypeMirror implements TypeMirror {
-
-    private final TypeKind kind;
-
-    public CodeTypeMirror(TypeKind kind) {
-        this.kind = kind;
-    }
-
-    @Override
-    public TypeKind getKind() {
-        return kind;
-    }
-
-    @Override
-    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-        throw new UnsupportedOperationException();
-    }
-
-    public static class WildcardTypeMirror extends CodeTypeMirror implements WildcardType {
-
-        private final TypeMirror extendsBounds;
-        private final TypeMirror superBounds;
-
-        public WildcardTypeMirror(TypeMirror extendsBounds, TypeMirror superBounds) {
-            super(TypeKind.WILDCARD);
-            this.extendsBounds = extendsBounds;
-            this.superBounds = superBounds;
-        }
-
-        public TypeMirror getExtendsBound() {
-            return extendsBounds;
-        }
-
-        public TypeMirror getSuperBound() {
-            return superBounds;
-        }
-
-    }
-
-    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
-
-        private final TypeMirror component;
-
-        public ArrayCodeTypeMirror(TypeMirror component) {
-            super(TypeKind.ARRAY);
-            this.component = component;
-        }
-
-        @Override
-        public TypeMirror getComponentType() {
-            return component;
-        }
-
-    }
-
-    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
-
-        private final TypeElement clazz;
-        private final List<TypeMirror> typeArguments;
-
-        public DeclaredCodeTypeMirror(TypeElement clazz) {
-            this(clazz, Collections.<TypeMirror> emptyList());
-        }
-
-        public DeclaredCodeTypeMirror(TypeElement clazz, List<TypeMirror> typeArguments) {
-            super(TypeKind.DECLARED);
-            this.clazz = clazz;
-            this.typeArguments = typeArguments;
-        }
-
-        @Override
-        public Element asElement() {
-            return clazz;
-        }
-
-        @Override
-        public TypeMirror getEnclosingType() {
-            return clazz.getEnclosingElement().asType();
-        }
-
-        @Override
-        public List<TypeMirror> getTypeArguments() {
-            return typeArguments;
-        }
-
-        @Override
-        public String toString() {
-            return clazz.getQualifiedName().toString();
-        }
-
-    }
-
-    public List<? extends AnnotationMirror> getAnnotationMirrors() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * @param annotationType
-     */
-    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class CodeVariableElement extends CodeElement<Element> implements VariableElement {
-
-    private Name name;
-    private TypeMirror type;
-    private Object constantValue;
-
-    private CodeTree init;
-
-    public CodeVariableElement(TypeMirror type, String name) {
-        super(ElementUtils.modifiers());
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
-        super(modifiers);
-        this.type = type;
-        this.name = CodeNames.of(name);
-    }
-
-    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
-        this(modifiers, type, name);
-        if (init != null) {
-            this.init = new CodeTree(null, CodeTreeKind.STRING, null, init);
-        }
-    }
-
-    public CodeTreeBuilder createInitBuilder() {
-        CodeTreeBuilder builder = new CodeTreeBuilder(null);
-        builder.setEnclosingElement(this);
-        init = builder.getTree();
-        return builder;
-    }
-
-    public void setInit(CodeTree init) {
-        this.init = init;
-    }
-
-    public CodeTree getInit() {
-        return init;
-    }
-
-    public Name getSimpleName() {
-        return name;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    @Override
-    public TypeMirror asType() {
-        return type;
-    }
-
-    @Override
-    public String toString() {
-        return super.toString() + "/* " + ElementUtils.getSimpleName(type) + "*/";
-    }
-
-    @Override
-    public ElementKind getKind() {
-        if (getEnclosingElement() instanceof ExecutableElement) {
-            return ElementKind.PARAMETER;
-        } else if (getEnclosingElement() instanceof TypeElement) {
-            return ElementKind.FIELD;
-        } else {
-            return ElementKind.PARAMETER;
-        }
-    }
-
-    public void setConstantValue(Object constantValue) {
-        this.constantValue = constantValue;
-    }
-
-    @Override
-    public Object getConstantValue() {
-        return constantValue;
-    }
-
-    public String getName() {
-        return getSimpleName().toString();
-    }
-
-    public void setSimpleName(Name name) {
-        this.name = name;
-    }
-
-    public void setName(String name) {
-        this.name = CodeNames.of(name);
-    }
-
-    public void setType(TypeMirror type) {
-        this.type = type;
-    }
-
-    @Override
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitVariable(this, p);
-    }
-
-    public static CodeVariableElement clone(VariableElement var) {
-        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
-        copy.setConstantValue(var.getConstantValue());
-        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
-            copy.addAnnotationMirror(mirror);
-        }
-        for (Element element : var.getEnclosedElements()) {
-            copy.add(element);
-        }
-        return copy;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import javax.lang.model.element.*;
-
-public interface GeneratedElement {
-
-    AnnotationMirror getGeneratorAnnotationMirror();
-
-    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
-
-    Element getGeneratorElement();
-
-    void setGeneratorElement(Element element);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public final class GeneratedPackageElement extends CodeElement<Element> implements PackageElement {
-
-    private final Name qualifiedName;
-    private final Name simpleName;
-
-    public GeneratedPackageElement(String qualifiedName) {
-        super(Collections.<Modifier> emptySet());
-        this.qualifiedName = CodeNames.of(qualifiedName);
-        int lastIndex = qualifiedName.lastIndexOf('.');
-        if (lastIndex == -1) {
-            simpleName = CodeNames.of("");
-        } else {
-            simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length()));
-        }
-    }
-
-    public TypeMirror asType() {
-        throw new UnsupportedOperationException();
-    }
-
-    public ElementKind getKind() {
-        return ElementKind.PACKAGE;
-    }
-
-    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
-        return v.visitPackage(this, p);
-    }
-
-    public Name getQualifiedName() {
-        return qualifiedName;
-    }
-
-    public Name getSimpleName() {
-        return simpleName;
-    }
-
-    public boolean isUnnamed() {
-        return simpleName.toString().equals("");
-    }
-
-    @Override
-    public int hashCode() {
-        return qualifiedName.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof PackageElement) {
-            return qualifiedName.equals(((PackageElement) obj).getQualifiedName());
-        }
-        return super.equals(obj);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-public final class GeneratedTypeElement extends CodeTypeElement {
-
-    public GeneratedTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
-        super(modifiers, kind, packageElement, simpleName);
-        setEnclosingElement(packageElement);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
-
-public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror {
-
-    public GeneratedTypeMirror(String packageName, String name) {
-        super(new GeneratedTypeElement(Collections.<Modifier> emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name));
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.transform;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
-
-    private static final int MAX_LINE_LENGTH = Integer.MAX_VALUE; // line wrapping disabled
-    private static final int LINE_WRAP_INDENTS = 3;
-    private static final String IDENT_STRING = "    ";
-    private static final String LN = "\n"; /* unix style */
-
-    protected Writer writer;
-    private int indent;
-    private boolean newLine;
-    private int lineLength;
-    private boolean lineWrapping = false;
-
-    private OrganizedImports imports;
-
-    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        if (e.isTopLevelClass()) {
-            Writer w = null;
-            try {
-                imports = OrganizedImports.organize(e);
-                w = new TrimTrailingSpaceWriter(createWriter(e));
-                writer = w;
-                writeRootClass(e);
-            } catch (IOException ex) {
-                throw new RuntimeException(ex);
-            } finally {
-                if (w != null) {
-                    try {
-                        w.close();
-                    } catch (Throwable e1) {
-                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
-                        // TODO temporary suppress errors on close.
-                    }
-                }
-                writer = null;
-            }
-        } else {
-            writeClassImpl(e);
-        }
-        return null;
-    }
-
-    private void writeRootClass(CodeTypeElement e) {
-        writeHeader();
-        write("package ").write(e.getPackageName()).write(";").writeLn();
-        writeEmptyLn();
-
-        Set<CodeImport> generateImports = imports.generateImports();
-        List<CodeImport> typeImports = new ArrayList<>();
-        List<CodeImport> staticImports = new ArrayList<>();
-
-        for (CodeImport codeImport : generateImports) {
-            if (codeImport.isStaticImport()) {
-                staticImports.add(codeImport);
-            } else {
-                typeImports.add(codeImport);
-            }
-        }
-        Collections.sort(typeImports);
-        Collections.sort(staticImports);
-
-        for (CodeImport imp : staticImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!staticImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        for (CodeImport imp : typeImports) {
-            imp.accept(this, null);
-            writeLn();
-        }
-        if (!typeImports.isEmpty()) {
-            writeEmptyLn();
-        }
-
-        writeClassImpl(e);
-    }
-
-    private String useImport(Element enclosedType, TypeMirror type) {
-        if (imports != null) {
-            return imports.createTypeReference(enclosedType, type);
-        } else {
-            return ElementUtils.getSimpleName(type);
-        }
-    }
-
-    private void writeClassImpl(CodeTypeElement e) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers(), true);
-        if (e.getKind() == ElementKind.ENUM) {
-            write("enum ");
-        } else {
-            write("class ");
-        }
-        write(e.getSimpleName());
-        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
-            write(" extends ").write(useImport(e, e.getSuperclass()));
-        }
-        if (e.getImplements().size() > 0) {
-            write(" implements ");
-            for (int i = 0; i < e.getImplements().size(); i++) {
-                write(useImport(e, e.getImplements().get(i)));
-                if (i < e.getImplements().size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        write(" {").writeLn();
-        writeEmptyLn();
-        indent(1);
-
-        List<VariableElement> staticFields = getStaticFields(e);
-        List<VariableElement> instanceFields = getInstanceFields(e);
-
-        for (int i = 0; i < staticFields.size(); i++) {
-            VariableElement field = staticFields.get(i);
-            field.accept(this, null);
-            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
-                write(",");
-                writeLn();
-            } else {
-                write(";");
-                writeLn();
-            }
-        }
-
-        if (staticFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (VariableElement field : instanceFields) {
-            field.accept(this, null);
-            write(";");
-            writeLn();
-        }
-        if (instanceFields.size() > 0) {
-            writeEmptyLn();
-        }
-
-        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getInstanceMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (ExecutableElement method : getStaticMethods(e)) {
-            method.accept(this, null);
-        }
-
-        for (TypeElement clazz : e.getInnerClasses()) {
-            clazz.accept(this, null);
-        }
-
-        dedent(1);
-        write("}");
-        writeEmptyLn();
-    }
-
-    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
-        List<VariableElement> staticFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                staticFields.add(field);
-            }
-        }
-        return staticFields;
-    }
-
-    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
-        List<VariableElement> instanceFields = new ArrayList<>();
-        for (VariableElement field : clazz.getFields()) {
-            if (!field.getModifiers().contains(Modifier.STATIC)) {
-                instanceFields.add(field);
-            }
-        }
-        return instanceFields;
-    }
-
-    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> staticMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (method.getModifiers().contains(Modifier.STATIC)) {
-                staticMethods.add(method);
-            }
-        }
-        return staticMethods;
-    }
-
-    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
-        List<ExecutableElement> instanceMethods = new ArrayList<>();
-        for (ExecutableElement method : clazz.getMethods()) {
-            if (!method.getModifiers().contains(Modifier.STATIC)) {
-                instanceMethods.add(method);
-            }
-        }
-        return instanceMethods;
-    }
-
-    @Override
-    public Void visitVariable(VariableElement f, Void p) {
-        Element parent = f.getEnclosingElement();
-
-        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
-            visitAnnotation(f, annotation);
-            write(" ");
-        }
-
-        CodeTree init = null;
-        if (f instanceof CodeVariableElement) {
-            init = ((CodeVariableElement) f).getInit();
-        }
-
-        if (parent != null && parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
-            write(f.getSimpleName());
-            if (init != null) {
-                write("(");
-                visitTree(init, p, f);
-                write(")");
-            }
-        } else {
-            writeModifiers(f.getModifiers(), true);
-
-            boolean varArgs = false;
-            if (parent != null && parent.getKind() == ElementKind.METHOD) {
-                ExecutableElement method = (ExecutableElement) parent;
-                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
-                    varArgs = true;
-                }
-            }
-
-            TypeMirror varType = f.asType();
-            if (varArgs) {
-                if (varType.getKind() == TypeKind.ARRAY) {
-                    varType = ((ArrayType) varType).getComponentType();
-                }
-                write(useImport(f, varType));
-                write("...");
-            } else {
-                write(useImport(f, varType));
-            }
-
-            write(" ");
-            write(f.getSimpleName());
-            if (init != null) {
-                write(" = ");
-                visitTree(init, p, f);
-            }
-        }
-        return null;
-    }
-
-    private void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
-        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
-
-        if (!e.getElementValues().isEmpty()) {
-            write("(");
-            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
-
-            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
-                visitAnnotationValue(enclosedElement, values.get(defaultElement));
-            } else {
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
-
-                    @Override
-                    public int compare(ExecutableElement o1, ExecutableElement o2) {
-                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
-                    }
-                });
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    ExecutableElement method = methodsList.get(i);
-                    AnnotationValue value = values.get(method);
-                    write(method.getSimpleName().toString());
-                    write(" = ");
-                    visitAnnotationValue(enclosedElement, value);
-
-                    if (i < methodsList.size() - 1) {
-                        write(", ");
-                    }
-                }
-            }
-
-            write(")");
-        }
-    }
-
-    private void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
-        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
-    }
-
-    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-        private final Element enclosedElement;
-
-        public AnnotationValueWriterVisitor(Element enclosedElement) {
-            this.enclosedElement = enclosedElement;
-        }
-
-        @Override
-        public Void visitBoolean(boolean b, Void p) {
-            write(Boolean.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitByte(byte b, Void p) {
-            write(Byte.toString(b));
-            return null;
-        }
-
-        @Override
-        public Void visitChar(char c, Void p) {
-            write(Character.toString(c));
-            return null;
-        }
-
-        @Override
-        public Void visitDouble(double d, Void p) {
-            write(Double.toString(d));
-            return null;
-        }
-
-        @Override
-        public Void visitFloat(float f, Void p) {
-            write(Float.toString(f));
-            return null;
-        }
-
-        @Override
-        public Void visitInt(int i, Void p) {
-            write(Integer.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitLong(long i, Void p) {
-            write(Long.toString(i));
-            return null;
-        }
-
-        @Override
-        public Void visitShort(short s, Void p) {
-            write(Short.toString(s));
-            return null;
-        }
-
-        @Override
-        public Void visitString(String s, Void p) {
-            write("\"");
-            write(s);
-            write("\"");
-            return null;
-        }
-
-        @Override
-        public Void visitType(TypeMirror t, Void p) {
-            write(useImport(enclosedElement, t));
-            write(".class");
-            return null;
-        }
-
-        @Override
-        public Void visitEnumConstant(VariableElement c, Void p) {
-            write(useImport(enclosedElement, c.asType()));
-            write(".");
-            write(c.getSimpleName().toString());
-            return null;
-        }
-
-        @Override
-        public Void visitAnnotation(AnnotationMirror a, Void p) {
-            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
-            return null;
-        }
-
-        @Override
-        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-            write("{");
-            for (int i = 0; i < vals.size(); i++) {
-                AnnotationValue value = vals.get(i);
-                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
-                if (i < vals.size() - 1) {
-                    write(", ");
-                }
-            }
-            write("}");
-            return null;
-        }
-    }
-
-    private static ExecutableElement findExecutableElement(DeclaredType type, String name) {
-        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
-        for (ExecutableElement executableElement : elements) {
-            if (executableElement.getSimpleName().toString().equals(name)) {
-                return executableElement;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void visitImport(CodeImport e, Void p) {
-        write("import ");
-        if (e.isStaticImport()) {
-            write("static ");
-        }
-        write(e.getPackageName());
-        write(".");
-        write(e.getSymbolName());
-        write(";");
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
-            visitAnnotation(e, annotation);
-            writeLn();
-        }
-
-        writeModifiers(e.getModifiers(), !e.getEnclosingClass().getModifiers().contains(Modifier.FINAL));
-
-        if (e.getReturnType() != null) {
-            write(useImport(e, e.getReturnType()));
-            write(" ");
-        }
-        write(e.getSimpleName());
-        write("(");
-
-        for (int i = 0; i < e.getParameters().size(); i++) {
-            VariableElement param = e.getParameters().get(i);
-            param.accept(this, p);
-            if (i < e.getParameters().size() - 1) {
-                write(", ");
-            }
-        }
-        write(")");
-
-        List<TypeMirror> throwables = e.getThrownTypes();
-        if (throwables.size() > 0) {
-            write(" throws ");
-            for (int i = 0; i < throwables.size(); i++) {
-                write(useImport(e, throwables.get(i)));
-                if (i < throwables.size() - 1) {
-                    write(", ");
-                }
-            }
-        }
-
-        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            writeLn(";");
-        } else if (e.getBodyTree() != null) {
-            writeLn(" {");
-            indent(1);
-            visitTree(e.getBodyTree(), p, e);
-            dedent(1);
-            writeLn("}");
-        } else if (e.getBody() != null) {
-            write(" {");
-            write(e.getBody());
-            writeLn("}");
-        } else {
-            writeLn(" {");
-            writeLn("}");
-        }
-        writeEmptyLn();
-        return null;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
-        CodeTreeKind kind = e.getCodeKind();
-
-        switch (kind) {
-            case COMMA_GROUP:
-                List<CodeTree> children = e.getEnclosedElements();
-                if (children != null) {
-                    for (int i = 0; i < children.size(); i++) {
-                        visitTree(children.get(i), p, enclosingElement);
-                        if (i < e.getEnclosedElements().size() - 1) {
-                            write(", ");
-                        }
-                    }
-                }
-                break;
-            case GROUP:
-                super.visitTree(e, p, enclosingElement);
-                break;
-            case INDENT:
-                indent(1);
-                super.visitTree(e, p, enclosingElement);
-                dedent(1);
-                break;
-            case NEW_LINE:
-                writeLn();
-                break;
-            case STRING:
-                if (e.getString() != null) {
-                    write(e.getString());
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_FIELD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticFieldReference(enclosingElement, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case STATIC_METHOD_REFERENCE:
-                if (e.getString() != null) {
-                    write(imports.createStaticMethodReference(enclosingElement, e.getType(), e.getString()));
-                } else {
-                    write("null");
-                }
-                break;
-            case TYPE:
-                write(useImport(enclosingElement, e.getType()));
-                break;
-            default:
-                assert false;
-                return;
-        }
-    }
-
-    protected void writeHeader() {
-        // default implementation does nothing
-    }
-
-    private void writeModifiers(Set<Modifier> modifiers, boolean includeFinal) {
-        if (modifiers != null && !modifiers.isEmpty()) {
-            Modifier[] modArray = modifiers.toArray(new Modifier[modifiers.size()]);
-            Arrays.sort(modArray);
-            for (Modifier mod : modArray) {
-                if (mod == Modifier.FINAL && !includeFinal) {
-                    continue;
-                }
-                write(mod.toString());
-                write(" ");
-            }
-        }
-    }
-
-    private void indent(int count) {
-        indent += count;
-    }
-
-    private void dedent(int count) {
-        indent -= count;
-    }
-
-    private void writeLn() {
-        writeLn("");
-    }
-
-    protected void writeLn(String text) {
-        write(text);
-        write(LN);
-        lineLength = 0;
-        newLine = true;
-        if (lineWrapping) {
-            dedent(LINE_WRAP_INDENTS);
-            lineWrapping = false;
-        }
-        lineWrapping = false;
-    }
-
-    private void writeEmptyLn() {
-        writeLn();
-    }
-
-    private AbstractCodeWriter write(Name name) {
-        return write(name.toString());
-    }
-
-    private AbstractCodeWriter write(String m) {
-        if (m.isEmpty()) {
-            return this;
-        }
-        try {
-            String s = m;
-            lineLength += s.length();
-            if (newLine && s != LN) {
-                writeIndent();
-                newLine = false;
-            }
-            if (lineLength > MAX_LINE_LENGTH) {
-                s = wrapLine(s);
-            }
-            writer.write(s);
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return this;
-    }
-
-    private String wrapLine(String m) throws IOException {
-        assert !m.isEmpty();
-
-        char firstCharacter = m.charAt(0);
-        char lastCharacter = m.charAt(m.length() - 1);
-        if (firstCharacter == '\"' && lastCharacter == '\"') {
-            // string line wrapping
-            String string = m.substring(1, m.length() - 1);
-            if (string.isEmpty()) {
-                return m;
-            }
-
-            // restore original line length
-            lineLength = lineLength - m.length();
-            int size = 0;
-            for (int i = 0; i < string.length(); i += size) {
-                if (i != 0) {
-                    write("+ ");
-                }
-
-                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                if (nextSize <= 0) {
-                    writeLn();
-                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
-                }
-
-                int end = Math.min(i + nextSize, string.length());
-
-                // TODO(CH): fails in normal usage - output ok though
-                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
-                write("\"");
-                write(string.substring(i, end));
-                write("\"");
-                size = nextSize;
-            }
-
-            return "";
-        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
-            return m;
-        }
-
-        if (!lineWrapping) {
-            indent(LINE_WRAP_INDENTS);
-        }
-        lineWrapping = true;
-        lineLength = 0;
-        write(LN);
-        writeIndent();
-        return m;
-    }
-
-    private void writeIndent() throws IOException {
-        lineLength += indentSize();
-        for (int i = 0; i < indent; i++) {
-            writer.write(IDENT_STRING);
-        }
-    }
-
-    private int indentSize() {
-        return IDENT_STRING.length() * indent;
-    }
-
-    private static class TrimTrailingSpaceWriter extends Writer {
-
-        private final Writer delegate;
-        private final StringBuilder buffer = new StringBuilder();
-
-        public TrimTrailingSpaceWriter(Writer delegate) {
-            this.delegate = delegate;
-        }
-
-        @Override
-        public void close() throws IOException {
-            this.delegate.close();
-        }
-
-        @Override
-        public void flush() throws IOException {
-            this.delegate.flush();
-        }
-
-        @Override
-        public void write(char[] cbuf, int off, int len) throws IOException {
-            buffer.append(cbuf, off, len);
-            int newLinePoint = buffer.indexOf(LN);
-
-            if (newLinePoint != -1) {
-                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
-                delegate.write(lhs);
-                delegate.write(LN);
-                buffer.delete(0, newLinePoint + 1);
-            }
-        }
-
-        private static String trimTrailing(String s) {
-            int cut = 0;
-            for (int i = s.length() - 1; i >= 0; i--) {
-                if (Character.isWhitespace(s.charAt(i))) {
-                    cut++;
-                } else {
-                    break;
-                }
-            }
-            if (cut > 0) {
-                return s.substring(0, s.length() - cut);
-            }
-            return s;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.transform;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static javax.lang.model.element.Modifier.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
-
-    private final Set<String> symbolsUsed = new HashSet<>();
-
-    private final ProcessingEnvironment processingEnv;
-    private final DeclaredType unusedAnnotation;
-    private final DeclaredType overrideType;
-
-    public FixWarningsVisitor(ProcessingEnvironment processingEnv, DeclaredType unusedAnnotation, DeclaredType overrideType) {
-        this.processingEnv = processingEnv;
-        this.unusedAnnotation = unusedAnnotation;
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitType(CodeTypeElement e, Void p) {
-        List<TypeElement> superTypes = ElementUtils.getSuperTypes(e);
-        for (TypeElement type : superTypes) {
-            String qualifiedName = ElementUtils.getQualifiedName(type);
-            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
-                if (!e.containsField("serialVersionUID")) {
-                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), ElementUtils.getType(processingEnv, long.class), "serialVersionUID", "1L"));
-                }
-                break;
-            }
-        }
-
-        return super.visitType(e, p);
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (e.getParameters().isEmpty()) {
-            return null;
-        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
-            return null;
-        } else if (containsOverride(e)) {
-            return null;
-        }
-
-        symbolsUsed.clear();
-        super.visitExecutable(e, p);
-
-        for (VariableElement parameter : e.getParameters()) {
-            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
-                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
-                break;
-            }
-        }
-        return null;
-    }
-
-    private boolean containsOverride(CodeExecutableElement e) {
-        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-            if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private CodeAnnotationMirror createUnusedAnnotationMirror() {
-        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
-        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
-        return mirror;
-    }
-
-    @Override
-    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
-        if (e.getString() != null) {
-            computeSymbols(e.getString());
-        }
-        super.visitTree(e, p, enclosingElement);
-    }
-
-    private void computeSymbols(String s) {
-        // TODO there should not be any need for a StringTokenizer if we have a real AST for
-        // method bodies. Also the current solution is not perfect. What if one token
-        // is spread across multiple CodeTree instances? But for now that works.
-        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
-        while (tokenizer.hasMoreElements()) {
-            String token = tokenizer.nextToken().trim();
-            if (token.length() > 0) {
-                symbolsUsed.add(token);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.transform;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
-
-    private final DeclaredType overrideType;
-
-    public GenerateOverrideVisitor(DeclaredType overrideType) {
-        this.overrideType = overrideType;
-    }
-
-    @Override
-    public Void visitExecutable(CodeExecutableElement e, Void p) {
-        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
-            String name = e.getSimpleName().toString();
-            TypeMirror[] params = e.getParameterTypes();
-
-            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
-                if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
-                    // already declared (may happen if method copied from super class)
-                    return super.visitExecutable(e, p);
-                }
-            }
-
-            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
-                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
-            }
-        }
-        return super.visitExecutable(e, p);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,452 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.java.transform;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-
-public final class OrganizedImports {
-
-    private final Map<String, String> classImportUsage = new HashMap<>();
-    private final Map<String, Set<String>> autoImportCache = new HashMap<>();
-
-    private final CodeTypeElement topLevelClass;
-
-    private OrganizedImports(CodeTypeElement topLevelClass) {
-        this.topLevelClass = topLevelClass;
-    }
-
-    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
-        OrganizedImports organized = new OrganizedImports(topLevelClass);
-        organized.organizeImpl();
-        return organized;
-    }
-
-    private void organizeImpl() {
-        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
-        topLevelClass.accept(reference, null);
-    }
-
-    public String createTypeReference(Element enclosedElement, TypeMirror type) {
-        switch (type.getKind()) {
-            case BOOLEAN:
-            case BYTE:
-            case CHAR:
-            case DOUBLE:
-            case FLOAT:
-            case SHORT:
-            case INT:
-            case LONG:
-            case VOID:
-                return ElementUtils.getSimpleName(type);
-            case DECLARED:
-                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
-            case ARRAY:
-                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
-            case WILDCARD:
-                return createWildcardName(enclosedElement, (WildcardType) type);
-            case TYPEVAR:
-                return "?";
-            default:
-                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
-        }
-    }
-
-    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
-        return createStaticReference(enclosedElement, type, fieldName);
-    }
-
-    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
-        return createStaticReference(enclosedElement, type, methodName);
-    }
-
-    private String createStaticReference(Element enclosedElement, TypeMirror type, String name) {
-        // ambiguous import
-        return createTypeReference(enclosedElement, type) + "." + name;
-    }
-
-    private String createWildcardName(Element enclosedElement, WildcardType type) {
-        StringBuilder b = new StringBuilder();
-        if (type.getExtendsBound() != null) {
-            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        } else if (type.getSuperBound() != null) {
-            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
-        } else {
-            b.append("?");
-        }
-        return b.toString();
-    }
-
-    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
-        String name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
-        if (classImportUsage.containsKey(name)) {
-            String qualifiedImport = classImportUsage.get(name);
-            String qualifiedName = ElementUtils.getEnclosedQualifiedName(type);
-
-            if (!qualifiedName.equals(qualifiedImport)) {
-                name = qualifiedName;
-            }
-        }
-
-        List<? extends TypeMirror> genericTypes = type.getTypeArguments();
-        if (genericTypes.size() == 0) {
-            return name;
-        }
-
-        StringBuilder b = new StringBuilder(name);
-        b.append("<");
-        for (int i = 0; i < genericTypes.size(); i++) {
-            TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null;
-            if (genericType != null) {
-                b.append(createTypeReference(enclosedElement, genericType));
-            } else {
-                b.append("?");
-            }
-
-            if (i < genericTypes.size() - 1) {
-                b.append(", ");
-            }
-        }
-        b.append(">");
-        return b.toString();
-    }
-
-    public Set<CodeImport> generateImports() {
-        Set<CodeImport> imports = new HashSet<>();
-
-        imports.addAll(generateImports(classImportUsage));
-
-        return imports;
-    }
-
-    private boolean needsImport(Element enclosed, TypeMirror importType) {
-        String importPackagName = getPackageName(importType);
-        TypeElement enclosedElement = findNearestEnclosingType(enclosed);
-        if (importPackagName == null) {
-            return false;
-        } else if (importPackagName.equals("java.lang")) {
-            return false;
-        } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) {
-            return false; // same package name -> no import
-        }
-
-        String enclosedElementId = ElementUtils.getUniqueIdentifier(enclosedElement.asType());
-        Set<String> autoImportedTypes = autoImportCache.get(enclosedElementId);
-        if (autoImportedTypes == null) {
-            List<Element> elements = ElementUtils.getElementHierarchy(enclosedElement);
-            autoImportedTypes = new HashSet<>();
-            for (Element element : elements) {
-                if (element.getKind().isClass()) {
-                    collectSuperTypeImports((TypeElement) element, autoImportedTypes);
-                    collectInnerTypeImports((TypeElement) element, autoImportedTypes);
-                }
-            }
-            autoImportCache.put(enclosedElementId, autoImportedTypes);
-        }
-
-        String qualifiedName = getQualifiedName(importType);
-        if (autoImportedTypes.contains(qualifiedName)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static Set<CodeImport> generateImports(Map<String, String> symbols) {
-        TreeSet<CodeImport> importObjects = new TreeSet<>();
-        for (String symbol : symbols.keySet()) {
-            String packageName = symbols.get(symbol);
-            if (packageName != null) {
-                importObjects.add(new CodeImport(packageName, symbol, false));
-            }
-        }
-        return importObjects;
-    }
-
-    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        autoImportedTypes.add(getQualifiedName(e));
-        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
-            collectInnerTypeImports(innerClass, autoImportedTypes);
-        }
-    }
-
-    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
-        List<TypeElement> superTypes = getSuperTypes(e);
-        for (TypeElement superType : superTypes) {
-            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
-            for (TypeElement declaredType : declaredTypes) {
-                if (!superTypes.contains(declaredType)) {
-                    autoImportedTypes.add(getQualifiedName(declaredType));
-                }
-            }
-        }
-    }
-
-    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
-
-        @Override
-        public void visitTree(CodeTree e, Void p, Element enclosing) {
-            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
-                visitStaticFieldReference(enclosing, e.getType(), e.getString());
-            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
-                visitStaticMethodReference(enclosing, e.getType(), e.getString());
-            } else if (e.getType() != null) {
-                visitTypeReference(enclosing, e.getType());
-            }
-            super.visitTree(e, p, enclosing);
-        }
-
-        @Override
-        public Void visitExecutable(CodeExecutableElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-            if (e.getReturnType() != null) {
-                visitTypeReference(e, e.getReturnType());
-            }
-            for (TypeMirror type : e.getThrownTypes()) {
-                visitTypeReference(e, type);
-            }
-            return super.visitExecutable(e, p);
-        }
-
-        @Override
-        public Void visitType(CodeTypeElement e, Void p) {
-            visitAnnotations(e, e.getAnnotationMirrors());
-
-            visitTypeReference(e, e.getSuperclass());
-            for (TypeMirror type : e.getImplements()) {
-                visitTypeReference(e, type);
-            }
-
-            return super.visitType(e, p);
-        }
-
-        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
-            for (AnnotationMirror mirror : mirrors) {
-                visitAnnotation(enclosingElement, mirror);
-            }
-        }
-
-        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
-            visitTypeReference(enclosingElement, e.getAnnotationType());
-            if (!e.getElementValues().isEmpty()) {
-                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
-                Set<? extends ExecutableElement> methodsSet = values.keySet();
-                List<ExecutableElement> methodsList = new ArrayList<>();
-                for (ExecutableElement method : methodsSet) {
-                    if (values.get(method) == null) {
-                        continue;
-                    }
-                    methodsList.add(method);
-                }
-
-                for (int i = 0; i < methodsList.size(); i++) {
-                    AnnotationValue value = values.get(methodsList.get(i));
-                    visitAnnotationValue(enclosingElement, value);
-                }
-            }
-        }
-
-        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
-            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
-        }
-
-        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
-
-            private final Element enclosingElement;
-
-            public AnnotationValueReferenceVisitor(Element enclosedElement) {
-                this.enclosingElement = enclosedElement;
-            }
-
-            @Override
-            public Void visitBoolean(boolean b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitByte(byte b, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitChar(char c, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitDouble(double d, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitFloat(float f, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitInt(int i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitLong(long i, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitShort(short s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitString(String s, Void p) {
-                return null;
-            }
-
-            @Override
-            public Void visitType(TypeMirror t, Void p) {
-                visitTypeReference(enclosingElement, t);
-                return null;
-            }
-
-            @Override
-            public Void visitEnumConstant(VariableElement c, Void p) {
-                visitTypeReference(enclosingElement, c.asType());
-                return null;
-            }
-
-            @Override
-            public Void visitAnnotation(AnnotationMirror a, Void p) {
-                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
-                return null;
-            }
-
-            @Override
-            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
-                for (int i = 0; i < vals.size(); i++) {
-                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
-                }
-                return null;
-            }
-        }
-
-        @Override
-        public Void visitVariable(VariableElement f, Void p) {
-            visitAnnotations(f, f.getAnnotationMirrors());
-            visitTypeReference(f, f.asType());
-            return super.visitVariable(f, p);
-        }
-
-        @Override
-        public void visitImport(CodeImport e, Void p) {
-        }
-
-        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
-
-        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
-
-        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
-
-    }
-
-    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
-
-        @Override
-        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
-            visitTypeReference(enclosedType, type);
-        }
-
-        @Override
-        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
-            visitTypeReference(enclosedType, type);
-        }
-
-        @Override
-        public void visitTypeReference(Element enclosedType, TypeMirror type) {
-            if (type != null) {
-                switch (type.getKind()) {
-                    case BOOLEAN:
-                    case BYTE:
-                    case CHAR:
-                    case DOUBLE:
-                    case FLOAT:
-                    case SHORT:
-                    case INT:
-                    case LONG:
-                    case VOID:
-                        return;
-                    case DECLARED:
-                        if (needsImport(enclosedType, type)) {
-                            DeclaredType declard = (DeclaredType) type;
-                            registerSymbol(classImportUsage, ElementUtils.getEnclosedQualifiedName(declard), ElementUtils.getDeclaredName(declard, false));
-                        }
-                        for (TypeMirror argument : ((DeclaredType) type).getTypeArguments()) {
-                            visitTypeReference(enclosedType, argument);
-                        }
-                        return;
-                    case ARRAY:
-                        visitTypeReference(enclosedType, ((ArrayType) type).getComponentType());
-                        return;
-                    case WILDCARD:
-                        WildcardType wildcard = (WildcardType) type;
-                        if (wildcard.getExtendsBound() != null) {
-                            visitTypeReference(enclosedType, wildcard.getExtendsBound());
-                        } else if (wildcard.getSuperBound() != null) {
-                            visitTypeReference(enclosedType, wildcard.getSuperBound());
-                        }
-                        return;
-                    case TYPEVAR:
-                        return;
-                    default:
-                        throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
-                }
-
-            }
-        }
-
-        private void registerSymbol(Map<String, String> symbolUsage, String elementQualifiedName, String elementName) {
-            if (symbolUsage.containsKey(elementName)) {
-                String otherQualifiedName = symbolUsage.get(elementName);
-                if (otherQualifiedName == null) {
-                    // already registered ambiguous
-                    return;
-                }
-                if (!otherQualifiedName.equals(elementQualifiedName)) {
-                    symbolUsage.put(elementName, null);
-                }
-            } else {
-                symbolUsage.put(elementName, elementQualifiedName);
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class AnnotatedParameterSpec extends ParameterSpec {
-
-    private final DeclaredType annotationType;
-
-    public AnnotatedParameterSpec(DeclaredType type) {
-        super("annotated", Collections.<TypeMirror> emptyList());
-        this.annotationType = type;
-    }
-
-    public DeclaredType getAnnotationType() {
-        return annotationType;
-    }
-
-    @Override
-    public boolean isAnnotated() {
-        return true;
-    }
-
-    @Override
-    public boolean matches(VariableElement variable) {
-        if (ElementUtils.findAnnotationMirror(variable.getAnnotationMirrors(), annotationType) != null) {
-            return true;
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class AssumptionExpression extends MessageContainer {
-
-    private final TemplateMethod source;
-    private final DSLExpression expression;
-    private final String id;
-
-    public AssumptionExpression(TemplateMethod source, DSLExpression expression, String id) {
-        this.source = source;
-        this.expression = expression;
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return source.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return source.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "assumptions");
-    }
-
-    public DSLExpression getExpression() {
-        return expression;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class CacheExpression extends MessageContainer {
-
-    private final DSLExpression expression;
-    private final Parameter sourceParameter;
-    private final AnnotationMirror sourceAnnotationMirror;
-
-    public CacheExpression(Parameter sourceParameter, AnnotationMirror sourceAnnotationMirror, DSLExpression expression) {
-        this.sourceParameter = sourceParameter;
-        this.expression = expression;
-        this.sourceAnnotationMirror = sourceAnnotationMirror;
-    }
-
-    public Parameter getParameter() {
-        return sourceParameter;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return sourceParameter.getVariableElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return sourceAnnotationMirror;
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "value");
-    }
-
-    public DSLExpression getExpression() {
-        return expression;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-public class CreateCastData extends TemplateMethod {
-
-    private final List<String> childNames;
-
-    public CreateCastData(TemplateMethod method, List<String> childNames) {
-        super(method);
-        this.childNames = childNames;
-    }
-
-    public List<String> getChildNames() {
-        return childNames;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,375 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class ExecutableTypeData extends MessageContainer implements Comparable<ExecutableTypeData> {
-
-    private final NodeData node;
-    private final ExecutableElement method;
-    private final TypeMirror returnType;
-    private final TypeMirror frameParameter;
-    private final List<TypeMirror> evaluatedParameters;
-    private ExecutableTypeData delegatedTo;
-    private final List<ExecutableTypeData> delegatedFrom = new ArrayList<>();
-
-    private String uniqueName;
-
-    public ExecutableTypeData(NodeData node, TypeMirror returnType, String uniqueName, TypeMirror frameParameter, List<TypeMirror> evaluatedParameters) {
-        this.node = node;
-        this.returnType = returnType;
-        this.frameParameter = frameParameter;
-        this.evaluatedParameters = evaluatedParameters;
-        this.uniqueName = uniqueName;
-        this.method = null;
-    }
-
-    public ExecutableTypeData(NodeData node, ExecutableElement method, int signatureSize, List<TypeMirror> frameTypes) {
-        this.node = node;
-        this.method = method;
-        this.returnType = method.getReturnType();
-        TypeMirror foundFrameParameter = null;
-        List<? extends VariableElement> parameters = method.getParameters();
-
-        int parameterIndex = 0;
-        evaluatedParameters = new ArrayList<>();
-        if (!parameters.isEmpty()) {
-            TypeMirror firstParameter = parameters.get(0).asType();
-            for (TypeMirror frameType : frameTypes) {
-                if (ElementUtils.typeEquals(firstParameter, frameType)) {
-                    foundFrameParameter = firstParameter;
-                    parameterIndex++;
-                    break;
-                }
-            }
-        }
-
-        int numberParameters = Math.max(parameters.size() - parameterIndex, signatureSize);
-        for (int i = 0; i < numberParameters; i++) {
-            TypeMirror parameter;
-            if (method.isVarArgs() && parameterIndex >= parameters.size() - 1) {
-                ArrayType varArgsArray = (ArrayType) parameters.get(parameters.size() - 1).asType();
-                parameter = varArgsArray.getComponentType();
-            } else if (parameterIndex < parameters.size()) {
-                parameter = parameters.get(parameterIndex).asType();
-            } else {
-                break;
-            }
-            parameterIndex++;
-            evaluatedParameters.add(parameter);
-        }
-        this.frameParameter = foundFrameParameter;
-        this.uniqueName = createName(this);
-    }
-
-    public static String createName(ExecutableTypeData type) {
-        return "execute" + (ElementUtils.isObject(type.getReturnType()) ? "" : ElementUtils.getTypeId(type.getReturnType()));
-    }
-
-    public void addDelegatedFrom(ExecutableTypeData child) {
-        this.delegatedFrom.add(child);
-        child.delegatedTo = this;
-    }
-
-    public List<ExecutableTypeData> getDelegatedFrom() {
-        return delegatedFrom;
-    }
-
-    public ExecutableTypeData getDelegatedTo() {
-        return delegatedTo;
-    }
-
-    public ExecutableElement getMethod() {
-        return method;
-    }
-
-    public String getUniqueName() {
-        return uniqueName;
-    }
-
-    public void setUniqueName(String name) {
-        this.uniqueName = name;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return method;
-    }
-
-    public List<TypeMirror> getEvaluatedParameters() {
-        return evaluatedParameters;
-    }
-
-    public List<TypeMirror> getSignatureParameters() {
-        List<TypeMirror> signaturetypes = new ArrayList<>();
-        int index = 0;
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.isShortCircuit()) {
-                index++;
-            }
-            if (index < getEvaluatedCount()) {
-                signaturetypes.add(getEvaluatedParameters().get(index));
-            }
-            index++;
-        }
-        return signaturetypes;
-    }
-
-    public int getVarArgsIndex(int parameterIndex) {
-        if (method.isVarArgs()) {
-            int index = parameterIndex - (method.getParameters().size() - 1);
-            return index;
-        }
-        return -1;
-    }
-
-    public int getParameterIndex(int signatureIndex) {
-        return frameParameter != null ? signatureIndex + 1 : signatureIndex;
-    }
-
-    public TypeMirror getFrameParameter() {
-        return frameParameter;
-    }
-
-    public TypeMirror getReturnType() {
-        return returnType;
-    }
-
-    public boolean hasUnexpectedValue(ProcessorContext context) {
-        return method == null ? false : ElementUtils.canThrowType(method.getThrownTypes(), context.getType(UnexpectedResultException.class));
-    }
-
-    public boolean isFinal() {
-        return method == null ? false : method.getModifiers().contains(Modifier.FINAL);
-    }
-
-    public boolean isAbstract() {
-        return method == null ? false : method.getModifiers().contains(Modifier.ABSTRACT);
-    }
-
-    public int getEvaluatedCount() {
-        return evaluatedParameters.size();
-    }
-
-    public boolean canDelegateTo(ExecutableTypeData to) {
-        ExecutableTypeData from = this;
-        if (to.getEvaluatedCount() < from.getEvaluatedCount()) {
-            return false;
-        }
-
-        ProcessorContext context = node.getContext();
-
-        // we cannot delegate from generic to unexpected
-        if (!from.hasUnexpectedValue(context) && to.hasUnexpectedValue(context)) {
-            return false;
-        }
-
-        // we can skip the return type check for void. everything is assignable to void.
-        if (!isVoid(from.getReturnType())) {
-            if (!isSubtypeBoxed(context, from.getReturnType(), to.getReturnType()) && !isSubtypeBoxed(context, to.getReturnType(), from.getReturnType())) {
-                return false;
-            }
-        }
-        if (from.getFrameParameter() != to.getFrameParameter() && from.getFrameParameter() != null && to.getFrameParameter() != null &&
-                        !isSubtypeBoxed(context, from.getFrameParameter(), to.getFrameParameter())) {
-            return false;
-        }
-
-        for (int i = 0; i < from.getEvaluatedCount(); i++) {
-            if (!isSubtypeBoxed(context, from.getEvaluatedParameters().get(i), to.getEvaluatedParameters().get(i))) {
-                return false;
-            }
-        }
-
-        List<TypeMirror> fromSignatureParameters = from.getSignatureParameters();
-        List<TypeMirror> toSignatureParameters = to.getSignatureParameters();
-        for (int i = fromSignatureParameters.size(); i < toSignatureParameters.size(); i++) {
-            TypeMirror delegateToParameter = toSignatureParameters.get(i);
-            if (i < node.getChildExecutions().size()) {
-                TypeMirror genericType = node.getGenericType(node.getChildExecutions().get(i));
-                if (!isSubtypeBoxed(context, genericType, delegateToParameter)) {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public int compareTo(ExecutableTypeData o2) {
-        ExecutableTypeData o1 = this;
-        ProcessorContext context = ProcessorContext.getInstance();
-
-        if (canDelegateTo(o2)) {
-            if (!o2.canDelegateTo(this)) {
-                return 1;
-            }
-        } else if (o2.canDelegateTo(this)) {
-            return -1;
-        }
-
-        int result = Integer.compare(o2.getEvaluatedCount(), o1.getEvaluatedCount());
-        if (result != 0) {
-            return result;
-        }
-
-        result = Boolean.compare(o1.hasUnexpectedValue(context), o2.hasUnexpectedValue(context));
-        if (result != 0) {
-            return result;
-        }
-
-        result = compareType(context, o1.getReturnType(), o2.getReturnType());
-        if (result != 0) {
-            return result;
-        }
-        result = compareType(context, o1.getFrameParameter(), o2.getFrameParameter());
-        if (result != 0) {
-            return result;
-        }
-
-        for (int i = 0; i < o1.getEvaluatedCount(); i++) {
-            result = compareType(context, o1.getEvaluatedParameters().get(i), o2.getEvaluatedParameters().get(i));
-            if (result != 0) {
-                return result;
-            }
-        }
-
-        result = o1.getUniqueName().compareTo(o2.getUniqueName());
-        if (result != 0) {
-            return result;
-        }
-
-        if (o1.getMethod() != null && o2.getMethod() != null) {
-            result = ElementUtils.compareMethod(o1.getMethod(), o2.getMethod());
-            if (result != 0) {
-                return result;
-            }
-        }
-        return 0;
-    }
-
-    public static int compareType(ProcessorContext context, TypeMirror signature1, TypeMirror signature2) {
-        if (signature1 == null) {
-            if (signature2 == null) {
-                return 0;
-            }
-            return -1;
-        } else if (signature2 == null) {
-            return 1;
-        }
-        if (ElementUtils.typeEquals(signature1, signature2)) {
-            return 0;
-        }
-        if (isVoid(signature1)) {
-            if (isVoid(signature2)) {
-                return 0;
-            }
-            return 1;
-        } else if (isVoid(signature2)) {
-            return -1;
-        }
-
-        TypeMirror boxedType1 = ElementUtils.boxType(context, signature1);
-        TypeMirror boxedType2 = ElementUtils.boxType(context, signature2);
-
-        if (ElementUtils.isSubtype(boxedType1, boxedType2)) {
-            if (ElementUtils.isSubtype(boxedType2, boxedType1)) {
-                return 0;
-            }
-            return 1;
-        } else if (ElementUtils.isSubtype(boxedType2, boxedType1)) {
-            return -1;
-        } else {
-            return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
-        }
-    }
-
-    public String getName() {
-        if (method != null) {
-            return method.getSimpleName().toString();
-        } else {
-            return getUniqueName();
-        }
-
-    }
-
-    private static String formatType(TypeMirror type) {
-        return type == null ? "null" : ElementUtils.getSimpleName(type);
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s %s(%s,%s)", formatType(getReturnType()), getName(), formatType(getFrameParameter()), getEvaluatedParameters());
-    }
-
-    public boolean sameParameters(ExecutableTypeData other) {
-        if (!typeEquals(other.getFrameParameter(), getFrameParameter())) {
-            return false;
-        }
-
-        if (getEvaluatedCount() != other.getEvaluatedCount()) {
-            return false;
-        }
-
-        for (int i = 0; i < getEvaluatedCount(); i++) {
-            if (!typeEquals(getEvaluatedParameters().get(i), other.getEvaluatedParameters().get(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public boolean sameSignature(ExecutableTypeData other) {
-        if (!typeEquals(other.getReturnType(), getReturnType())) {
-            return false;
-        }
-
-        if (other.getFrameParameter() != null) {
-            if (!typeEquals(getFrameParameter(), other.getFrameParameter())) {
-                return false;
-            }
-        }
-
-        if (getEvaluatedCount() != other.getEvaluatedCount()) {
-            return false;
-        }
-
-        for (int i = 0; i < getEvaluatedCount(); i++) {
-            if (!typeEquals(getEvaluatedParameters().get(i), other.getEvaluatedParameters().get(i))) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class GuardExpression extends MessageContainer {
-
-    private final TemplateMethod source;
-    private final DSLExpression expression;
-
-    public GuardExpression(TemplateMethod source, DSLExpression expression) {
-        this.source = source;
-        this.expression = expression;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return source.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return source.getMessageAnnotation();
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "guards");
-    }
-
-    public DSLExpression getExpression() {
-        return expression;
-    }
-
-    public boolean equalsNegated(GuardExpression other) {
-        boolean negated = false;
-        DSLExpression thisExpression = expression;
-        if (thisExpression instanceof Negate) {
-            negated = true;
-            thisExpression = ((Negate) thisExpression).getReceiver();
-        }
-
-        boolean otherNegated = false;
-        DSLExpression otherExpression = other.expression;
-        if (otherExpression instanceof Negate) {
-            otherNegated = true;
-            otherExpression = ((Negate) otherExpression).getReceiver();
-        }
-        return Objects.equals(thisExpression, otherExpression) && negated != otherNegated;
-    }
-
-    public boolean implies(GuardExpression other) {
-        if (Objects.equals(expression, other.expression)) {
-            return true;
-        }
-        return false;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.type.*;
-
-public class ImplicitCastData extends TemplateMethod {
-
-    private final TypeMirror sourceType;
-    private final TypeMirror targetType;
-
-    public ImplicitCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public TypeMirror getSourceType() {
-        return sourceType;
-    }
-
-    public TypeMirror getTargetType() {
-        return targetType;
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        return super.compareTo(o);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public abstract class MessageContainer implements Iterable<MessageContainer> {
-
-    private final List<Message> messages = new ArrayList<>();
-
-    public final void addWarning(String text, Object... params) {
-        getMessages().add(new Message(null, null, this, String.format(text, params), Kind.WARNING));
-    }
-
-    public final void addWarning(AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.WARNING));
-    }
-
-    public final void addError(String text, Object... params) {
-        addError(null, text, params);
-    }
-
-    public final void addError(AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.ERROR));
-    }
-
-    public final void addError(AnnotationMirror mirror, AnnotationValue value, String text, Object... params) {
-        getMessages().add(new Message(mirror, value, this, String.format(text, params), Kind.ERROR));
-    }
-
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public abstract Element getMessageElement();
-
-    public MessageContainer getBaseContainer() {
-        return null;
-    }
-
-    public Iterator<MessageContainer> iterator() {
-        return findChildContainers().iterator();
-    }
-
-    public final void emitMessages(ProcessorContext context, Log log) {
-        emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
-    }
-
-    private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
-        List<Message> childMessages;
-        if (verifiedMessages == null) {
-            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
-        } else {
-            childMessages = verifiedMessages;
-        }
-        verifyExpectedMessages(context, log, childMessages);
-
-        for (int i = getMessages().size() - 1; i >= 0; i--) {
-            emitDefault(context, log, getMessages().get(i));
-        }
-
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                continue;
-            }
-
-            visitedSinks.add(sink);
-            if (sink.getMessageElement() == this.getMessageElement()) {
-                sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
-            } else {
-                sink.emitMessagesImpl(context, log, visitedSinks, null);
-            }
-        }
-    }
-
-    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
-        if (visitedSinks.contains(this)) {
-            return Collections.emptyList();
-        }
-        visitedSinks.add(this);
-
-        List<Message> foundMessages = new ArrayList<>();
-        if (getMessageElement() != null && ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) {
-            foundMessages.addAll(getMessages());
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
-        }
-        return foundMessages;
-    }
-
-    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            Element element = getMessageElement();
-            if (element != null) {
-                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError.asType());
-                if (mirror != null) {
-                    List<String> values = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
-                    if (values == null) {
-                        values = Collections.emptyList();
-                    }
-                    if (values.size() != msgs.size()) {
-                        log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
-                    }
-                }
-            }
-        }
-    }
-
-    private void emitDefault(ProcessorContext context, Log log, Message message) {
-        Kind kind = message.getKind();
-
-        Element messageElement = getMessageElement();
-        AnnotationMirror messageAnnotation = getMessageAnnotation();
-        AnnotationValue messageValue = getMessageAnnotationValue();
-        if (message.getAnnotationValue() != null) {
-            messageValue = message.getAnnotationValue();
-        }
-        if (message.getAnnotationMirror() != null) {
-            messageAnnotation = message.getAnnotationMirror();
-        }
-
-        String text = message.getText();
-
-        TypeElement expectError = context.getTruffleTypes().getExpectError();
-        if (expectError != null) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError.asType());
-            if (mirror != null) {
-                List<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
-                boolean found = false;
-                for (String expectedText : expectedTexts) {
-                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
-                        found = true;
-                        break;
-                    } else if (text.equals(expectedText)) {
-                        found = true;
-                        break;
-                    }
-                }
-                if (!found) {
-                    log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
-                } else {
-                    return;
-                }
-
-            }
-        }
-
-        log.message(kind, messageElement, messageAnnotation, messageValue, text);
-    }
-
-    public AnnotationMirror getMessageAnnotation() {
-        return null;
-    }
-
-    public AnnotationValue getMessageAnnotationValue() {
-        return null;
-    }
-
-    public final boolean hasErrors() {
-        return hasErrorsImpl(new HashSet<MessageContainer>());
-    }
-
-    public final List<Message> collectMessages() {
-        List<Message> collectedMessages = new ArrayList<>();
-        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
-        return collectedMessages;
-    }
-
-    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
-        collectedMessages.addAll(getMessages());
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return;
-            }
-
-            visitedSinks.add(sink);
-            sink.collectMessagesImpl(collectedMessages, visitedSinks);
-        }
-    }
-
-    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
-        for (Message msg : getMessages()) {
-            if (msg.getKind() == Kind.ERROR) {
-                return true;
-            }
-        }
-        for (MessageContainer sink : findChildContainers()) {
-            if (visitedSinks.contains(sink)) {
-                return false;
-            }
-
-            visitedSinks.add(sink);
-
-            if (sink.hasErrorsImpl(visitedSinks)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public List<Message> getMessages() {
-        return messages;
-    }
-
-    public static final class Message {
-
-        private final MessageContainer originalContainer;
-        private final AnnotationMirror annotationMirror;
-        private final AnnotationValue annotationValue;
-        private final String text;
-        private final Kind kind;
-
-        public Message(AnnotationMirror annotationMirror, AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
-            this.annotationMirror = annotationMirror;
-            this.annotationValue = annotationValue;
-            this.originalContainer = originalContainer;
-            this.text = text;
-            this.kind = kind;
-        }
-
-        public AnnotationMirror getAnnotationMirror() {
-            return annotationMirror;
-        }
-
-        public AnnotationValue getAnnotationValue() {
-            return annotationValue;
-        }
-
-        public MessageContainer getOriginalContainer() {
-            return originalContainer;
-        }
-
-        public String getText() {
-            return text;
-        }
-
-        public Kind getKind() {
-            return kind;
-        }
-
-        @Override
-        public String toString() {
-            return kind + ": " + text;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class MethodSpec {
-
-    private final ParameterSpec returnType;
-    private final List<ParameterSpec> optional = new ArrayList<>();
-    private final List<ParameterSpec> required = new ArrayList<>();
-    private final List<ParameterSpec> annotations = new ArrayList<>();
-
-    private boolean ignoreAdditionalParameters;
-    private boolean ignoreAdditionalSpecifications;
-    private boolean variableRequiredParameters;
-
-    private List<TypeDef> typeDefinitions;
-
-    public MethodSpec(ParameterSpec returnType) {
-        this.returnType = returnType;
-    }
-
-    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
-        this.variableRequiredParameters = variableRequiredParameters;
-    }
-
-    public boolean isVariableRequiredParameters() {
-        return variableRequiredParameters;
-    }
-
-    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
-        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
-    }
-
-    public boolean isIgnoreAdditionalParameters() {
-        return ignoreAdditionalParameters;
-    }
-
-    public void addOptional(ParameterSpec spec) {
-        optional.add(spec);
-    }
-
-    public ParameterSpec addRequired(ParameterSpec spec) {
-        required.add(spec);
-        return spec;
-    }
-
-    public List<ParameterSpec> getAnnotations() {
-        return annotations;
-    }
-
-    public ParameterSpec getReturnType() {
-        return returnType;
-    }
-
-    public List<ParameterSpec> getRequired() {
-        return required;
-    }
-
-    public List<ParameterSpec> getOptional() {
-        return optional;
-    }
-
-    public List<ParameterSpec> getAll() {
-        List<ParameterSpec> specs = new ArrayList<>();
-        specs.add(getReturnType());
-        specs.addAll(getOptional());
-        specs.addAll(getRequired());
-        return specs;
-    }
-
-    public void applyTypeDefinitions(String prefix) {
-        this.typeDefinitions = createTypeDefinitions(prefix);
-    }
-
-    private List<TypeDef> createTypeDefinitions(String prefix) {
-        List<TypeDef> typeDefs = new ArrayList<>();
-
-        int defIndex = 0;
-        for (ParameterSpec spec : getAll()) {
-            Collection<TypeMirror> allowedTypes = spec.getAllowedTypes();
-            Collection<TypeMirror> types = spec.getAllowedTypes();
-            if (types != null && allowedTypes.size() > 1) {
-                TypeDef foundDef = null;
-                for (TypeDef def : typeDefs) {
-                    if (allowedTypes.equals(def.getTypes())) {
-                        foundDef = def;
-                        break;
-                    }
-                }
-                if (foundDef == null) {
-                    foundDef = new TypeDef(types, prefix + defIndex);
-                    typeDefs.add(foundDef);
-                    defIndex++;
-                }
-
-                spec.setTypeDefinition(foundDef);
-            }
-        }
-
-        return typeDefs;
-    }
-
-    public String toSignatureString(String methodName) {
-        StringBuilder b = new StringBuilder();
-        b.append("    ");
-        b.append(createTypeSignature(returnType, true));
-
-        b.append(" ");
-        b.append(methodName);
-        b.append("(");
-
-        String sep = "";
-
-        for (ParameterSpec optionalSpec : getOptional()) {
-            b.append(sep);
-            b.append("[");
-            b.append(createTypeSignature(optionalSpec, false));
-            b.append("]");
-            sep = ", ";
-        }
-
-        for (int i = 0; i < getRequired().size(); i++) {
-            ParameterSpec requiredSpec = getRequired().get(i);
-            b.append(sep);
-
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("{"));
-            }
-            b.append(createTypeSignature(requiredSpec, false));
-            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
-                b.append(("}"));
-            }
-
-            sep = ", ";
-        }
-
-        b.append(")");
-
-        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
-            b.append("\n\n");
-
-            String lineSep = "";
-            for (TypeDef def : typeDefinitions) {
-                b.append(lineSep);
-                b.append("    <").append(def.getName()).append(">");
-                b.append(" = {");
-                String separator = "";
-                for (TypeMirror type : def.getTypes()) {
-                    b.append(separator).append(ElementUtils.getSimpleName(type));
-                    separator = ", ";
-                }
-                b.append("}");
-                lineSep = "\n";
-
-            }
-        }
-        return b.toString();
-    }
-
-    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        TypeDef foundTypeDef = spec.getTypeDefinition();
-        if (foundTypeDef != null) {
-            builder.append("<" + foundTypeDef.getName() + ">");
-        } else if (spec.getAllowedTypes().size() >= 1) {
-            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().iterator().next()));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(spec.getName());
-        }
-        return builder.toString();
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString("methodName");
-    }
-
-    static final class TypeDef {
-
-        private final Collection<TypeMirror> types;
-        private final String name;
-
-        private TypeDef(Collection<TypeMirror> types, String name) {
-            this.types = types;
-            this.name = name;
-        }
-
-        public Collection<TypeMirror> getTypes() {
-            return types;
-        }
-
-        public String getName() {
-            return name;
-        }
-    }
-
-    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
-        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
-    }
-
-    public boolean isIgnoreAdditionalSpecifications() {
-        return ignoreAdditionalSpecifications;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-
-public class NodeChildData extends MessageContainer {
-
-    public enum Cardinality {
-        ONE,
-        MANY;
-
-        public boolean isMany() {
-            return this == MANY;
-        }
-
-        public boolean isOne() {
-            return this == ONE;
-        }
-    }
-
-    private final Element sourceElement;
-    private final AnnotationMirror sourceAnnotationMirror;
-    private final String name;
-    private final TypeMirror type;
-    private final TypeMirror originalType;
-    private final Element accessElement;
-    private final Cardinality cardinality;
-
-    private List<NodeExecutionData> executeWith = Collections.emptyList();
-
-    private NodeData childNode;
-
-    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
-        this.sourceElement = sourceElement;
-        this.sourceAnnotationMirror = sourceMirror;
-        this.name = name;
-        this.type = nodeType;
-        this.originalType = originalNodeType;
-        this.accessElement = accessElement;
-        this.cardinality = cardinality;
-    }
-
-    public List<NodeExecutionData> getExecuteWith() {
-        return executeWith;
-    }
-
-    public void setExecuteWith(List<NodeExecutionData> executeWith) {
-        this.executeWith = executeWith;
-    }
-
-    public ExecutableTypeData findExecutableType(TypeMirror targetType) {
-        return childNode.findExecutableType(targetType, getExecuteWith().size());
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
-        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
-        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
-    }
-
-    public TypeMirror getOriginalType() {
-        return originalType;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return sourceElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return sourceAnnotationMirror;
-    }
-
-    public void setNode(NodeData nodeData) {
-        this.childNode = nodeData;
-        if (nodeData != null) {
-            getMessages().addAll(nodeData.collectMessages());
-        }
-    }
-
-    public Element getAccessElement() {
-        return accessElement;
-    }
-
-    public TypeMirror getNodeType() {
-        return type;
-    }
-
-    public Cardinality getCardinality() {
-        return cardinality;
-    }
-
-    public NodeData getNodeData() {
-        return childNode;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-
-public class NodeData extends Template implements Comparable<NodeData> {
-
-    private final String nodeId;
-    private final String shortName;
-    private final List<NodeData> enclosingNodes = new ArrayList<>();
-    private NodeData declaringNode;
-
-    private final TypeSystemData typeSystem;
-    private final List<NodeChildData> children;
-    private final List<NodeExecutionData> childExecutions;
-    private final List<NodeFieldData> fields;
-
-    private ParameterSpec instanceParameterSpec;
-
-    private final List<SpecializationData> specializations = new ArrayList<>();
-    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
-    private final List<CreateCastData> casts = new ArrayList<>();
-    private final List<ExecutableTypeData> executableTypes = new ArrayList<>();
-
-    private final NodeExecutionData thisExecution;
-    private final boolean generateFactory;
-
-    private TypeMirror frameType;
-
-    public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, boolean generateFactory) {
-        super(context, type, null);
-        this.nodeId = ElementUtils.getSimpleName(type);
-        this.shortName = shortName;
-        this.typeSystem = typeSystem;
-        this.fields = new ArrayList<>();
-        this.children = new ArrayList<>();
-        this.childExecutions = new ArrayList<>();
-        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, -1, false);
-        this.thisExecution.getChild().setNode(this);
-        this.generateFactory = generateFactory;
-    }
-
-    public NodeData(ProcessorContext context, TypeElement type) {
-        this(context, type, null, null, false);
-    }
-
-    public boolean isGenerateFactory() {
-        return generateFactory;
-    }
-
-    public NodeExecutionData getThisExecution() {
-        return thisExecution;
-    }
-
-    public boolean isFallbackReachable() {
-        SpecializationData generic = getGenericSpecialization();
-        if (generic != null) {
-            return generic.isReachable();
-        }
-        return false;
-    }
-
-    public void setFrameType(TypeMirror frameType) {
-        this.frameType = frameType;
-    }
-
-    public TypeMirror getFrameType() {
-        return frameType;
-    }
-
-    public void addEnclosedNode(NodeData node) {
-        this.enclosingNodes.add(node);
-        node.declaringNode = this;
-    }
-
-    public List<NodeExecutionData> getChildExecutions() {
-        return childExecutions;
-    }
-
-    public Set<TypeMirror> findSpecializedTypes(NodeExecutionData execution) {
-        Set<TypeMirror> types = new HashSet<>();
-        for (SpecializationData specialization : getSpecializations()) {
-            if (!specialization.isSpecialized()) {
-                continue;
-            }
-            List<Parameter> parameters = specialization.findByExecutionData(execution);
-            for (Parameter parameter : parameters) {
-                TypeMirror type = parameter.getType();
-                if (type == null) {
-                    throw new AssertionError();
-                }
-                types.add(type);
-            }
-        }
-        return types;
-    }
-
-    public Collection<TypeMirror> findSpecializedReturnTypes() {
-        Set<TypeMirror> types = new HashSet<>();
-        for (SpecializationData specialization : getSpecializations()) {
-            if (!specialization.isSpecialized()) {
-                continue;
-            }
-            types.add(specialization.getReturnType().getType());
-        }
-        return types;
-    }
-
-    public int getExecutionCount() {
-        return getChildExecutions().size();
-    }
-
-    public int getSignatureSize() {
-        int count = 0;
-        for (NodeExecutionData execution : getChildExecutions()) {
-            if (execution.isShortCircuit()) {
-                count++;
-            }
-            count++;
-        }
-        return count;
-    }
-
-    public boolean isFrameUsedByAnyGuard() {
-        for (SpecializationData specialization : specializations) {
-            if (!specialization.isReachable()) {
-                continue;
-            }
-            Parameter frame = specialization.getFrame();
-            if (frame != null) {
-                for (GuardExpression guard : specialization.getGuards()) {
-                    if (guard.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) {
-                        return true;
-                    }
-                }
-                for (CacheExpression cache : specialization.getCaches()) {
-                    if (cache.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    public List<CreateCastData> getCasts() {
-        return casts;
-    }
-
-    public String getShortName() {
-        return shortName;
-    }
-
-    public List<NodeFieldData> getFields() {
-        return fields;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> containerChildren = new ArrayList<>();
-        if (enclosingNodes != null) {
-            containerChildren.addAll(enclosingNodes);
-        }
-        if (typeSystem != null) {
-            containerChildren.add(typeSystem);
-        }
-        if (specializations != null) {
-            for (MessageContainer specialization : specializations) {
-                if (specialization.getMessageElement() != null) {
-                    containerChildren.add(specialization);
-                }
-            }
-        }
-        if (executableTypes != null) {
-            containerChildren.addAll(getExecutableTypes());
-        }
-        if (shortCircuits != null) {
-            containerChildren.addAll(shortCircuits);
-        }
-        if (children != null) {
-            containerChildren.addAll(children);
-        }
-        if (fields != null) {
-            containerChildren.addAll(fields);
-        }
-        if (casts != null) {
-            containerChildren.addAll(casts);
-        }
-        return containerChildren;
-    }
-
-    public ParameterSpec getInstanceParameterSpec() {
-        return instanceParameterSpec;
-    }
-
-    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
-        this.instanceParameterSpec = instanceParameter;
-    }
-
-    public String getNodeId() {
-        return nodeId;
-    }
-
-    public TypeMirror getNodeType() {
-        return getTemplateType().asType();
-    }
-
-    public boolean needsFactory() {
-        if (specializations == null) {
-            return false;
-        }
-        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-            return false;
-        }
-
-        boolean noSpecialization = true;
-        for (SpecializationData specialization : specializations) {
-            noSpecialization = noSpecialization && !specialization.isSpecialized();
-        }
-        return !noSpecialization;
-    }
-
-    public boolean supportsFrame() {
-        if (executableTypes != null) {
-            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
-                if (execType.getFrameParameter() == null) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public NodeExecutionData findExecutionByExpression(String childNameExpression) {
-        String childName = childNameExpression;
-        int index = -1;
-
-        int start = childName.indexOf('[');
-        int end = childName.lastIndexOf(']');
-        if (start != -1 && end != -1 && start < end) {
-            try {
-                index = Integer.parseInt(childName.substring(start + 1, end));
-                childName = childName.substring(0, start);
-                childName = NodeExecutionData.createName(childName, index);
-            } catch (NumberFormatException e) {
-                // ignore
-            }
-        }
-
-        for (NodeExecutionData execution : childExecutions) {
-            if (execution.getName().equals(childName) && (execution.getChildIndex() == -1 || execution.getChildIndex() == index)) {
-                return execution;
-            }
-        }
-        return null;
-    }
-
-    public List<NodeData> getNodesWithFactories() {
-        List<NodeData> nodeChildren = new ArrayList<>();
-        for (NodeData child : getEnclosingNodes()) {
-            if (child.needsFactory() && child.isGenerateFactory()) {
-                nodeChildren.add(child);
-            }
-            nodeChildren.addAll(child.getNodesWithFactories());
-        }
-        return nodeChildren;
-    }
-
-    public NodeData getDeclaringNode() {
-        return declaringNode;
-    }
-
-    public List<NodeData> getEnclosingNodes() {
-        return enclosingNodes;
-    }
-
-    public List<ExecutableElement> getAllTemplateMethods() {
-        List<ExecutableElement> methods = new ArrayList<>();
-
-        for (SpecializationData specialization : getSpecializations()) {
-            methods.add(specialization.getMethod());
-        }
-
-        for (ExecutableTypeData execType : getExecutableTypes()) {
-            if (execType.getMethod() != null) {
-                methods.add(execType.getMethod());
-            }
-        }
-        for (ShortCircuitData shortcircuit : getShortCircuits()) {
-            methods.add(shortcircuit.getMethod());
-        }
-
-        if (getCasts() != null) {
-            for (CreateCastData castData : getCasts()) {
-                methods.add(castData.getMethod());
-            }
-        }
-
-        return methods;
-    }
-
-    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
-        for (ExecutableTypeData type : types) {
-            if (context.isType(type.getReturnType(), Object.class)) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            if (!context.isType(type.getReturnType(), void.class)) {
-                return type;
-            }
-        }
-
-        for (ExecutableTypeData type : types) {
-            return type;
-        }
-        return null;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
-        if (evaluatedCount == -1) {
-            return executableTypes;
-        } else {
-            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
-            for (ExecutableTypeData type : executableTypes) {
-                if (type.getEvaluatedCount() == evaluatedCount) {
-                    filteredTypes.add(type);
-                }
-            }
-            return filteredTypes;
-        }
-    }
-
-    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
-        List<ExecutableTypeData> types = new ArrayList<>();
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (!type.hasUnexpectedValue(context)) {
-                types.add(type);
-            }
-        }
-        return types;
-    }
-
-    public ExecutableTypeData findExecutableType(TypeMirror primitiveType, int evaluatedCount) {
-        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
-            if (ElementUtils.typeEquals(type.getReturnType(), primitiveType)) {
-                return type;
-            }
-        }
-        return null;
-    }
-
-    public boolean needsRewrites(ProcessorContext context) {
-        boolean needsRewrites = false;
-
-        for (SpecializationData specialization : getSpecializations()) {
-            if (specialization.hasRewrite(context)) {
-                needsRewrites = true;
-                break;
-            }
-        }
-        return needsRewrites || getSpecializations().size() > 1;
-    }
-
-    public SpecializationData getPolymorphicSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isPolymorphic()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getGenericSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isFallback()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    public SpecializationData getUninitializedSpecialization() {
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isUninitialized()) {
-                return specialization;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return typeSystem;
-    }
-
-    @Override
-    public String dump() {
-        return dump(0);
-    }
-
-    private String dump(int level) {
-        String indent = "";
-        for (int i = 0; i < level; i++) {
-            indent += "    ";
-        }
-        StringBuilder builder = new StringBuilder();
-
-        builder.append(String.format("%s%s {", indent, toString()));
-
-        dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType()));
-        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
-        dumpProperty(builder, indent, "fields", getChildren());
-        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
-        dumpProperty(builder, indent, "specializations", getSpecializations());
-        dumpProperty(builder, indent, "casts", getCasts());
-        dumpProperty(builder, indent, "messages", collectMessages());
-        if (getEnclosingNodes().size() > 0) {
-            builder.append(String.format("\n%s  children = [", indent));
-            for (NodeData node : getEnclosingNodes()) {
-                builder.append("\n");
-                builder.append(node.dump(level + 1));
-            }
-            builder.append(String.format("\n%s  ]", indent));
-        }
-        builder.append(String.format("%s}", indent));
-        return builder.toString();
-    }
-
-    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
-        if (value instanceof List) {
-            List<?> list = (List<?>) value;
-            if (!list.isEmpty()) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
-            }
-        } else {
-            if (value != null) {
-                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
-            }
-        }
-    }
-
-    private static String dumpList(String indent, List<?> array) {
-        if (array == null) {
-            return "null";
-        }
-
-        if (array.isEmpty()) {
-            return "[]";
-        } else if (array.size() == 1) {
-            return "[" + array.get(0).toString() + "]";
-        }
-
-        StringBuilder b = new StringBuilder();
-        b.append("[");
-        for (Object object : array) {
-            b.append("\n        ");
-            b.append(indent);
-            b.append(object);
-            b.append(", ");
-        }
-        b.append("\n    ").append(indent).append("]");
-        return b.toString();
-    }
-
-    public NodeChildData findChild(String name) {
-        for (NodeChildData field : getChildren()) {
-            if (field.getName().equals(name)) {
-                return field;
-            }
-        }
-        return null;
-    }
-
-    public List<NodeChildData> getChildren() {
-        return children;
-    }
-
-    public List<SpecializationData> getSpecializations() {
-        return specializations;
-    }
-
-    public ExecutableTypeData getGenericExecutableType(ExecutableTypeData typeHint) {
-        ExecutableTypeData polymorphicDelegate = null;
-        if (typeHint != null) {
-            polymorphicDelegate = typeHint;
-            while (polymorphicDelegate.getDelegatedTo() != null && polymorphicDelegate.getEvaluatedCount() != getSignatureSize()) {
-                polymorphicDelegate = polymorphicDelegate.getDelegatedTo();
-            }
-        }
-        if (polymorphicDelegate == null) {
-            for (ExecutableTypeData type : getExecutableTypes()) {
-                if (type.getDelegatedTo() == null && type.getEvaluatedCount() == getSignatureSize()) {
-                    polymorphicDelegate = type;
-                    break;
-                }
-            }
-        }
-        return polymorphicDelegate;
-    }
-
-    public List<ExecutableTypeData> getExecutableTypes() {
-        return getExecutableTypes(-1);
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public int getMinimalEvaluatedParameters() {
-        int minimalEvaluatedParameters = Integer.MAX_VALUE;
-        for (ExecutableTypeData type : getExecutableTypes()) {
-            minimalEvaluatedParameters = Math.min(minimalEvaluatedParameters, type.getEvaluatedCount());
-        }
-        return minimalEvaluatedParameters;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + getNodeId() + "]";
-    }
-
-    public CreateCastData findCast(String name) {
-        if (getCasts() != null) {
-            for (CreateCastData cast : getCasts()) {
-                if (cast.getChildNames().contains(name)) {
-                    return cast;
-                }
-            }
-        }
-        return null;
-    }
-
-    public int compareTo(NodeData o) {
-        return getNodeId().compareTo(o.getNodeId());
-    }
-
-    public TypeMirror getGenericType(NodeExecutionData execution) {
-        return ElementUtils.getCommonSuperType(getContext(), getGenericTypes(execution));
-    }
-
-    public List<TypeMirror> getGenericTypes(NodeExecutionData execution) {
-        List<TypeMirror> types = new ArrayList<>();
-
-        // add types possible through return types and evaluated parameters in execute methods
-        if (execution.getChild() != null) {
-            for (ExecutableTypeData executable : execution.getChild().getNodeData().getExecutableTypes()) {
-                if (executable.hasUnexpectedValue(getContext())) {
-                    continue;
-                }
-                types.add(executable.getReturnType());
-            }
-        }
-
-        int executionIndex = execution.getIndex();
-        if (executionIndex >= 0) {
-            for (ExecutableTypeData typeData : getExecutableTypes()) {
-                List<TypeMirror> signatureParameters = typeData.getSignatureParameters();
-                if (executionIndex < signatureParameters.size()) {
-                    TypeMirror genericType = signatureParameters.get(executionIndex);
-                    types.add(genericType);
-                }
-            }
-        }
-
-        return ElementUtils.uniqueSortedTypes(types, false);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-
-public class NodeExecutionData {
-
-    private final NodeChildData child;
-    private final String name;
-    private final int index;
-    private final int childIndex;
-    private final boolean shortCircuit;
-    private final List<TypeMirror> typeRestrictions = new ArrayList<>();
-
-    public NodeExecutionData(NodeChildData child, int index, int childIndex, boolean shortCircuit) {
-        this.child = child;
-        this.index = index;
-        this.childIndex = childIndex;
-        this.shortCircuit = shortCircuit;
-        this.name = createName();
-    }
-
-    private String createName() {
-        return child != null ? createName(child.getName(), childIndex) : ("arg" + index);
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public List<TypeMirror> getTypeRestrictions() {
-        return typeRestrictions;
-    }
-
-    public TypeMirror getNodeType() {
-        TypeMirror type;
-        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
-            type = ((ArrayType) child.getNodeType()).getComponentType();
-        } else {
-            type = child.getNodeType();
-        }
-        return type;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public NodeChildData getChild() {
-        return child;
-    }
-
-    public int getChildIndex() {
-        return childIndex;
-    }
-
-    public boolean isIndexed() {
-        return childIndex > -1;
-    }
-
-    public boolean isShortCircuit() {
-        return shortCircuit;
-    }
-
-    public String getIndexedName() {
-        return createIndexedName(child, childIndex);
-    }
-
-    public static String createIndexedName(NodeChildData child, int varArgsIndex) {
-        String shortCircuitName = child.getName();
-        if (child.getCardinality().isMany()) {
-            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
-        }
-        return shortCircuitName;
-    }
-
-    public static String createName(String childName, int index) {
-        if (index > -1) {
-            return childName + index;
-        }
-        return childName;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class NodeFieldData extends MessageContainer {
-
-    private final Element messageElement;
-    private final AnnotationMirror messageAnnotation;
-    private final boolean generated;
-    private ExecutableElement getter;
-    private final VariableElement variable;
-
-    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, VariableElement variableElement, boolean generated) {
-        this.messageElement = messageElement;
-        this.messageAnnotation = messageAnnotation;
-        this.generated = generated;
-        this.variable = variableElement;
-    }
-
-    public VariableElement getVariable() {
-        return variable;
-    }
-
-    public void setGetter(ExecutableElement getter) {
-        this.getter = getter;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return messageElement;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return messageAnnotation;
-    }
-
-    public String getName() {
-        return variable.getSimpleName().toString();
-    }
-
-    public TypeMirror getType() {
-        return variable.asType();
-    }
-
-    public boolean isGenerated() {
-        return generated;
-    }
-
-    public ExecutableElement getGetter() {
-        return getter;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public final class Parameter {
-
-    private final ParameterSpec specification;
-    private TemplateMethod method;
-    private String localName;
-    private final int specificationVarArgsIndex;
-    private final int typeVarArgsIndex;
-    private final VariableElement variableElement;
-    private final TypeMirror type;
-
-    public Parameter(ParameterSpec specification, VariableElement variableElement, int specificationVarArgsIndex, int typeVarArgsIndex) {
-        this.specification = specification;
-        this.variableElement = variableElement;
-        this.type = variableElement.asType();
-        this.specificationVarArgsIndex = specificationVarArgsIndex;
-
-        String valueName = specification.getName() + "Value";
-        if (specificationVarArgsIndex > -1) {
-            valueName += specificationVarArgsIndex;
-        }
-        this.typeVarArgsIndex = typeVarArgsIndex;
-        this.localName = valueName;
-    }
-
-    public Parameter(Parameter parameter) {
-        this.specification = parameter.specification;
-        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
-        this.localName = parameter.localName;
-        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
-        this.variableElement = parameter.variableElement;
-        this.type = parameter.type;
-    }
-
-    public Parameter(Parameter parameter, TypeMirror newType) {
-        this.specification = parameter.specification;
-        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
-        this.localName = parameter.localName;
-        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
-        this.variableElement = parameter.variableElement;
-        this.type = newType;
-    }
-
-    public void setLocalName(String localName) {
-        this.localName = localName;
-    }
-
-    public VariableElement getVariableElement() {
-        return variableElement;
-    }
-
-    public int getTypeVarArgsIndex() {
-        return typeVarArgsIndex;
-    }
-
-    public int getSpecificationVarArgsIndex() {
-        return specificationVarArgsIndex;
-    }
-
-    public String getLocalName() {
-        return localName;
-    }
-
-    void setMethod(TemplateMethod method) {
-        this.method = method;
-    }
-
-    public ParameterSpec getSpecification() {
-        return specification;
-    }
-
-    public TemplateMethod getMethod() {
-        return method;
-    }
-
-    public TypeMirror getType() {
-        return type;
-    }
-
-    public boolean isTypeVarArgs() {
-        return typeVarArgsIndex >= 0;
-    }
-
-    public Parameter getPreviousParameter() {
-        return method.getPreviousParam(this);
-    }
-
-    @Override
-    public String toString() {
-        return "Parameter [localName=" + localName + ", type=" + getType() + ", variableElement=" + variableElement + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
-
-public class ParameterSpec {
-
-    private final String name;
-    private final Collection<TypeMirror> allowedTypes;
-    private final boolean anyType;
-
-    /** Type is bound to local final variable. */
-    private boolean local;
-    private boolean signature;
-    private boolean allowSubclasses = true;
-
-    /** Optional bound execution of node. */
-    private NodeExecutionData execution;
-    private TypeDef typeDefinition;
-
-    public ParameterSpec(String name, Collection<TypeMirror> allowedTypes) {
-        this.name = name;
-        this.allowedTypes = allowedTypes;
-        boolean anyTypeTemp = false;
-        for (TypeMirror type : allowedTypes) {
-            if (ElementUtils.isObject(type)) {
-                anyTypeTemp = true;
-                break;
-            }
-        }
-        this.anyType = anyTypeTemp;
-    }
-
-    public boolean isAnnotated() {
-        return false;
-    }
-
-    public ParameterSpec(ParameterSpec original, TypeMirror newType) {
-        this(original.name, newType);
-        this.local = original.local;
-        this.signature = original.signature;
-        this.execution = original.execution;
-        this.typeDefinition = original.typeDefinition;
-        this.allowSubclasses = original.allowSubclasses;
-    }
-
-    public ParameterSpec(String name, TypeMirror type) {
-        this(name, Arrays.asList(type));
-    }
-
-    public void setAllowSubclasses(boolean allowSubclasses) {
-        this.allowSubclasses = allowSubclasses;
-    }
-
-    public NodeExecutionData getExecution() {
-        return execution;
-    }
-
-    public void setExecution(NodeExecutionData executionData) {
-        this.execution = executionData;
-        this.signature = execution != null;
-    }
-
-    public void setSignature(boolean signature) {
-        this.signature = signature;
-    }
-
-    void setTypeDefinition(TypeDef typeDefinition) {
-        this.typeDefinition = typeDefinition;
-    }
-
-    TypeDef getTypeDefinition() {
-        return typeDefinition;
-    }
-
-    public void setLocal(boolean local) {
-        this.local = local;
-    }
-
-    public boolean isSignature() {
-        return signature;
-    }
-
-    public boolean isLocal() {
-        return local;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public Collection<TypeMirror> getAllowedTypes() {
-        return allowedTypes;
-    }
-
-    public boolean matches(VariableElement variable) {
-        if (anyType) {
-            return true;
-        } else {
-            for (TypeMirror type : allowedTypes) {
-                if (ElementUtils.typeEquals(variable.asType(), type)) {
-                    return true;
-                }
-            }
-            if (allowSubclasses) {
-                for (TypeMirror type : allowedTypes) {
-                    if (ElementUtils.isSubtypeBoxed(ProcessorContext.getInstance(), variable.asType(), type)) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        return toSignatureString(false);
-    }
-
-    public String toSignatureString(boolean typeOnly) {
-        StringBuilder builder = new StringBuilder();
-        if (typeDefinition != null) {
-            builder.append("<" + typeDefinition.getName() + ">");
-        } else if (getAllowedTypes().size() >= 1) {
-            builder.append(ElementUtils.getSimpleName(getAllowedTypes().iterator().next()));
-        } else {
-            builder.append("void");
-        }
-        if (!typeOnly) {
-            builder.append(" ");
-            builder.append(getName());
-        }
-        return builder.toString();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class ShortCircuitData extends TemplateMethod {
-
-    private ShortCircuitData genericShortCircuitMethod;
-    private final String valueName;
-
-    public ShortCircuitData(TemplateMethod template, String valueName) {
-        super(template);
-        this.valueName = valueName;
-    }
-
-    public String getValueName() {
-        return valueName;
-    }
-
-    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
-        this.genericShortCircuitMethod = genericShortCircuitMethod;
-    }
-
-    public boolean isGeneric() {
-        return genericShortCircuitMethod == null;
-    }
-
-    public ShortCircuitData getGeneric() {
-        if (isGeneric()) {
-            return this;
-        } else {
-            return genericShortCircuitMethod;
-        }
-    }
-
-    public boolean isCompatibleTo(SpecializationData specialization) {
-        if (isGeneric() && specialization.isFallback()) {
-            return true;
-        }
-
-        for (Parameter param : getParameters()) {
-            Parameter specializationParam = specialization.findParameter(param.getLocalName());
-            if (!ElementUtils.typeEquals(param.getType(), specializationParam.getType())) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,395 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public final class SpecializationData extends TemplateMethod {
-
-    public enum SpecializationKind {
-        UNINITIALIZED,
-        SPECIALIZED,
-        POLYMORPHIC,
-        FALLBACK
-    }
-
-    private final NodeData node;
-    private SpecializationKind kind;
-    private final List<SpecializationThrowsData> exceptions;
-    private List<GuardExpression> guards = Collections.emptyList();
-    private List<CacheExpression> caches = Collections.emptyList();
-    private List<AssumptionExpression> assumptionExpressions = Collections.emptyList();
-    private List<ShortCircuitData> shortCircuits;
-    private final Set<SpecializationData> contains = new TreeSet<>();
-    private final Set<String> containsNames = new TreeSet<>();
-    private final Set<SpecializationData> excludedBy = new TreeSet<>();
-    private String insertBeforeName;
-    private SpecializationData insertBefore;
-    private boolean reachable;
-    private int index;
-    private DSLExpression limitExpression;
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) {
-        super(template);
-        this.node = node;
-        this.kind = kind;
-        this.exceptions = exceptions;
-        this.index = template.getNaturalOrder();
-
-        for (SpecializationThrowsData exception : exceptions) {
-            exception.setSpecialization(this);
-        }
-    }
-
-    public boolean isCacheBoundByGuard(CacheExpression cacheExpression) {
-        for (GuardExpression expression : getGuards()) {
-            if (expression.getExpression().findBoundVariableElements().contains(cacheExpression.getParameter().getVariableElement())) {
-                return true;
-            }
-        }
-
-        // check all next binding caches if they are bound by guard
-        Set<VariableElement> boundVariables = cacheExpression.getExpression().findBoundVariableElements();
-        boolean found = false;
-        for (CacheExpression expression : getCaches()) {
-            if (cacheExpression == expression) {
-                found = true;
-            } else if (found) {
-                if (boundVariables.contains(expression.getParameter().getVariableElement())) {
-                    if (isCacheBoundByGuard(expression)) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    public void setKind(SpecializationKind kind) {
-        this.kind = kind;
-    }
-
-    public boolean isDynamicParameterBound(DSLExpression expression) {
-        Set<VariableElement> boundVariables = expression.findBoundVariableElements();
-        for (Parameter parameter : getDynamicParameters()) {
-            if (boundVariables.contains(parameter.getVariableElement())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public Parameter findByVariable(VariableElement variable) {
-        for (Parameter parameter : getParameters()) {
-            if (ElementUtils.variableEquals(parameter.getVariableElement(), variable)) {
-                return parameter;
-            }
-        }
-        return null;
-    }
-
-    public DSLExpression getLimitExpression() {
-        return limitExpression;
-    }
-
-    public void setLimitExpression(DSLExpression limitExpression) {
-        this.limitExpression = limitExpression;
-    }
-
-    public void setInsertBefore(SpecializationData insertBefore) {
-        this.insertBefore = insertBefore;
-    }
-
-    public void setInsertBeforeName(String insertBeforeName) {
-        this.insertBeforeName = insertBeforeName;
-    }
-
-    public SpecializationData getInsertBefore() {
-        return insertBefore;
-    }
-
-    public String getInsertBeforeName() {
-        return insertBeforeName;
-    }
-
-    public Set<String> getContainsNames() {
-        return containsNames;
-    }
-
-    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
-        this(node, template, kind, new ArrayList<SpecializationThrowsData>());
-    }
-
-    public Set<SpecializationData> getContains() {
-        return contains;
-    }
-
-    public Set<SpecializationData> getExcludedBy() {
-        return excludedBy;
-    }
-
-    public void setReachable(boolean reachable) {
-        this.reachable = reachable;
-    }
-
-    public boolean isReachable() {
-        return reachable;
-    }
-
-    public boolean isPolymorphic() {
-        return kind == SpecializationKind.POLYMORPHIC;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (exceptions != null) {
-            sinks.addAll(exceptions);
-        }
-        if (guards != null) {
-            sinks.addAll(guards);
-        }
-        if (caches != null) {
-            sinks.addAll(caches);
-        }
-        if (assumptionExpressions != null) {
-            sinks.addAll(assumptionExpressions);
-        }
-        return sinks;
-    }
-
-    public boolean hasRewrite(ProcessorContext context) {
-        if (!getExceptions().isEmpty()) {
-            return true;
-        }
-        if (!getGuards().isEmpty()) {
-            return true;
-        }
-        if (!getAssumptionExpressions().isEmpty()) {
-            return true;
-        }
-
-        for (Parameter parameter : getSignatureParameters()) {
-            NodeChildData child = parameter.getSpecification().getExecution().getChild();
-            if (child != null) {
-                ExecutableTypeData type = child.findExecutableType(parameter.getType());
-                if (type == null) {
-                    type = child.findAnyGenericExecutableType(context);
-                }
-                if (type.hasUnexpectedValue(context)) {
-                    return true;
-                }
-                if (ElementUtils.needsCastTo(type.getReturnType(), parameter.getType())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int compareTo(TemplateMethod other) {
-        if (this == other) {
-            return 0;
-        } else if (!(other instanceof SpecializationData)) {
-            return super.compareTo(other);
-        }
-        SpecializationData m2 = (SpecializationData) other;
-        int kindOrder = kind.compareTo(m2.kind);
-        if (kindOrder != 0) {
-            return kindOrder;
-        }
-
-        int compare = 0;
-        int order1 = index;
-        int order2 = m2.index;
-        if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) {
-            compare = Integer.compare(order1, order2);
-            if (compare != 0) {
-                return compare;
-            }
-        }
-
-        return super.compareTo(other);
-    }
-
-    public void setIndex(int order) {
-        this.index = order;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public NodeData getNode() {
-        return node;
-    }
-
-    public void setGuards(List<GuardExpression> guards) {
-        this.guards = guards;
-    }
-
-    public boolean isSpecialized() {
-        return kind == SpecializationKind.SPECIALIZED;
-    }
-
-    public boolean isFallback() {
-        return kind == SpecializationKind.FALLBACK;
-    }
-
-    public boolean isUninitialized() {
-        return kind == SpecializationKind.UNINITIALIZED;
-    }
-
-    public List<SpecializationThrowsData> getExceptions() {
-        return exceptions;
-    }
-
-    public List<GuardExpression> getGuards() {
-        return guards;
-    }
-
-    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
-        this.shortCircuits = shortCircuits;
-    }
-
-    public List<ShortCircuitData> getShortCircuits() {
-        return shortCircuits;
-    }
-
-    public SpecializationData findNextSpecialization() {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = 0; i < specializations.size() - 1; i++) {
-            if (specializations.get(i) == this) {
-                return specializations.get(i + 1);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getDynamicTypes());
-    }
-
-    public boolean isFrameUsed() {
-        return getFrame() != null;
-    }
-
-    public List<CacheExpression> getCaches() {
-        return caches;
-    }
-
-    public void setCaches(List<CacheExpression> caches) {
-        this.caches = caches;
-    }
-
-    public void setAssumptionExpressions(List<AssumptionExpression> assumptionExpressions) {
-        this.assumptionExpressions = assumptionExpressions;
-    }
-
-    public List<AssumptionExpression> getAssumptionExpressions() {
-        return assumptionExpressions;
-    }
-
-    public boolean hasMultipleInstances() {
-        if (!getCaches().isEmpty()) {
-            for (GuardExpression guard : getGuards()) {
-                DSLExpression guardExpression = guard.getExpression();
-                Set<VariableElement> boundVariables = guardExpression.findBoundVariableElements();
-                if (isDynamicParameterBound(guardExpression)) {
-                    for (CacheExpression cache : getCaches()) {
-                        if (boundVariables.contains(cache.getParameter().getVariableElement())) {
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    public boolean isReachableAfter(SpecializationData prev) {
-        if (!prev.isSpecialized()) {
-            return true;
-        }
-
-        if (!prev.getExceptions().isEmpty()) {
-            // may get excluded by exception
-            return true;
-        }
-
-        if (hasMultipleInstances()) {
-            // may fallthrough due to limit
-            return true;
-        }
-
-        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
-        Iterator<Parameter> prevSignature = prev.getSignatureParameters().iterator();
-
-        TypeSystemData typeSystem = prev.getNode().getTypeSystem();
-        while (currentSignature.hasNext() && prevSignature.hasNext()) {
-            TypeMirror currentType = currentSignature.next().getType();
-            TypeMirror prevType = prevSignature.next().getType();
-
-            if (!typeSystem.isImplicitSubtypeOf(currentType, prevType)) {
-                return true;
-            }
-        }
-
-        if (!prev.getAssumptionExpressions().isEmpty()) {
-            // TODO: chumer: we could at least check reachability after trivial assumptions
-            // not sure if this is worth it.
-            return true;
-        }
-
-        Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
-        Iterator<GuardExpression> currentGuards = getGuards().iterator();
-        while (prevGuards.hasNext()) {
-            GuardExpression prevGuard = prevGuards.next();
-            GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null;
-            if (currentGuard == null || !currentGuard.implies(prevGuard)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public CacheExpression findCache(Parameter resolvedParameter) {
-        for (CacheExpression cache : getCaches()) {
-            if (cache.getParameter() == resolvedParameter) {
-                return cache;
-            }
-        }
-        return null;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-public class SpecializationThrowsData extends MessageContainer {
-
-    private final AnnotationValue annotationValue;
-    private final AnnotationMirror annotationMirror;
-    private final TypeMirror javaClass;
-    private SpecializationData specialization;
-
-    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
-        this.annotationMirror = annotationMirror;
-        this.annotationValue = value;
-        this.javaClass = javaClass;
-    }
-
-    void setSpecialization(SpecializationData specialization) {
-        this.specialization = specialization;
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return specialization.getMessageElement();
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return annotationMirror;
-    }
-
-    @Override
-    public AnnotationValue getMessageAnnotationValue() {
-        return annotationValue;
-    }
-
-    public TypeMirror getJavaClass() {
-        return javaClass;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    public AnnotationMirror getAnnotationMirror() {
-        return annotationMirror;
-    }
-
-    public SpecializationData getTransitionTo() {
-        return specialization.findNextSpecialization();
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public abstract class Template extends MessageContainer {
-
-    private final ProcessorContext context;
-    private final TypeElement templateType;
-    private final AnnotationMirror annotation;
-
-    public Template(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) {
-        this.context = context;
-        this.templateType = templateType;
-        this.annotation = annotation;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    @Override
-    public MessageContainer getBaseContainer() {
-        return this;
-    }
-
-    public abstract TypeSystemData getTypeSystem();
-
-    @Override
-    public Element getMessageElement() {
-        return templateType;
-    }
-
-    public String dump() {
-        return toString();
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public TypeElement getTemplateType() {
-        return templateType;
-    }
-
-    public AnnotationMirror getTemplateTypeAnnotation() {
-        return annotation;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(getTemplateType()) + "]";
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.util.*;
-
-/**
- * Note: this class has a natural ordering that is inconsistent with equals.
- */
-public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
-
-    public static final String FRAME_NAME = "frameValue";
-    public static final int NO_NATURAL_ORDER = -1;
-
-    private String id;
-    private final Template template;
-    private final int naturalOrder;
-    private final MethodSpec specification;
-    private final ExecutableElement method;
-    private final AnnotationMirror markerAnnotation;
-    private Parameter returnType;
-    private final List<Parameter> parameters;
-    private final Map<String, Parameter> parameterCache = new HashMap<>();
-
-    public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, Parameter returnType,
-                    List<Parameter> parameters) {
-        this.template = template;
-        this.specification = specification;
-        this.naturalOrder = naturalOrder;
-        this.method = method;
-        this.markerAnnotation = markerAnnotation;
-        this.returnType = returnType;
-        this.parameters = new ArrayList<>();
-        for (Parameter param : parameters) {
-            Parameter newParam = new Parameter(param);
-            this.parameters.add(newParam);
-            newParam.setMethod(this);
-            parameterCache.put(param.getLocalName(), param);
-        }
-        if (returnType != null) {
-            parameterCache.put(returnType.getLocalName(), returnType);
-        }
-        this.id = id;
-    }
-
-    public final Parameter getFrame() {
-        return findParameter(FRAME_NAME);
-    }
-
-    public void removeParameter(Parameter p) {
-        this.parameters.remove(p);
-        this.parameterCache.remove(p.getLocalName());
-        p.setMethod(this);
-    }
-
-    public void addParameter(int index, Parameter p) {
-        this.parameters.add(index, p);
-        this.parameterCache.put(p.getLocalName(), p);
-        p.setMethod(this);
-    }
-
-    public String createReferenceName() {
-        if (getMethod() == null) {
-            return "-";
-        }
-        return ElementUtils.createReferenceName(getMethod());
-    }
-
-    public int getNaturalOrder() {
-        return naturalOrder;
-    }
-
-    public TemplateMethod(TemplateMethod method) {
-        this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
-        this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
-        getMessages().addAll(method.getMessages());
-    }
-
-    @Override
-    public Element getMessageElement() {
-        return method;
-    }
-
-    @Override
-    public AnnotationMirror getMessageAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        return Collections.emptyList();
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public Template getTemplate() {
-        return template;
-    }
-
-    public MethodSpec getSpecification() {
-        return specification;
-    }
-
-    public Parameter getReturnType() {
-        return returnType;
-    }
-
-    public void replaceParameter(String localName, Parameter newParameter) {
-        if (returnType.getLocalName().equals(localName)) {
-            returnType = newParameter;
-        } else {
-            Parameter local = findParameter(localName);
-            int index = parameters.indexOf(local);
-            parameters.set(index, newParameter);
-        }
-        parameterCache.put(newParameter.getLocalName(), newParameter);
-        newParameter.setMethod(this);
-    }
-
-    public Iterable<Parameter> getDynamicParameters() {
-        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
-            public boolean evaluate(Parameter value) {
-                return !value.getSpecification().isLocal() && !value.getSpecification().isAnnotated();
-            }
-        });
-    }
-
-    public Iterable<Parameter> getSignatureParameters() {
-        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
-            public boolean evaluate(Parameter value) {
-                return value.getSpecification().isSignature();
-            }
-        });
-    }
-
-    public List<Parameter> getParameters() {
-        return parameters;
-    }
-
-    public Parameter findParameterOrDie(NodeExecutionData execution) {
-        for (Parameter parameter : parameters) {
-            if (parameter.getSpecification().isSignature() && parameter.getSpecification().getExecution() == execution) {
-                return parameter;
-            }
-        }
-        throw new AssertionError("Could not find parameter for execution");
-    }
-
-    public List<Parameter> findByExecutionData(NodeExecutionData execution) {
-        List<Parameter> foundParameters = new ArrayList<>();
-        for (Parameter parameter : getParameters()) {
-            ParameterSpec spec = parameter.getSpecification();
-            if (spec != null && spec.getExecution() != null && spec.getExecution().equals(execution) && parameter.getSpecification().isSignature()) {
-                foundParameters.add(parameter);
-            }
-        }
-        return foundParameters;
-    }
-
-    public Parameter findParameter(String valueName) {
-        return parameterCache.get(valueName);
-    }
-
-    public List<Parameter> getReturnTypeAndParameters() {
-        List<Parameter> allParameters = new ArrayList<>(getParameters().size() + 1);
-        if (getReturnType() != null) {
-            allParameters.add(getReturnType());
-        }
-        allParameters.addAll(getParameters());
-        return Collections.unmodifiableList(allParameters);
-    }
-
-    public ExecutableElement getMethod() {
-        return method;
-    }
-
-    public String getMethodName() {
-        if (getMethod() != null) {
-            return getMethod().getSimpleName().toString();
-        } else {
-            return "$synthetic";
-        }
-    }
-
-    public AnnotationMirror getMarkerAnnotation() {
-        return markerAnnotation;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
-    }
-
-    public Parameter getPreviousParam(Parameter searchParam) {
-        Parameter prev = null;
-        for (Parameter param : getParameters()) {
-            if (param == searchParam) {
-                return prev;
-            }
-            prev = param;
-        }
-        return prev;
-    }
-
-    @SuppressWarnings("unused")
-    public int getSignatureSize() {
-        int signatureSize = 0;
-        for (Parameter parameter : getSignatureParameters()) {
-            signatureSize++;
-        }
-        return signatureSize;
-    }
-
-    public TypeSignature getTypeSignature() {
-        TypeSignature signature = new TypeSignature();
-        signature.types.add(getReturnType().getType());
-        for (Parameter parameter : getSignatureParameters()) {
-            TypeMirror typeData = parameter.getType();
-            if (typeData != null) {
-                signature.types.add(typeData);
-            }
-        }
-        return signature;
-    }
-
-    public void updateSignature(TypeSignature signature) {
-        // TODO(CH): fails in normal usage - output ok though
-        // assert signature.size() >= 1;
-
-        int signatureIndex = 0;
-        for (Parameter parameter : getReturnTypeAndParameters()) {
-            if (!parameter.getSpecification().isSignature()) {
-                continue;
-            }
-            if (signatureIndex >= signature.size()) {
-                break;
-            }
-            TypeMirror newType = signature.get(signatureIndex++);
-            if (!ElementUtils.typeEquals(newType, parameter.getType())) {
-                replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType));
-            }
-        }
-    }
-
-    @Override
-    public int compareTo(TemplateMethod o) {
-        if (this == o) {
-            return 0;
-        }
-
-        int compare = compareBySignature(o);
-        if (compare == 0) {
-            // if signature sorting failed sort by id
-            compare = getId().compareTo(o.getId());
-        }
-        if (compare == 0) {
-            // if still no difference sort by enclosing type name
-            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(getMethod());
-            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(o.getMethod());
-            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
-        }
-        return compare;
-    }
-
-    public int compareBySignature(TemplateMethod compareMethod) {
-        List<TypeMirror> signature1 = getDynamicTypes();
-        List<TypeMirror> signature2 = compareMethod.getDynamicTypes();
-
-        int result = 0;
-        for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
-            TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
-            TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
-            result = ElementUtils.compareType(t1, t2);
-            if (result != 0) {
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    public List<TypeMirror> getDynamicTypes() {
-        List<TypeMirror> types = new ArrayList<>();
-        for (Parameter param : getDynamicParameters()) {
-            types.add(param.getType());
-        }
-        return types;
-    }
-
-    public static class TypeSignature implements Iterable<TypeMirror> {
-
-        private final List<TypeMirror> types;
-
-        public TypeSignature() {
-            this.types = new ArrayList<>();
-        }
-
-        public TypeSignature(List<TypeMirror> signature) {
-            this.types = signature;
-        }
-
-        @Override
-        public int hashCode() {
-            return types.hashCode();
-        }
-
-        public int size() {
-            return types.size();
-        }
-
-        public TypeMirror get(int index) {
-            return types.get(index);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof TypeSignature) {
-                return ((TypeSignature) obj).types.equals(types);
-            }
-            return super.equals(obj);
-        }
-
-        public Iterator<TypeMirror> iterator() {
-            return types.iterator();
-        }
-
-        @Override
-        public String toString() {
-            return types.toString();
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.type.*;
-
-public class TypeCastData extends TemplateMethod {
-
-    private final TypeMirror targetType;
-    private final TypeMirror sourceType;
-
-    public TypeCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
-        super(method);
-        this.sourceType = sourceType;
-        this.targetType = targetType;
-    }
-
-    public TypeMirror getSourceType() {
-        return sourceType;
-    }
-
-    public TypeMirror getTargetType() {
-        return targetType;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import javax.lang.model.type.*;
-
-public class TypeCheckData extends TemplateMethod {
-
-    private final TypeMirror checkedType;
-    private final TypeMirror valueType;
-
-    public TypeCheckData(TemplateMethod method, TypeMirror checkedType, TypeMirror valueType) {
-        super(method);
-        this.checkedType = checkedType;
-        this.valueType = valueType;
-    }
-
-    public TypeMirror getCheckedType() {
-        return checkedType;
-    }
-
-    public TypeMirror getValueType() {
-        return valueType;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.model;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-
-public class TypeSystemData extends Template {
-
-    private final List<ImplicitCastData> implicitCasts = new ArrayList<>();
-    private final List<TypeCastData> casts = new ArrayList<>();
-    private final List<TypeCheckData> checks = new ArrayList<>();
-    private final List<TypeMirror> legacyTypes = new ArrayList<>();
-
-    private Set<String> legacyTypeIds;
-
-    private final boolean isDefault;
-    private final DSLOptions options;
-
-    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options, boolean isDefault) {
-        super(context, templateType, annotation);
-        this.options = options;
-        this.isDefault = isDefault;
-    }
-
-    public boolean isDefault() {
-        return isDefault;
-    }
-
-    public DSLOptions getOptions() {
-        return options;
-    }
-
-    @Override
-    public TypeSystemData getTypeSystem() {
-        return this;
-    }
-
-    public List<TypeMirror> getLegacyTypes() {
-        return legacyTypes;
-    }
-
-    public TypeCastData getCast(TypeMirror targetType) {
-        for (TypeCastData cast : casts) {
-            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
-                return cast;
-            }
-        }
-        return null;
-    }
-
-    public TypeCheckData getCheck(TypeMirror type) {
-        for (TypeCheckData check : checks) {
-            if (ElementUtils.typeEquals(check.getCheckedType(), type)) {
-                return check;
-            }
-        }
-        return null;
-    }
-
-    public List<ImplicitCastData> getImplicitCasts() {
-        return implicitCasts;
-    }
-
-    public List<TypeCastData> getCasts() {
-        return casts;
-    }
-
-    public List<TypeCheckData> getChecks() {
-        return checks;
-    }
-
-    @Override
-    protected List<MessageContainer> findChildContainers() {
-        List<MessageContainer> sinks = new ArrayList<>();
-        if (checks != null) {
-            sinks.addAll(checks);
-        }
-        if (casts != null) {
-            sinks.addAll(casts);
-        }
-        if (implicitCasts != null) {
-            sinks.addAll(implicitCasts);
-        }
-        return sinks;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + "]";
-    }
-
-    public List<ImplicitCastData> lookupByTargetType(TypeMirror targetType) {
-        if (getImplicitCasts() == null) {
-            return Collections.emptyList();
-        }
-        List<ImplicitCastData> foundCasts = new ArrayList<>();
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
-                foundCasts.add(cast);
-            }
-        }
-        return foundCasts;
-    }
-
-    public ImplicitCastData lookupCast(TypeMirror sourceType, TypeMirror targetType) {
-        if (getImplicitCasts() == null) {
-            return null;
-        }
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (ElementUtils.typeEquals(cast.getSourceType(), sourceType) && ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
-                return cast;
-            }
-        }
-        return null;
-    }
-
-    public boolean hasImplicitSourceTypes(TypeMirror targetType) {
-        if (getImplicitCasts() == null) {
-            return false;
-        }
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public List<TypeMirror> lookupTargetTypes() {
-        List<TypeMirror> sourceTypes = new ArrayList<>();
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            sourceTypes.add(cast.getTargetType());
-        }
-        return ElementUtils.uniqueSortedTypes(sourceTypes, true);
-    }
-
-    public List<TypeMirror> lookupSourceTypes(TypeMirror targetType) {
-        List<TypeMirror> sourceTypes = new ArrayList<>();
-        sourceTypes.add(targetType);
-        for (ImplicitCastData cast : getImplicitCasts()) {
-            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
-                sourceTypes.add(cast.getSourceType());
-            }
-        }
-        return ElementUtils.uniqueSortedTypes(sourceTypes, true);
-    }
-
-    public boolean isImplicitSubtypeOf(TypeMirror source, TypeMirror target) {
-        List<ImplicitCastData> targetCasts = lookupByTargetType(target);
-        for (ImplicitCastData cast : targetCasts) {
-            if (ElementUtils.isSubtype(boxType(source), boxType(cast.getSourceType()))) {
-                return true;
-            }
-        }
-        return ElementUtils.isSubtype(boxType(source), boxType(target));
-    }
-
-    public TypeMirror boxType(TypeMirror type) {
-        return ElementUtils.boxType(getContext(), type);
-    }
-
-    public boolean hasType(TypeMirror type) {
-        if (legacyTypeIds == null) {
-            legacyTypeIds = new HashSet<>();
-            for (TypeMirror legacyType : legacyTypes) {
-                legacyTypeIds.add(ElementUtils.getTypeId(legacyType));
-            }
-        }
-        return legacyTypeIds.contains(ElementUtils.getTypeId(type));
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.MessageContainer.Message;
-
-/**
- * THIS IS NOT PUBLIC API.
- */
-public abstract class AbstractParser<M extends MessageContainer> {
-
-    protected final ProcessorContext context;
-    protected final ProcessingEnvironment processingEnv;
-
-    protected final Log log;
-
-    public AbstractParser() {
-        this.context = ProcessorContext.getInstance();
-        this.processingEnv = context.getEnvironment();
-        this.log = context.getLog();
-    }
-
-    public final M parse(Element element) {
-        M model = null;
-        try {
-            AnnotationMirror mirror = null;
-            if (getAnnotationType() != null) {
-                mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
-            }
-
-            if (!context.getTruffleTypes().verify(context, element, mirror)) {
-                return null;
-            }
-            model = parse(element, mirror);
-            if (model == null) {
-                return null;
-            }
-
-            redirectMessages(new HashSet<MessageContainer>(), model, model);
-            model.emitMessages(context, log);
-            return filterErrorElements(model);
-        } catch (CompileErrorException e) {
-            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
-            return null;
-        }
-    }
-
-    private void redirectMessages(Set<MessageContainer> visitedSinks, MessageContainer model, MessageContainer baseContainer) {
-        List<Message> messages = model.getMessages();
-        for (int i = messages.size() - 1; i >= 0; i--) {
-            Message message = messages.get(i);
-            if (!ElementUtils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) {
-                // redirect message
-                MessageContainer original = message.getOriginalContainer();
-                String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
-                Message redirectedMessage = new Message(null, null, baseContainer, text, message.getKind());
-                model.getMessages().remove(i);
-                baseContainer.getMessages().add(redirectedMessage);
-            }
-        }
-
-        for (MessageContainer childContainer : model) {
-            if (visitedSinks.contains(childContainer)) {
-                continue;
-            }
-            visitedSinks.add(childContainer);
-
-            MessageContainer newBase = baseContainer;
-            if (childContainer.getBaseContainer() != null) {
-                newBase = childContainer.getBaseContainer();
-            }
-            redirectMessages(visitedSinks, childContainer, newBase);
-        }
-    }
-
-    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
-        StringBuilder b = new StringBuilder();
-        if (element != null) {
-            if (element.getKind() == ElementKind.METHOD) {
-                b.append("Method " + ElementUtils.createReferenceName((ExecutableElement) element));
-            } else {
-                b.append("Element " + element.getSimpleName());
-            }
-        }
-        if (mirror != null) {
-            b.append(" at annotation @" + ElementUtils.getSimpleName(mirror.getAnnotationType()).trim());
-        }
-
-        if (b.length() > 0) {
-            b.append(" is erroneous: ").append(text);
-            return b.toString();
-        } else {
-            return text;
-        }
-    }
-
-    protected M filterErrorElements(M model) {
-        return model.hasErrors() ? null : model;
-    }
-
-    protected abstract M parse(Element element, AnnotationMirror mirror);
-
-    public abstract Class<? extends Annotation> getAnnotationType();
-
-    public boolean isDelegateToRootDeclaredType() {
-        return false;
-    }
-
-    public List<Class<? extends Annotation>> getAllAnnotationTypes() {
-        List<Class<? extends Annotation>> list = new ArrayList<>();
-        if (getAnnotationType() != null) {
-            list.add(getAnnotationType());
-        }
-        list.addAll(getTypeDelegatedAnnotationTypes());
-        return list;
-    }
-
-    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
-        return Collections.emptyList();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class CreateCastParser extends NodeMethodParser<CreateCastData> {
-
-    public CreateCastParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return CreateCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
-        NodeChildData foundChild = null;
-        for (String childName : childNames) {
-            foundChild = getNode().findChild(childName);
-            if (foundChild != null) {
-                break;
-            }
-        }
-        TypeMirror baseType = getContext().getTruffleTypes().getNode();
-        if (foundChild != null) {
-            baseType = foundChild.getOriginalType();
-        }
-
-        MethodSpec spec = new MethodSpec(new ParameterSpec("child", baseType));
-        addDefaultFieldMethodSpec(spec);
-        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
-        childSpec.setSignature(true);
-        spec.addRequired(childSpec);
-        return spec;
-    }
-
-    @Override
-    public CreateCastData create(TemplateMethod method, boolean invalid) {
-        AnnotationMirror mirror = method.getMarkerAnnotation();
-        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
-        CreateCastData cast = new CreateCastData(method, childNames);
-        AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
-        TypeMirror type = null;
-        if (childNames == null || childNames.isEmpty()) {
-            cast.addError(value, "No value specified but required.");
-            return cast;
-        }
-
-        for (String childName : childNames) {
-            NodeChildData child = getNode().findChild(childName);
-            if (child == null) {
-                // error
-                cast.addError(value, "Specified child '%s' not found.", childName);
-                continue;
-            }
-            if (type == null) {
-                type = child.getNodeType();
-            } else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
-                cast.addError(value, "All child nodes for a cast must have the same node type.");
-                continue;
-            }
-        }
-        return cast;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/FallbackParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
-
-public class FallbackParser extends NodeMethodParser<SpecializationData> {
-
-    public FallbackParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        return createDefaultMethodSpec(method, mirror, true, null);
-    }
-
-    @Override
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        ParameterSpec parameterSpec = super.createValueParameterSpec(execution);
-        parameterSpec.setAllowSubclasses(false);
-        return parameterSpec;
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return new SpecializationData(getNode(), method, SpecializationKind.FALLBACK);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Fallback.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
-
-    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ImplicitCast.class;
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = new MethodSpec(new ParameterSpec("target", getContext().getType(Object.class)));
-        spec.addRequired(new ParameterSpec("source", getContext().getType(Object.class))).setSignature(true);
-        return spec;
-    }
-
-    @Override
-    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
-        if (invalid) {
-            return new ImplicitCastData(method, null, null);
-        }
-
-        Parameter target = method.findParameter("targetValue");
-        Parameter source = method.findParameter("sourceValue");
-
-        TypeMirror targetType = target.getType();
-        TypeMirror sourceType = source.getType();
-
-        if (ElementUtils.typeEquals(targetType, sourceType)) {
-            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
-        }
-
-        if (!method.getMethod().getModifiers().contains(Modifier.STATIC)) {
-            method.addError("@%s annotated method %s must be static.", ImplicitCast.class.getSimpleName(), method.getMethodName());
-        }
-
-        return new ImplicitCastData(method, sourceType, targetType);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public final class MethodSpecParser {
-
-    private boolean emitErrors = true;
-    private boolean useVarArgs = false;
-
-    private final Template template;
-
-    public MethodSpecParser(Template template) {
-        this.template = template;
-    }
-
-    public Template getTemplate() {
-        return template;
-    }
-
-    public boolean isEmitErrors() {
-        return emitErrors;
-    }
-
-    public boolean isUseVarArgs() {
-        return useVarArgs;
-    }
-
-    public void setEmitErrors(boolean emitErrors) {
-        this.emitErrors = emitErrors;
-    }
-
-    public void setUseVarArgs(boolean useVarArgs) {
-        this.useVarArgs = useVarArgs;
-    }
-
-    public TemplateMethod parse(MethodSpec methodSpecification, ExecutableElement method, AnnotationMirror annotation, int naturalOrder) {
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        methodSpecification.applyTypeDefinitions("types");
-
-        String id = method.getSimpleName().toString();
-        TypeMirror returnType = method.getReturnType();
-        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, method.getParameters());
-    }
-
-    public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
-                    List<? extends VariableElement> parameterTypes) {
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        Parameter returnTypeMirror = matchParameter(returnTypeSpec, new CodeVariableElement(returnType, "returnType"), -1, -1);
-        if (returnTypeMirror == null) {
-            if (isEmitErrors() && method != null) {
-                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
-                String expectedReturnType = returnTypeSpec.toSignatureString(true);
-                String actualReturnType = ElementUtils.getSimpleName(returnType);
-
-                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
-        if (parameters == null) {
-            if (isEmitErrors() && method != null) {
-                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
-                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
-                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
-                invalidMethod.addError(message);
-                return invalidMethod;
-            } else {
-                return null;
-            }
-        }
-
-        return new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters);
-    }
-
-    private static String createActualSignature(ExecutableElement method) {
-        StringBuilder b = new StringBuilder("(");
-        String sep = "";
-        if (method != null) {
-            for (VariableElement var : method.getParameters()) {
-                b.append(sep);
-                b.append(ElementUtils.getSimpleName(var.asType()));
-                sep = ", ";
-            }
-        }
-        b.append(")");
-        return b.toString();
-    }
-
-    /*
-     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
-     * offset until it finds a signature end that matches the required specification. If there is no
-     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
-     * ones are cut and used to parse the optional parameters.
-     */
-    private static List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) {
-        List<Parameter> parsedRequired = null;
-        int offset = 0;
-        for (; offset <= parameterTypes.size(); offset++) {
-            List<VariableElement> parameters = new ArrayList<>();
-            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
-            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
-            if (parsedRequired != null) {
-                break;
-            }
-        }
-
-        if (parsedRequired == null) {
-            return null;
-        }
-
-        if (parsedRequired.isEmpty() && offset == 0) {
-            offset = parameterTypes.size();
-        }
-        List<? extends VariableElement> potentialOptionals = parameterTypes.subList(0, offset);
-        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
-        if (parsedOptionals == null) {
-            return null;
-        }
-
-        List<Parameter> finalParameters = new ArrayList<>();
-        finalParameters.addAll(parsedOptionals);
-        finalParameters.addAll(parsedRequired);
-        return finalParameters;
-    }
-
-    private static List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) {
-        List<Parameter> parsedParams = new ArrayList<>();
-
-        int typeStartIndex = 0;
-        List<ParameterSpec> specifications = spec.getOptional();
-        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
-            ParameterSpec specification = specifications.get(specIndex);
-            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
-                VariableElement variable = types.get(typeIndex);
-                Parameter optionalParam = matchParameter(specification, variable, -1, -1);
-                if (optionalParam != null) {
-                    parsedParams.add(optionalParam);
-                    typeStartIndex = typeIndex + 1;
-                    continue outer;
-                }
-            }
-        }
-
-        if (typeStartIndex < types.size()) {
-            // not enough types found
-            return null;
-        }
-        return parsedParams;
-    }
-
-    private static List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) {
-        List<Parameter> parsedParams = new ArrayList<>();
-        List<ParameterSpec> specifications = spec.getRequired();
-        boolean specVarArgs = spec.isVariableRequiredParameters();
-        int typeIndex = 0;
-        int specificationIndex = 0;
-
-        ParameterSpec specification;
-        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
-            VariableElement actualType = nextActualType(types, typeIndex, typeVarArgs);
-            if (actualType == null) {
-                if (spec.isIgnoreAdditionalSpecifications()) {
-                    break;
-                }
-                return null;
-            }
-
-            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
-            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
-
-            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
-                // both specifications and types have a variable number of arguments
-                // we would get into an endless loop if we would continue
-                break;
-            }
-
-            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
-            if (resolvedParameter == null) {
-                return null;
-            }
-            parsedParams.add(resolvedParameter);
-            typeIndex++;
-            specificationIndex++;
-        }
-
-        // consume randomly ordered annotated parameters
-        VariableElement variable;
-        while ((variable = nextActualType(types, typeIndex, typeVarArgs)) != null) {
-            Parameter matchedParamter = matchAnnotatedParameter(spec, variable);
-            if (matchedParamter == null) {
-                break;
-            }
-            parsedParams.add(matchedParamter);
-            typeIndex++;
-        }
-
-        if (typeIndex < types.size()) {
-            if (spec.isIgnoreAdditionalParameters()) {
-                return parsedParams;
-            } else {
-                return null;
-            }
-        }
-
-        return parsedParams;
-    }
-
-    private static Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) {
-        for (ParameterSpec parameterSpec : spec.getAnnotations()) {
-            if (parameterSpec.matches(variable)) {
-                Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1);
-                if (matchedParameter != null) {
-                    matchedParameter.setLocalName(variable.getSimpleName().toString());
-                    return matchedParameter;
-                }
-            }
-        }
-        return null;
-    }
-
-    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
-        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
-            return specifications.get(specifications.size() - 1);
-        } else if (specIndex < specifications.size()) {
-            return specifications.get(specIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private static VariableElement nextActualType(List<VariableElement> types, int typeIndex, boolean varArgs) {
-        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
-            // unpack varargs array argument
-            VariableElement actualType = types.get(types.size() - 1);
-            if (actualType.asType().getKind() == TypeKind.ARRAY) {
-                actualType = new CodeVariableElement(((ArrayType) actualType.asType()).getComponentType(), actualType.getSimpleName().toString());
-            }
-            return actualType;
-        } else if (typeIndex < types.size()) {
-            return types.get(typeIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private static Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = variable.asType();
-        if (hasError(resolvedType)) {
-            return null;
-        }
-
-        if (!specification.matches(variable)) {
-            return null;
-        }
-
-        return new Parameter(specification, variable, specificationIndex, varArgsIndex);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
-
-    public NodeMethodParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-    }
-
-    public NodeData getNode() {
-        return template;
-    }
-
-    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
-        ParameterSpec spec = new ParameterSpec(execution.getName(), getPossibleParameterTypes(execution));
-        spec.setExecution(execution);
-        return spec;
-    }
-
-    protected Collection<TypeMirror> getPossibleParameterTypes(NodeExecutionData execution) {
-        return getNode().getGenericTypes(execution);
-    }
-
-    protected ParameterSpec createReturnParameterSpec() {
-        ParameterSpec returnValue = new ParameterSpec("returnValue", getPossibleReturnTypes());
-        returnValue.setExecution(getNode().getThisExecution());
-        return returnValue;
-    }
-
-    protected Collection<TypeMirror> getPossibleReturnTypes() {
-        return Arrays.asList(getNode().getGenericType(getNode().getThisExecution()));
-    }
-
-    @Override
-    public boolean isParsable(ExecutableElement method) {
-        if (getAnnotationType() != null) {
-            return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-        }
-
-        return true;
-    }
-
-    @SuppressWarnings("unused")
-    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
-        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
-
-        addDefaultFrame(methodSpec);
-        addDefaultFieldMethodSpec(methodSpec);
-        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
-
-        return methodSpec;
-    }
-
-    private void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
-        if (getNode().getChildren() == null) {
-            // children are null when parsing executable types
-            return;
-        }
-
-        for (NodeExecutionData execution : getNode().getChildExecutions()) {
-            if (breakName != null && execution.getIndexedName().equals(breakName)) {
-                break;
-            }
-
-            if (execution.isShortCircuit() && shortCircuitsEnabled) {
-                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
-            }
-            spec.addRequired(createValueParameterSpec(execution));
-        }
-    }
-
-    protected void addDefaultFrame(MethodSpec methodSpec) {
-        if (getNode().supportsFrame()) {
-            methodSpec.addOptional(new ParameterSpec("frame", getNode().getFrameType()));
-        }
-    }
-
-    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
-        for (NodeFieldData field : getNode().getFields()) {
-            if (field.getGetter() == null) {
-                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
-                spec.setLocal(true);
-                methodSpec.addOptional(spec);
-            }
-        }
-    }
-
-    private static String shortCircuitValueName(String valueName) {
-        return "has" + ElementUtils.firstLetterUpperCase(valueName);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1680 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.expression.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.java.compiler.*;
-import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
-import com.oracle.truffle.dsl.processor.java.model.*;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
-
-@DSLOptions
-public class NodeParser extends AbstractParser<NodeData> {
-
-    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
-                    NodeChildren.class);
-
-    @Override
-    protected NodeData parse(Element element, AnnotationMirror mirror) {
-        NodeData node = parseRootType((TypeElement) element);
-        if (Log.isDebug() && node != null) {
-            String dump = node.dump();
-            log.message(Kind.ERROR, null, null, null, dump);
-        }
-        return node;
-    }
-
-    @Override
-    protected NodeData filterErrorElements(NodeData model) {
-        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
-            NodeData node = filterErrorElements(iterator.next());
-            if (node == null) {
-                iterator.remove();
-            }
-        }
-        if (model.hasErrors()) {
-            return null;
-        }
-        return model;
-    }
-
-    @Override
-    public boolean isDelegateToRootDeclaredType() {
-        return true;
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    @Override
-    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
-        return ANNOTATIONS;
-    }
-
-    private NodeData parseRootType(TypeElement rootType) {
-        List<NodeData> enclosedNodes = new ArrayList<>();
-        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
-            NodeData enclosedChild = parseRootType(enclosedType);
-            if (enclosedChild != null) {
-                enclosedNodes.add(enclosedChild);
-            }
-        }
-        NodeData node;
-        try {
-            node = parseNode(rootType);
-        } catch (CompileErrorException e) {
-            throw e;
-        } catch (Throwable e) {
-            RuntimeException e2 = new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)));
-            e2.addSuppressed(e);
-            throw e2;
-        }
-        if (node == null && !enclosedNodes.isEmpty()) {
-            node = new NodeData(context, rootType);
-        }
-
-        if (node != null) {
-            for (NodeData enclosedNode : enclosedNodes) {
-                node.addEnclosedNode(enclosedNode);
-            }
-        }
-        return node;
-    }
-
-    private NodeData parseNode(TypeElement originalTemplateType) {
-        // reloading the type elements is needed for ecj
-        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
-
-        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
-            // generated nodes should not get called again.
-            return null;
-        }
-
-        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
-            return null;
-        }
-
-        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
-        List<Element> members = loadMembers(templateType);
-        // ensure the processed element has at least one @Specialization annotation.
-        if (!containsSpecializations(members)) {
-            return null;
-        }
-
-        NodeData node = parseNodeData(templateType, lookupTypes);
-        if (node.hasErrors()) {
-            return node;
-        }
-
-        node.getFields().addAll(parseFields(lookupTypes, members));
-        node.getChildren().addAll(parseChildren(lookupTypes, members));
-        node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members));
-        node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, node.getSignatureSize(), context.getFrameTypes(), false));
-
-        initializeExecutableTypes(node);
-        initializeImportGuards(node, lookupTypes, members);
-        initializeChildren(node);
-
-        if (node.hasErrors()) {
-            return node; // error sync point
-        }
-
-        if (node.hasErrors()) {
-            return node; // error sync point
-        }
-
-        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(members));
-        node.getSpecializations().addAll(new FallbackParser(context, node).parse(members));
-        node.getCasts().addAll(new CreateCastParser(context, node).parse(members));
-        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members));
-
-        if (node.hasErrors()) {
-            return node;  // error sync point
-        }
-        initializeSpecializations(members, node);
-        initializeExecutableTypeHierarchy(node);
-
-        verifySpecializationSameLength(node);
-        initializeShortCircuits(node); // requires specializations and polymorphic specializations
-
-        verifyVisibilities(node);
-        verifyMissingAbstractMethods(node, members);
-        verifyConstructors(node);
-        verifyNamingConvention(node.getShortCircuits(), "needs");
-        verifySpecializationThrows(node);
-        return node;
-    }
-
-    private static void initializeExecutableTypeHierarchy(NodeData node) {
-        SpecializationData polymorphic = node.getPolymorphicSpecialization();
-        if (polymorphic != null) {
-            boolean polymorphicSignatureFound = false;
-            List<TypeMirror> dynamicTypes = polymorphic.getDynamicTypes();
-            TypeMirror frame = null;
-            if (polymorphic.getFrame() != null) {
-                frame = dynamicTypes.remove(0);
-            }
-
-            ExecutableTypeData polymorphicType = new ExecutableTypeData(node, polymorphic.getReturnType().getType(), "execute", frame, dynamicTypes);
-            String genericName = ExecutableTypeData.createName(polymorphicType) + "_";
-            polymorphicType.setUniqueName(genericName);
-
-            for (ExecutableTypeData type : node.getExecutableTypes()) {
-                if (polymorphicType.sameSignature(type)) {
-                    polymorphicSignatureFound = true;
-                    break;
-                }
-            }
-
-            if (!polymorphicSignatureFound) {
-                node.getExecutableTypes().add(polymorphicType);
-            }
-        }
-
-        List<ExecutableTypeData> rootTypes = buildExecutableHierarchy(node);
-        List<ExecutableTypeData> additionalAbstractRootTypes = new ArrayList<>();
-        for (int i = 1; i < rootTypes.size(); i++) {
-            ExecutableTypeData rootType = rootTypes.get(i);
-            if (rootType.isAbstract()) {
-                // cannot implemement root
-                additionalAbstractRootTypes.add(rootType);
-            } else {
-                node.getExecutableTypes().remove(rootType);
-            }
-        }
-        if (!additionalAbstractRootTypes.isEmpty()) {
-            node.addError("Incompatible abstract execute methods found %s.", additionalAbstractRootTypes);
-        }
-
-        namesUnique(node.getExecutableTypes());
-
-    }
-
-    private static List<ExecutableTypeData> buildExecutableHierarchy(NodeData node) {
-        List<ExecutableTypeData> executes = node.getExecutableTypes();
-        if (executes.isEmpty()) {
-            return Collections.emptyList();
-        }
-        List<ExecutableTypeData> hierarchyExecutes = new ArrayList<>(executes);
-        Collections.sort(hierarchyExecutes);
-        ExecutableTypeData parent = hierarchyExecutes.get(0);
-        ListIterator<ExecutableTypeData> executesIterator = hierarchyExecutes.listIterator(1);
-        buildExecutableHierarchy(node, parent, executesIterator);
-        return hierarchyExecutes;
-    }
-
-    private static void buildExecutableHierarchy(NodeData node, ExecutableTypeData parent, ListIterator<ExecutableTypeData> executesIterator) {
-        while (executesIterator.hasNext()) {
-            ExecutableTypeData other = executesIterator.next();
-            if (other.canDelegateTo(parent)) {
-                parent.addDelegatedFrom(other);
-                executesIterator.remove();
-            }
-        }
-        for (int i = 1; i < parent.getDelegatedFrom().size(); i++) {
-            buildExecutableHierarchy(node, parent.getDelegatedFrom().get(i - 1), parent.getDelegatedFrom().listIterator(i));
-        }
-    }
-
-    private List<Element> loadMembers(TypeElement templateType) {
-        List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
-
-        return members;
-    }
-
-    private boolean containsSpecializations(List<Element> elements) {
-        boolean foundSpecialization = false;
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            if (ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class) != null) {
-                foundSpecialization = true;
-                break;
-            }
-        }
-        return foundSpecialization;
-    }
-
-    private void initializeImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> elements) {
-        for (TypeElement lookupType : lookupTypes) {
-            AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportStatic.class);
-            if (importAnnotation == null) {
-                continue;
-            }
-            AnnotationValue importClassesValue = ElementUtils.getAnnotationValue(importAnnotation, "value");
-            List<TypeMirror> importClasses = ElementUtils.getAnnotationValueList(TypeMirror.class, importAnnotation, "value");
-            if (importClasses.isEmpty()) {
-                node.addError(importAnnotation, importClassesValue, "At least import guard classes must be specified.");
-                continue;
-            }
-            for (TypeMirror importGuardClass : importClasses) {
-                if (importGuardClass.getKind() != TypeKind.DECLARED) {
-                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass));
-                    continue;
-                }
-
-                TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
-                if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) {
-                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass));
-                    continue;
-                }
-                elements.addAll(importPublicStaticMembers(typeElement, false));
-            }
-        }
-    }
-
-    private List<? extends Element> importPublicStaticMembers(TypeElement importGuardClass, boolean includeConstructors) {
-        // hack to reload type is necessary for incremental compiling in eclipse.
-        // otherwise methods inside of import guard types are just not found.
-        TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType()));
-
-        List<Element> members = new ArrayList<>();
-        for (Element importElement : processingEnv.getElementUtils().getAllMembers(typeElement)) {
-            if (!importElement.getModifiers().contains(Modifier.PUBLIC)) {
-                continue;
-            }
-
-            if (includeConstructors && importElement.getKind() == ElementKind.CONSTRUCTOR) {
-                members.add(importElement);
-            }
-
-            if (!importElement.getModifiers().contains(Modifier.STATIC)) {
-                continue;
-            }
-
-            ElementKind kind = importElement.getKind();
-            if (kind.isField() || kind == ElementKind.METHOD) {
-                members.add(importElement);
-            }
-        }
-        return members;
-    }
-
-    private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) {
-        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
-        TypeSystemData typeSystem = null;
-        if (typeSystemMirror != null) {
-            TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
-            typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
-            if (typeSystem == null) {
-                NodeData nodeData = new NodeData(context, templateType);
-                nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType));
-                return nodeData;
-            }
-        } else {
-            // default dummy type system
-            typeSystem = new TypeSystemData(context, templateType, null, NodeParser.class.getAnnotation(DSLOptions.class), true);
-        }
-        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
-        String shortName = null;
-        if (nodeInfoMirror != null) {
-            shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
-        }
-        boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null;
-        return new NodeData(context, templateType, shortName, typeSystem, useNodeFactory);
-
-    }
-
-    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
-        Set<String> names = new HashSet<>();
-
-        List<NodeFieldData> fields = new ArrayList<>();
-        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
-            if (field.getModifiers().contains(Modifier.STATIC)) {
-                continue;
-            }
-            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
-                String name = field.getSimpleName().toString();
-                fields.add(new NodeFieldData(field, null, field, false));
-                names.add(name);
-            }
-        }
-
-        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
-        Collections.reverse(reversedTypeHierarchy);
-        for (TypeElement typeElement : reversedTypeHierarchy) {
-            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
-            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
-
-            for (AnnotationMirror mirror : children) {
-                String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name"));
-                TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type");
-
-                NodeFieldData field = new NodeFieldData(typeElement, mirror, new CodeVariableElement(type, name), true);
-                if (name.isEmpty()) {
-                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
-                } else if (names.contains(name)) {
-                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
-                }
-                names.add(name);
-
-                fields.add(field);
-            }
-        }
-
-        for (NodeFieldData nodeFieldData : fields) {
-            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
-        }
-
-        return fields;
-    }
-
-    private List<NodeChildData> parseChildren(final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
-        Set<String> shortCircuits = new HashSet<>();
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
-            if (mirror != null) {
-                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
-            if (mirror != null) {
-                List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
-                if (children != null) {
-                    for (String child : children) {
-                        castNodeTypes.put(child, method.getReturnType());
-                    }
-                }
-            }
-        }
-
-        List<NodeChildData> parsedChildren = new ArrayList<>();
-        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
-        Collections.reverse(typeHierarchyReversed);
-        for (TypeElement type : typeHierarchyReversed) {
-            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
-
-            TypeMirror nodeClassType = type.getSuperclass();
-            if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
-                nodeClassType = null;
-            }
-
-            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
-            int index = 0;
-            for (AnnotationMirror childMirror : children) {
-                String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
-                if (name.equals("")) {
-                    name = "child" + index;
-                }
-
-                Cardinality cardinality = Cardinality.ONE;
-
-                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
-                if (childType.getKind() == TypeKind.ARRAY) {
-                    cardinality = Cardinality.MANY;
-                }
-
-                TypeMirror originalChildType = childType;
-                TypeMirror castNodeType = castNodeTypes.get(name);
-                if (castNodeType != null) {
-                    childType = castNodeType;
-                }
-
-                Element getter = findGetter(elements, name, childType);
-                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
-
-                parsedChildren.add(nodeChild);
-
-                if (nodeChild.getNodeType() == null) {
-                    nodeChild.addError("No valid node type could be resoleved.");
-                }
-                if (nodeChild.hasErrors()) {
-                    continue;
-                }
-
-                index++;
-            }
-        }
-
-        List<NodeChildData> filteredChildren = new ArrayList<>();
-        Set<String> encounteredNames = new HashSet<>();
-        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
-            NodeChildData child = parsedChildren.get(i);
-            if (!encounteredNames.contains(child.getName())) {
-                filteredChildren.add(0, child);
-                encounteredNames.add(child.getName());
-            }
-        }
-
-        return filteredChildren;
-    }
-
-    private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
-        // pre-parse short circuits
-        Set<String> shortCircuits = new HashSet<>();
-        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
-            if (mirror != null) {
-                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
-            }
-        }
-
-        boolean hasVarArgs = false;
-        int maxSignatureSize = 0;
-        if (!children.isEmpty()) {
-            int lastIndex = children.size() - 1;
-            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
-            if (hasVarArgs) {
-                maxSignatureSize = lastIndex;
-            } else {
-                maxSignatureSize = children.size();
-            }
-        }
-
-        List<NodeFieldData> nonGetterFields = new ArrayList<>();
-        for (NodeFieldData field : fields) {
-            if (field.getGetter() == null && field.isGenerated()) {
-                nonGetterFields.add(field);
-            }
-        }
-
-        TypeMirror cacheAnnotation = context.getType(Cached.class);
-        List<TypeMirror> frameTypes = context.getFrameTypes();
-        // pre-parse specializations to find signature size
-        for (ExecutableElement method : methods) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
-            if (mirror == null) {
-                continue;
-            }
-            int currentArgumentIndex = 0;
-            boolean skipShortCircuit = false;
-            parameter: for (VariableElement var : method.getParameters()) {
-                if (skipShortCircuit) {
-                    skipShortCircuit = false;
-                    continue parameter;
-                }
-
-                TypeMirror type = var.asType();
-                if (currentArgumentIndex == 0) {
-                    // skip optionals
-                    for (TypeMirror frameType : frameTypes) {
-                        if (ElementUtils.typeEquals(type, frameType)) {
-                            continue parameter;
-                        }
-                    }
-                }
-
-                if (currentArgumentIndex < nonGetterFields.size()) {
-                    for (NodeFieldData field : nonGetterFields) {
-                        if (ElementUtils.typeEquals(var.asType(), field.getType())) {
-                            continue parameter;
-                        }
-                    }
-                }
-
-                if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
-                    continue parameter;
-                }
-
-                int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1;
-                if (childIndex != -1) {
-                    NodeChildData child = children.get(childIndex);
-                    if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) {
-                        skipShortCircuit = true;
-                    }
-                }
-
-                currentArgumentIndex++;
-            }
-            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex);
-        }
-
-        List<NodeExecutionData> executions = new ArrayList<>();
-        for (int i = 0; i < maxSignatureSize; i++) {
-            boolean varArgParameter = false;
-            int childIndex = i;
-            if (i >= children.size() - 1) {
-                if (hasVarArgs) {
-                    varArgParameter = hasVarArgs;
-                    childIndex = Math.min(i, children.size() - 1);
-                } else if (i >= children.size()) {
-                    childIndex = -1;
-                }
-            }
-            int varArgsIndex = -1;
-            boolean shortCircuit = false;
-            NodeChildData child = null;
-            if (childIndex != -1) {
-                varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
-                child = children.get(childIndex);
-                shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex));
-            }
-            executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit));
-        }
-        return executions;
-    }
-
-    private List<ExecutableTypeData> parseExecutableTypeData(NodeData node, List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes, boolean includeFinals) {
-        List<ExecutableTypeData> typeData = new ArrayList<>();
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            Set<Modifier> modifiers = method.getModifiers();
-            if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) {
-                continue;
-            }
-            if (!includeFinals && modifiers.contains(Modifier.FINAL)) {
-                continue;
-            }
-
-            if (!method.getSimpleName().toString().startsWith("execute")) {
-                continue;
-            }
-            if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) {
-                continue;
-            }
-
-            ExecutableTypeData executableType = new ExecutableTypeData(node, method, signatureSize, context.getFrameTypes());
-
-            if (executableType.getFrameParameter() != null) {
-                boolean supportedType = false;
-                for (TypeMirror type : frameTypes) {
-                    if (ElementUtils.isAssignable(type, executableType.getFrameParameter())) {
-                        supportedType = true;
-                        break;
-                    }
-                }
-                if (!supportedType) {
-                    continue;
-                }
-            }
-
-            typeData.add(executableType);
-        }
-
-        namesUnique(typeData);
-
-        return typeData;
-    }
-
-    private static void namesUnique(List<ExecutableTypeData> typeData) {
-        List<String> names = new ArrayList<>();
-        for (ExecutableTypeData type : typeData) {
-            names.add(type.getUniqueName());
-        }
-        while (renameDuplicateIds(names)) {
-            // fix point
-        }
-
-        for (int i = 0; i < typeData.size(); i++) {
-            typeData.get(i).setUniqueName(names.get(i));
-        }
-    }
-
-    private void initializeExecutableTypes(NodeData node) {
-        List<ExecutableTypeData> allExecutes = node.getExecutableTypes();
-
-        Set<String> inconsistentFrameTypes = new HashSet<>();
-        TypeMirror frameType = null;
-        for (ExecutableTypeData execute : allExecutes) {
-
-            TypeMirror frame = execute.getFrameParameter();
-            TypeMirror resolvedFrameType;
-            if (frame != null) {
-                resolvedFrameType = frame;
-                if (frameType == null) {
-                    frameType = resolvedFrameType;
-                } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
-                    // found inconsistent frame types
-                    inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType));
-                    inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType));
-                }
-            }
-        }
-        if (!inconsistentFrameTypes.isEmpty()) {
-            // ensure they are sorted somehow
-            List<String> inconsistentFrameTypesList = new ArrayList<>(inconsistentFrameTypes);
-            Collections.sort(inconsistentFrameTypesList);
-            node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList);
-        }
-        if (frameType == null) {
-            frameType = context.getType(void.class);
-        }
-
-        node.setFrameType(frameType);
-
-        boolean genericFound = false;
-        for (ExecutableTypeData type : node.getExecutableTypes()) {
-            if (!type.hasUnexpectedValue(context)) {
-                genericFound = true;
-                break;
-            }
-        }
-
-        // no generic executes
-        if (!genericFound) {
-            node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the "
-                            + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions.");
-        }
-
-        int nodeChildDeclarations = 0;
-        int nodeChildDeclarationsRequired = 0;
-        List<NodeExecutionData> executions = node.getChildExecutions();
-        for (NodeExecutionData execution : executions) {
-            if (execution.getChild() == null) {
-                nodeChildDeclarationsRequired = execution.getIndex() + 1;
-            } else {
-                nodeChildDeclarations++;
-            }
-        }
-
-        List<String> requireNodeChildDeclarations = new ArrayList<>();
-        for (ExecutableTypeData type : allExecutes) {
-            if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) {
-                requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod()));
-            }
-        }
-
-        if (!requireNodeChildDeclarations.isEmpty()) {
-            node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
-                            + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations);
-        }
-
-        if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) {
-            for (NodeChildData child : node.getChildren()) {
-                child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.");
-            }
-        }
-
-    }
-
-    private void initializeChildren(NodeData node) {
-        initializeExecuteWith(node);
-
-        for (NodeChildData child : node.getChildren()) {
-            TypeMirror nodeType = child.getNodeType();
-            NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType));
-
-            child.setNode(fieldNodeData);
-            if (fieldNodeData == null || fieldNodeData.hasErrors()) {
-                child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType));
-            } else {
-                List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
-                if (types.isEmpty()) {
-                    AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
-                    child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(),
-                                    ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node)));
-                }
-            }
-        }
-    }
-
-    private static void initializeExecuteWith(NodeData node) {
-        for (NodeChildData child : node.getChildren()) {
-            List<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
-            AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
-            List<NodeExecutionData> executeWith = new ArrayList<>();
-            for (String executeWithString : executeWithStrings) {
-                if (child.getName().equals(executeWithString)) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
-                    continue;
-                }
-                NodeExecutionData found = null;
-                boolean before = true;
-                for (NodeExecutionData resolveChild : node.getChildExecutions()) {
-                    if (resolveChild.getChild() == child) {
-                        before = false;
-                        continue;
-                    }
-                    if (resolveChild.getIndexedName().equals(executeWithString)) {
-                        found = resolveChild;
-                        break;
-                    }
-                }
-
-                if (found == null) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
-                    continue;
-                } else if (!before) {
-                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
-                                    executeWithString);
-                    continue;
-                }
-                executeWith.add(found);
-            }
-            child.setExecuteWith(executeWith);
-        }
-    }
-
-    private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, TypeElement originalTemplateType) {
-        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
-
-        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
-            // generated nodes should not get called again.
-            return null;
-        }
-
-        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
-            return null;
-        }
-
-        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
-
-        // Declaration order is not required for child nodes.
-        List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType);
-        NodeData node = parseNodeData(templateType, lookupTypes);
-        if (node.hasErrors()) {
-            return node;
-        }
-        List<TypeMirror> frameTypes = Collections.emptyList();
-        if (parentNode.getFrameType() != null) {
-            frameTypes = Arrays.asList(parentNode.getFrameType());
-        }
-        node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, child.getExecuteWith().size(), frameTypes, true));
-        node.setFrameType(parentNode.getFrameType());
-        return node;
-    }
-
-    private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) {
-        List<TypeMirror> allowedFrameTypes = new ArrayList<>();
-        for (TypeMirror frameType : context.getFrameTypes()) {
-            if (ElementUtils.isAssignable(parentNode.getFrameType(), frameType)) {
-                allowedFrameTypes.add(frameType);
-            }
-        }
-        return allowedFrameTypes;
-    }
-
-    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
-        if (node.getSpecializations().isEmpty()) {
-            return;
-        }
-
-        initializeExpressions(elements, node);
-
-        if (node.hasErrors()) {
-            return;
-        }
-
-        initializeGeneric(node);
-        initializeUninitialized(node);
-        initializeOrder(node);
-        initializePolymorphism(node); // requires specializations
-        initializeReachability(node);
-        initializeContains(node);
-        resolveContains(node);
-
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (SpecializationData cur : specializations) {
-            for (SpecializationData contained : cur.getContains()) {
-                if (contained != cur) {
-                    contained.getExcludedBy().add(cur);
-                }
-            }
-        }
-
-        initializeSpecializationIdsWithMethodNames(node.getSpecializations());
-    }
-
-    private static void initializeOrder(NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        Collections.sort(specializations);
-
-        for (SpecializationData specialization : specializations) {
-            String searchName = specialization.getInsertBeforeName();
-            if (searchName == null || specialization.getMethod() == null) {
-                continue;
-            }
-            SpecializationData found = lookupSpecialization(node, searchName);
-            if (found == null || found.getMethod() == null) {
-                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
-                specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName);
-                continue;
-            }
-
-            ExecutableElement currentMethod = specialization.getMethod();
-            ExecutableElement insertBeforeMethod = found.getMethod();
-
-            TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType();
-            TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType();
-
-            if (ElementUtils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !ElementUtils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) {
-                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
-                specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName);
-                continue;
-            }
-
-            specialization.setInsertBefore(found);
-        }
-
-        for (int i = 0; i < specializations.size(); i++) {
-            SpecializationData specialization = specializations.get(i);
-            SpecializationData insertBefore = specialization.getInsertBefore();
-            if (insertBefore != null) {
-                int insertIndex = specializations.indexOf(insertBefore);
-                if (insertIndex < i) {
-                    specializations.remove(i);
-                    specializations.add(insertIndex, specialization);
-                }
-            }
-        }
-
-        for (int i = 0; i < specializations.size(); i++) {
-            specializations.get(i).setIndex(i);
-        }
-    }
-
-    private static void initializeContains(NodeData node) {
-        for (SpecializationData specialization : node.getSpecializations()) {
-            Set<SpecializationData> resolvedSpecializations = specialization.getContains();
-            resolvedSpecializations.clear();
-            Set<String> includeNames = specialization.getContainsNames();
-            for (String includeName : includeNames) {
-                // TODO reduce complexity of this lookup.
-                SpecializationData foundSpecialization = lookupSpecialization(node, includeName);
-
-                if (foundSpecialization == null) {
-                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                    specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName);
-                } else {
-                    if (foundSpecialization.compareTo(specialization) > 0) {
-                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                        if (foundSpecialization.compareTo(specialization) > 0) {
-                            specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
-                        }
-
-                    }
-                    resolvedSpecializations.add(foundSpecialization);
-                }
-            }
-        }
-    }
-
-    private void resolveContains(NodeData node) {
-        // flatten transitive includes
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.getContains().isEmpty()) {
-                continue;
-            }
-            Set<SpecializationData> foundSpecializations = new HashSet<>();
-            collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>());
-            specialization.getContains().addAll(foundSpecializations);
-        }
-    }
-
-    private static SpecializationData lookupSpecialization(NodeData node, String includeName) {
-        SpecializationData foundSpecialization = null;
-        for (SpecializationData searchSpecialization : node.getSpecializations()) {
-            if (searchSpecialization.getMethodName().equals(includeName)) {
-                foundSpecialization = searchSpecialization;
-                break;
-            }
-        }
-        return foundSpecialization;
-    }
-
-    private void collectIncludes(SpecializationData specialization, Set<SpecializationData> found, Set<SpecializationData> visited) {
-        if (visited.contains(specialization)) {
-            // circle found
-            specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName());
-            return;
-        }
-        visited.add(specialization);
-
-        for (SpecializationData included : specialization.getContains()) {
-            collectIncludes(included, found, new HashSet<>(visited));
-            found.add(included);
-        }
-    }
-
-    private static void initializeReachability(final NodeData node) {
-        List<SpecializationData> specializations = node.getSpecializations();
-        for (int i = specializations.size() - 1; i >= 0; i--) {
-            SpecializationData current = specializations.get(i);
-            if (current.isPolymorphic()) {
-                current.setReachable(true);
-                continue;
-            }
-
-            List<SpecializationData> shadowedBy = null;
-            for (int j = i - 1; j >= 0; j--) {
-                SpecializationData prev = specializations.get(j);
-                if (prev.isPolymorphic()) {
-                    continue;
-                }
-                if (!current.isReachableAfter(prev)) {
-                    if (shadowedBy == null) {
-                        shadowedBy = new ArrayList<>();
-                    }
-                    shadowedBy.add(prev);
-                }
-            }
-
-            if (shadowedBy != null) {
-                StringBuilder name = new StringBuilder();
-                String sep = "";
-                for (SpecializationData shadowSpecialization : shadowedBy) {
-                    name.append(sep);
-                    name.append(shadowSpecialization.createReferenceName());
-                    sep = ", ";
-                }
-                current.addError("%s is not reachable. It is shadowed by %s.", current.isFallback() ? "Generic" : "Specialization", name);
-            }
-            current.setReachable(shadowedBy == null);
-        }
-    }
-
-    private static void initializeSpecializationIdsWithMethodNames(List<SpecializationData> specializations) {
-        List<String> signatures = new ArrayList<>();
-        for (SpecializationData specialization : specializations) {
-            if (specialization.isFallback()) {
-                signatures.add("Fallback");
-            } else if (specialization.isUninitialized()) {
-                signatures.add("Uninitialized");
-            } else if (specialization.isPolymorphic()) {
-                signatures.add("Polymorphic");
-            } else {
-                String name = specialization.getMethodName();
-
-                // hack for name clashes with BaseNode.
-                if (name.equalsIgnoreCase("base")) {
-                    name = name + "0";
-                } else if (name.startsWith("do")) {
-                    String filteredDo = name.substring(2, name.length());
-                    if (!filteredDo.isEmpty() && Character.isJavaIdentifierStart(filteredDo.charAt(0))) {
-                        name = filteredDo;
-                    }
-                }
-                signatures.add(ElementUtils.firstLetterUpperCase(name));
-            }
-        }
-
-        while (renameDuplicateIds(signatures)) {
-            // fix point
-        }
-
-        for (int i = 0; i < specializations.size(); i++) {
-            specializations.get(i).setId(signatures.get(i));
-        }
-    }
-
-    private static boolean renameDuplicateIds(List<String> signatures) {
-        boolean changed = false;
-        Map<String, Integer> counts = new HashMap<>();
-        for (String s1 : signatures) {
-            Integer count = counts.get(s1.toLowerCase());
-            if (count == null) {
-                count = 0;
-            }
-            count++;
-            counts.put(s1.toLowerCase(), count);
-        }
-
-        for (String s : counts.keySet()) {
-            int count = counts.get(s);
-            if (count > 1) {
-                changed = true;
-                int number = 0;
-                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
-                    String s2 = iterator.next();
-                    if (s.equalsIgnoreCase(s2)) {
-                        iterator.set(s2 + number);
-                        number++;
-                    }
-                }
-            }
-        }
-        return changed;
-    }
-
-    private void initializeExpressions(List<? extends Element> elements, NodeData node) {
-        List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements);
-
-        List<VariableElement> fields = new ArrayList<>();
-        for (NodeFieldData field : node.getFields()) {
-            fields.add(field.getVariable());
-        }
-
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.getMethod() == null) {
-                continue;
-            }
-
-            List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size());
-            for (Parameter p : specialization.getParameters()) {
-                specializationMembers.add(p.getVariableElement());
-            }
-            specializationMembers.addAll(fields);
-            specializationMembers.addAll(members);
-            DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers);
-
-            initializeCaches(specialization, resolver);
-            initializeGuards(specialization, resolver);
-            if (specialization.hasErrors()) {
-                continue;
-            }
-            initializeLimit(specialization, resolver);
-            initializeAssumptions(specialization, resolver);
-        }
-    }
-
-    private void initializeAssumptions(SpecializationData specialization, DSLExpressionResolver resolver) {
-        final DeclaredType assumptionType = context.getDeclaredType(Assumption.class);
-        final TypeMirror assumptionArrayType = new ArrayCodeTypeMirror(assumptionType);
-        final List<String> assumptionDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
-        List<AssumptionExpression> assumptionExpressions = new ArrayList<>();
-        int assumptionId = 0;
-        for (String assumption : assumptionDefinitions) {
-            AssumptionExpression assumptionExpression;
-            DSLExpression expression = null;
-            try {
-                expression = DSLExpression.parse(assumption);
-                expression.accept(resolver);
-                assumptionExpression = new AssumptionExpression(specialization, expression, "assumption" + assumptionId);
-                if (!ElementUtils.isAssignable(expression.getResolvedType(), assumptionType) && !ElementUtils.isAssignable(expression.getResolvedType(), assumptionArrayType)) {
-                    assumptionExpression.addError("Incompatible return type %s. Assumptions must be assignable to %s or %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
-                                    ElementUtils.getSimpleName(assumptionType), ElementUtils.getSimpleName(assumptionArrayType));
-                }
-                if (specialization.isDynamicParameterBound(expression)) {
-                    specialization.addError("Assumption expressions must not bind dynamic parameter values.");
-                }
-            } catch (InvalidExpressionException e) {
-                assumptionExpression = new AssumptionExpression(specialization, null, "assumption" + assumptionId);
-                assumptionExpression.addError("Error parsing expression '%s': %s", assumption, e.getMessage());
-            }
-            assumptionExpressions.add(assumptionExpression);
-        }
-        specialization.setAssumptionExpressions(assumptionExpressions);
-    }
-
-    private void initializeLimit(SpecializationData specialization, DSLExpressionResolver resolver) {
-        AnnotationValue annotationValue = ElementUtils.getAnnotationValue(specialization.getMessageAnnotation(), "limit");
-
-        String limitValue;
-        if (annotationValue == null) {
-            limitValue = "";
-        } else {
-            limitValue = (String) annotationValue.getValue();
-        }
-        if (limitValue.isEmpty()) {
-            limitValue = "3";
-        } else if (!specialization.hasMultipleInstances()) {
-            specialization.addWarning(annotationValue, "The limit expression has no effect. Multiple specialization instantiations are impossible for this specialization.");
-            return;
-        }
-
-        TypeMirror expectedType = context.getType(int.class);
-        try {
-            DSLExpression expression = DSLExpression.parse(limitValue);
-            expression.accept(resolver);
-            if (!ElementUtils.typeEquals(expression.getResolvedType(), expectedType)) {
-                specialization.addError(annotationValue, "Incompatible return type %s. Limit expressions must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
-                                ElementUtils.getSimpleName(expectedType));
-            }
-            if (specialization.isDynamicParameterBound(expression)) {
-                specialization.addError(annotationValue, "Limit expressions must not bind dynamic parameter values.");
-            }
-
-            specialization.setLimitExpression(expression);
-        } catch (InvalidExpressionException e) {
-            specialization.addError(annotationValue, "Error parsing expression '%s': %s", limitValue, e.getMessage());
-        }
-    }
-
-    private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) {
-        TypeMirror cacheMirror = context.getType(Cached.class);
-        List<CacheExpression> expressions = new ArrayList<>();
-        for (Parameter parameter : specialization.getParameters()) {
-            AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror);
-            if (annotationMirror != null) {
-                String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value");
-
-                TypeMirror parameterType = parameter.getType();
-
-                DSLExpressionResolver localResolver = resolver;
-                if (parameterType.getKind() == TypeKind.DECLARED) {
-                    localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true));
-                }
-
-                CacheExpression cacheExpression;
-                DSLExpression expression = null;
-                try {
-                    expression = DSLExpression.parse(initializer);
-                    expression.accept(localResolver);
-                    cacheExpression = new CacheExpression(parameter, annotationMirror, expression);
-                    if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) {
-                        cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
-                                        ElementUtils.getSimpleName(parameter.getType()));
-                    }
-                } catch (InvalidExpressionException e) {
-                    cacheExpression = new CacheExpression(parameter, annotationMirror, null);
-                    cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage());
-                }
-                expressions.add(cacheExpression);
-            }
-        }
-        specialization.setCaches(expressions);
-
-        if (specialization.hasErrors()) {
-            return;
-        }
-
-        // verify that cache expressions are bound in the correct order.
-        for (int i = 0; i < expressions.size(); i++) {
-            CacheExpression currentExpression = expressions.get(i);
-            Set<VariableElement> boundVariables = currentExpression.getExpression().findBoundVariableElements();
-            for (int j = i + 1; j < expressions.size(); j++) {
-                CacheExpression boundExpression = expressions.get(j);
-                if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) {
-                    currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.",
-                                    currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName());
-                    break;
-                }
-            }
-        }
-    }
-
-    private void initializeGuards(SpecializationData specialization, DSLExpressionResolver resolver) {
-        final TypeMirror booleanType = context.getType(boolean.class);
-        List<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
-        List<GuardExpression> guardExpressions = new ArrayList<>();
-        for (String guard : guardDefinitions) {
-            GuardExpression guardExpression;
-            DSLExpression expression = null;
-            try {
-                expression = DSLExpression.parse(guard);
-                expression.accept(resolver);
-                guardExpression = new GuardExpression(specialization, expression);
-                if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) {
-                    guardExpression.addError("Incompatible return type %s. Guards must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(booleanType));
-                }
-            } catch (InvalidExpressionException e) {
-                guardExpression = new GuardExpression(specialization, null);
-                guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage());
-            }
-            guardExpressions.add(guardExpression);
-        }
-        specialization.setGuards(guardExpressions);
-    }
-
-    private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) {
-        String packageName = ElementUtils.getPackageName(templateType);
-        List<Element> filteredElements = new ArrayList<>(elements);
-        for (Element element : elements) {
-            Modifier visibility = ElementUtils.getVisibility(element.getModifiers());
-            if (visibility == Modifier.PRIVATE) {
-                continue;
-            } else if (visibility == null) {
-                String elementPackageName = ElementUtils.getPackageName(element.getEnclosingElement().asType());
-                if (!Objects.equals(packageName, elementPackageName) && !elementPackageName.equals("java.lang")) {
-                    continue;
-                }
-            }
-
-            filteredElements.add(element);
-        }
-        return filteredElements;
-    }
-
-    private void initializeGeneric(final NodeData node) {
-        List<SpecializationData> generics = new ArrayList<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            if (spec.isFallback()) {
-                generics.add(spec);
-            }
-        }
-
-        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
-            // TODO this limitation should be lifted
-            for (SpecializationData generic : generics) {
-                generic.addError("@%s defined but no @%s.", Fallback.class.getSimpleName(), Specialization.class.getSimpleName());
-            }
-        }
-
-        if (generics.isEmpty()) {
-            node.getSpecializations().add(createGenericSpecialization(node));
-        } else {
-            if (generics.size() > 1) {
-                for (SpecializationData generic : generics) {
-                    generic.addError("Only one @%s is allowed per operation.", Fallback.class.getSimpleName());
-                }
-            }
-        }
-    }
-
-    private SpecializationData createGenericSpecialization(final NodeData node) {
-        FallbackParser parser = new FallbackParser(context, node);
-        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
-
-        List<VariableElement> parameterTypes = new ArrayList<>();
-        int signatureIndex = 1;
-        for (ParameterSpec spec : specification.getRequired()) {
-            parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex));
-            if (spec.isSignature()) {
-                signatureIndex++;
-            }
-        }
-
-        TypeMirror returnType = createGenericType(node, specification.getReturnType());
-        SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
-        if (generic == null) {
-            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
-        }
-
-        return generic;
-    }
-
-    private TypeMirror createGenericType(NodeData node, ParameterSpec spec) {
-        NodeExecutionData execution = spec.getExecution();
-        Collection<TypeMirror> allowedTypes;
-        if (execution == null) {
-            allowedTypes = spec.getAllowedTypes();
-        } else {
-            allowedTypes = Arrays.asList(node.getGenericType(execution));
-        }
-        if (allowedTypes.size() == 1) {
-            return allowedTypes.iterator().next();
-        } else {
-            return ElementUtils.getCommonSuperType(context, allowedTypes);
-        }
-    }
-
-    private static void initializeUninitialized(final NodeData node) {
-        SpecializationData generic = node.getGenericSpecialization();
-        if (generic == null) {
-            return;
-        }
-        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
-        // should not use messages from generic specialization
-        uninializedMethod.getMessages().clear();
-        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
-    }
-
-    private void initializePolymorphism(NodeData node) {
-        if (!node.needsRewrites(context)) {
-            return;
-        }
-
-        SpecializationData generic = node.getGenericSpecialization();
-        List<VariableElement> types = new ArrayList<>();
-
-        Collection<TypeMirror> frameTypes = new HashSet<>();
-        for (SpecializationData specialization : node.getSpecializations()) {
-            if (specialization.getFrame() != null) {
-                frameTypes.add(specialization.getFrame().getType());
-            }
-        }
-        if (node.supportsFrame()) {
-            frameTypes.add(node.getFrameType());
-        }
-
-        if (!frameTypes.isEmpty()) {
-            frameTypes = ElementUtils.uniqueSortedTypes(frameTypes, false);
-            TypeMirror frameType;
-            if (frameTypes.size() == 1) {
-                frameType = frameTypes.iterator().next();
-            } else {
-                frameType = context.getType(Frame.class);
-            }
-            types.add(new CodeVariableElement(frameType, TemplateMethod.FRAME_NAME));
-        }
-
-        TypeMirror returnType = null;
-        int index = 0;
-        for (Parameter genericParameter : generic.getReturnTypeAndParameters()) {
-            TypeMirror polymorphicType;
-            if (genericParameter.getLocalName().equals(TemplateMethod.FRAME_NAME)) {
-                continue;
-            }
-            boolean isReturnParameter = genericParameter == generic.getReturnType();
-            if (!genericParameter.getSpecification().isSignature()) {
-                polymorphicType = genericParameter.getType();
-            } else {
-                Collection<TypeMirror> usedTypes = new HashSet<>();
-                for (SpecializationData specialization : node.getSpecializations()) {
-                    if (specialization.isUninitialized()) {
-                        continue;
-                    }
-                    Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
-                    if (parameter == specialization.getReturnType() && specialization.isFallback() && specialization.getMethod() == null) {
-                        continue;
-                    }
-                    if (parameter == null) {
-                        throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
-                    }
-                    usedTypes.add(parameter.getType());
-                }
-                usedTypes = ElementUtils.uniqueSortedTypes(usedTypes, false);
-
-                if (usedTypes.size() == 1) {
-                    polymorphicType = usedTypes.iterator().next();
-                } else {
-                    polymorphicType = ElementUtils.getCommonSuperType(context, usedTypes);
-                }
-
-                NodeExecutionData execution = genericParameter.getSpecification().getExecution();
-                if (execution != null && !ElementUtils.isSubtypeBoxed(context, polymorphicType, node.getGenericType(execution))) {
-                    throw new AssertionError(String.format("Polymorphic types %s not compatible to generic type %s.", polymorphicType, node.getGenericType(execution)));
-                }
-
-            }
-            if (isReturnParameter) {
-                returnType = polymorphicType;
-            } else {
-                types.add(new CodeVariableElement(polymorphicType, "param" + index));
-            }
-            index++;
-        }
-
-        SpecializationMethodParser parser = new SpecializationMethodParser(context, node);
-        SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types);
-        if (polymorphic == null) {
-            throw new AssertionError("Failed to parse polymorphic signature. " + parser.createDefaultMethodSpec(null, null, false, null) + " Types: " + returnType + " - " + types);
-        }
-
-        polymorphic.setKind(SpecializationKind.POLYMORPHIC);
-        node.getSpecializations().add(polymorphic);
-    }
-
-    private void initializeShortCircuits(NodeData node) {
-        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
-
-        boolean valid = true;
-        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (!execution.isShortCircuit()) {
-                continue;
-            }
-            shortCircuitExecutions.add(execution);
-            String valueName = execution.getIndexedName();
-            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
-
-            if (availableCircuits == null || availableCircuits.isEmpty()) {
-                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            boolean sameMethodName = true;
-            String methodName = availableCircuits.get(0).getMethodName();
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (!circuit.getMethodName().equals(methodName)) {
-                    sameMethodName = false;
-                }
-            }
-
-            if (!sameMethodName) {
-                for (ShortCircuitData circuit : availableCircuits) {
-                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
-                }
-                valid = false;
-                continue;
-            }
-
-            ShortCircuitData genericCircuit = null;
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (isGenericShortCutMethod(circuit)) {
-                    genericCircuit = circuit;
-                    break;
-                }
-            }
-
-            if (genericCircuit == null) {
-                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
-                valid = false;
-                continue;
-            }
-
-            for (ShortCircuitData circuit : availableCircuits) {
-                if (circuit != genericCircuit) {
-                    circuit.setGenericShortCircuitMethod(genericCircuit);
-                }
-            }
-        }
-
-        if (!valid) {
-            return;
-        }
-
-        List<SpecializationData> specializations = new ArrayList<>();
-        specializations.addAll(node.getSpecializations());
-        for (SpecializationData specialization : specializations) {
-            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
-
-            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
-                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getIndexedName());
-
-                ShortCircuitData genericShortCircuit = null;
-                ShortCircuitData compatibleShortCircuit = null;
-                for (ShortCircuitData circuit : availableShortCuts) {
-                    if (circuit.isGeneric()) {
-                        genericShortCircuit = circuit;
-                    } else if (circuit.isCompatibleTo(specialization)) {
-                        compatibleShortCircuit = circuit;
-                    }
-                }
-
-                if (compatibleShortCircuit == null) {
-                    compatibleShortCircuit = genericShortCircuit;
-                }
-                assignedShortCuts.add(compatibleShortCircuit);
-            }
-            specialization.setShortCircuits(assignedShortCuts);
-        }
-    }
-
-    private boolean isGenericShortCutMethod(ShortCircuitData method) {
-        for (Parameter parameter : method.getParameters()) {
-            NodeExecutionData execution = parameter.getSpecification().getExecution();
-            if (execution == null) {
-                continue;
-            }
-            ExecutableTypeData found = null;
-            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
-            for (ExecutableTypeData executable : executableElements) {
-                if (ElementUtils.typeEquals(executable.getReturnType(), parameter.getType())) {
-                    found = executable;
-                    break;
-                }
-            }
-            if (found == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
-        Map<String, List<ShortCircuitData>> group = new HashMap<>();
-        for (ShortCircuitData shortCircuit : shortCircuits) {
-            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
-            if (circuits == null) {
-                circuits = new ArrayList<>();
-                group.put(shortCircuit.getValueName(), circuits);
-            }
-            circuits.add(shortCircuit);
-        }
-        return group;
-    }
-
-    private static boolean verifySpecializationSameLength(NodeData nodeData) {
-        int lastArgs = -1;
-        for (SpecializationData specializationData : nodeData.getSpecializations()) {
-            int signatureArgs = specializationData.getSignatureSize();
-            if (lastArgs == signatureArgs) {
-                continue;
-            }
-            if (lastArgs != -1) {
-                for (SpecializationData specialization : nodeData.getSpecializations()) {
-                    specialization.addError("All specializations must have the same number of arguments.");
-                }
-                return false;
-            } else {
-                lastArgs = signatureArgs;
-            }
-        }
-        return true;
-    }
-
-    private static void verifyVisibilities(NodeData node) {
-        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
-            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
-        }
-    }
-
-    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
-        if (!nodeData.needsFactory()) {
-            // missing abstract methods only needs to be implemented
-            // if we need go generate factory for it.
-            return;
-        }
-
-        List<Element> elements = new ArrayList<>(originalElements);
-        Set<Element> unusedElements = new HashSet<>(elements);
-        for (ExecutableElement method : nodeData.getAllTemplateMethods()) {
-            unusedElements.remove(method);
-        }
-
-        for (NodeFieldData field : nodeData.getFields()) {
-            if (field.getGetter() != null) {
-                unusedElements.remove(field.getGetter());
-            }
-        }
-
-        for (NodeChildData child : nodeData.getChildren()) {
-            if (child.getAccessElement() != null) {
-                unusedElements.remove(child.getAccessElement());
-            }
-        }
-
-        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
-            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
-                nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()),
-                                ElementUtils.getReadableSignature(unusedMethod));
-            }
-        }
-    }
-
-    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
-        for (int i = 0; i < methods.size(); i++) {
-            TemplateMethod m1 = methods.get(i);
-            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
-                m1.addError("Naming convention: method name must start with '%s'.", prefix);
-            }
-        }
-    }
-
-    private static void verifySpecializationThrows(NodeData node) {
-        Map<String, SpecializationData> specializationMap = new HashMap<>();
-        for (SpecializationData spec : node.getSpecializations()) {
-            specializationMap.put(spec.getMethodName(), spec);
-        }
-        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
-            if (sourceSpecialization.getExceptions() != null) {
-                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
-                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
-                        if (otherThrowsData != throwsData && ElementUtils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
-                            throwsData.addError("Duplicate exception type.");
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private static void verifyConstructors(NodeData nodeData) {
-        List<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeData.getTemplateType().getEnclosedElements());
-        if (constructors.isEmpty()) {
-            return;
-        }
-
-        boolean oneNonPrivate = false;
-        for (ExecutableElement constructor : constructors) {
-            if (ElementUtils.getVisibility(constructor.getModifiers()) != Modifier.PRIVATE) {
-                oneNonPrivate = true;
-                break;
-            }
-        }
-        if (!oneNonPrivate && !nodeData.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
-            nodeData.addError("At least one constructor must be non-private.");
-        }
-    }
-
-    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
-        for (Element element : elements) {
-            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, element, annotation);
-            if (mirror != null) {
-                return mirror;
-            }
-        }
-        return null;
-    }
-
-    private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
-        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
-        TypeMirror value = ElementUtils.getAnnotationValue(TypeMirror.class, annotation, valueName);
-        if (ElementUtils.typeEquals(inhertNodeType, value)) {
-            return parentType;
-        } else {
-            return value;
-        }
-    }
-
-    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
-        if (type == null) {
-            return null;
-        }
-        String methodName;
-        if (ElementUtils.typeEquals(type, context.getType(boolean.class))) {
-            methodName = "is" + ElementUtils.firstLetterUpperCase(variableName);
-        } else {
-            methodName = "get" + ElementUtils.firstLetterUpperCase(variableName);
-        }
-
-        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
-            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && ElementUtils.isAssignable(type, method.getReturnType())) {
-                return method;
-            }
-        }
-        return null;
-    }
-
-    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
-        if (element != null) {
-            collection.add(element);
-            if (element.getSuperclass() != null) {
-                collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass()));
-            }
-        }
-        return collection;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
-
-    private final Set<String> shortCircuitValues;
-
-    public ShortCircuitParser(ProcessorContext context, NodeData node) {
-        super(context, node);
-
-        shortCircuitValues = new HashSet<>();
-        for (NodeExecutionData execution : node.getChildExecutions()) {
-            if (execution.isShortCircuit()) {
-                shortCircuitValues.add(execution.getIndexedName());
-            }
-        }
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, mirror, "value");
-
-        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
-    }
-
-    @Override
-    protected ParameterSpec createReturnParameterSpec() {
-        return new ParameterSpec("has", getContext().getType(boolean.class));
-    }
-
-    @Override
-    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
-        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
-
-        if (!shortCircuitValues.contains(shortCircuitValue)) {
-            method.addError("Invalid short circuit value %s.", shortCircuitValue);
-        }
-
-        return new ShortCircuitData(method, shortCircuitValue);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return ShortCircuit.class;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.util.*;
-
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
-
-/**
- * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
- * and generic execute methods.
- */
-public final class SpecializationGroup {
-
-    private final List<TypeGuard> typeGuards;
-    private final List<GuardExpression> guards;
-
-    private final NodeData node;
-    private final SpecializationData specialization;
-    private final List<SpecializationGroup> children = new ArrayList<>();
-
-    private SpecializationGroup parent;
-
-    private SpecializationGroup(SpecializationData data) {
-        this.node = data.getNode();
-        this.typeGuards = new ArrayList<>();
-        this.guards = new ArrayList<>();
-        this.specialization = data;
-
-        TypeSignature sig = data.getTypeSignature();
-        for (int i = 1; i < sig.size(); i++) {
-            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
-        }
-        this.guards.addAll(data.getGuards());
-    }
-
-    public SpecializationGroup(List<SpecializationGroup> children, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
-        assert !children.isEmpty() : "children must not be empty";
-        this.typeGuards = typeGuardsMatches;
-        this.guards = guardMatches;
-        this.node = children.get(0).node;
-        this.specialization = null;
-        updateChildren(children);
-    }
-
-    public List<TypeGuard> getAllGuards() {
-        List<TypeGuard> collectedGuards = new ArrayList<>();
-        collectedGuards.addAll(typeGuards);
-        if (parent != null) {
-            collectedGuards.addAll(parent.getAllGuards());
-        }
-        return collectedGuards;
-    }
-
-    public List<GuardExpression> findElseConnectableGuards() {
-        if (!getTypeGuards().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        if (getGuards().isEmpty()) {
-            return Collections.emptyList();
-        }
-
-        List<GuardExpression> elseConnectableGuards = new ArrayList<>();
-        int guardIndex = 0;
-        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
-            elseConnectableGuards.add(getGuards().get(guardIndex));
-            guardIndex++;
-        }
-
-        return elseConnectableGuards;
-    }
-
-    private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
-        SpecializationGroup previous = this.getPreviousGroup();
-        if (previous == null) {
-            return null;
-        }
-        List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
-
-        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
-            return null;
-        }
-
-        /* Guard is else branch can be connected in previous specialization. */
-        if (elseConnectedGuards.contains(guard)) {
-            return guard;
-        }
-
-        GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
-        if (guard.equalsNegated(previousGuard)) {
-            return guard;
-        }
-        return null;
-    }
-
-    private void updateChildren(List<SpecializationGroup> childs) {
-        if (!children.isEmpty()) {
-            children.clear();
-        }
-        this.children.addAll(childs);
-        for (SpecializationGroup child : childs) {
-            child.parent = this;
-        }
-    }
-
-    public SpecializationGroup getParent() {
-        return parent;
-    }
-
-    public List<TypeGuard> getTypeGuards() {
-        return typeGuards;
-    }
-
-    public List<GuardExpression> getGuards() {
-        return guards;
-    }
-
-    public List<SpecializationGroup> getChildren() {
-        return children;
-    }
-
-    public SpecializationData getSpecialization() {
-        return specialization;
-    }
-
-    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
-        if (groups.isEmpty()) {
-            throw new IllegalArgumentException("empty combinations");
-        }
-        if (groups.size() == 1) {
-            return null;
-        }
-
-        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
-        List<GuardExpression> guardMatches = new ArrayList<>();
-
-        SpecializationGroup first = groups.get(0);
-        List<SpecializationGroup> others = groups.subList(1, groups.size());
-
-        outer: for (TypeGuard typeGuard : first.typeGuards) {
-            for (SpecializationGroup other : others) {
-                if (!other.typeGuards.contains(typeGuard)) {
-                    // type guards can be combined unordered
-                    continue outer;
-                }
-            }
-            typeGuardsMatches.add(typeGuard);
-        }
-
-        outer: for (GuardExpression guard : first.guards) {
-            for (SpecializationGroup other : others) {
-                if (!other.guards.contains(guard)) {
-                    // we must break here. One guard may depend on the other.
-                    break outer;
-                }
-            }
-            guardMatches.add(guard);
-        }
-
-        // check for guards for required type casts
-        for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
-            GuardExpression guardMatch = iterator.next();
-            if (!guardMatch.getExpression().findBoundVariables().isEmpty()) {
-                iterator.remove();
-            }
-            // TODO we need to be smarter here with bound parameters.
-        }
-
-        if (typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
-            return null;
-        }
-
-        for (SpecializationGroup group : groups) {
-            group.typeGuards.removeAll(typeGuardsMatches);
-            group.guards.removeAll(guardMatches);
-        }
-
-        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
-        return new SpecializationGroup(newChildren, typeGuardsMatches, guardMatches);
-    }
-
-    public static SpecializationGroup create(SpecializationData specialization) {
-        return new SpecializationGroup(specialization);
-    }
-
-    public static SpecializationGroup create(List<SpecializationData> specializations) {
-        List<SpecializationGroup> groups = new ArrayList<>();
-        for (SpecializationData specialization : specializations) {
-            groups.add(new SpecializationGroup(specialization));
-        }
-        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
-    }
-
-    @Override
-    public String toString() {
-        return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]";
-    }
-
-    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
-        if (groups.size() <= 1) {
-            return groups;
-        }
-        List<SpecializationGroup> newGroups = new ArrayList<>();
-
-        int i = 0;
-        for (i = 0; i < groups.size();) {
-            SpecializationGroup combined = null;
-            for (int j = groups.size(); j > i + 1; j--) {
-                combined = combine(groups.subList(i, j));
-                if (combined != null) {
-                    break;
-                }
-            }
-            SpecializationGroup newGroup;
-            if (combined == null) {
-                newGroup = groups.get(i);
-                i++;
-            } else {
-                newGroup = combined;
-                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
-                combined.updateChildren(createCombinationalGroups(originalGroups));
-                i += originalGroups.size();
-            }
-
-            newGroups.add(newGroup);
-
-        }
-
-        return newGroups;
-    }
-
-    public SpecializationGroup getPreviousGroup() {
-        if (parent == null || parent.children.isEmpty()) {
-            return null;
-        }
-        int index = parent.children.indexOf(this);
-        if (index <= 0) {
-            return null;
-        }
-        return parent.children.get(index - 1);
-    }
-
-    public int getUncheckedSpecializationIndex() {
-        int groupMaxIndex = getMaxSpecializationIndex();
-
-        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
-        if (groupMaxIndex >= genericIndex) {
-            // no minimum state check for an generic index
-            groupMaxIndex = -1;
-        }
-
-        if (groupMaxIndex > -1) {
-            // no minimum state check if already checked by parent group
-            int parentMaxIndex = -1;
-            if (getParent() != null) {
-                parentMaxIndex = getParent().getMaxSpecializationIndex();
-            }
-            if (groupMaxIndex == parentMaxIndex) {
-                groupMaxIndex = -1;
-            }
-        }
-        return groupMaxIndex;
-    }
-
-    public int getMaxSpecializationIndex() {
-        if (specialization != null) {
-            return specialization.getNode().getSpecializations().indexOf(specialization);
-        } else {
-            int max = Integer.MIN_VALUE;
-            for (SpecializationGroup childGroup : getChildren()) {
-                max = Math.max(max, childGroup.getMaxSpecializationIndex());
-            }
-            return max;
-        }
-    }
-
-    public static final class TypeGuard {
-
-        private final int signatureIndex;
-        private final TypeMirror type;
-
-        public TypeGuard(TypeMirror type, int signatureIndex) {
-            this.type = type;
-            this.signatureIndex = signatureIndex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + signatureIndex;
-            result = prime * result + type.hashCode();
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) {
-                return true;
-            } else if (obj == null) {
-                return false;
-            } else if (getClass() != obj.getClass()) {
-                return false;
-            }
-
-            TypeGuard other = (TypeGuard) obj;
-            if (signatureIndex != other.signatureIndex) {
-                return false;
-            } else if (!type.equals(other.type)) {
-                return false;
-            }
-            return true;
-        }
-
-        public int getSignatureIndex() {
-            return signatureIndex;
-        }
-
-        public TypeMirror getType() {
-            return type;
-        }
-    }
-
-    public SpecializationGroup getPrevious() {
-        if (getParent() == null) {
-            return null;
-        }
-
-        List<SpecializationGroup> parentChildren = getParent().getChildren();
-        int index = parentChildren.indexOf(this);
-        if (index <= 0) {
-            return null;
-        }
-        return parentChildren.get(index - 1);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
-
-public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
-
-    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
-        super(context, operation);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
-        spec.getAnnotations().add(new AnnotatedParameterSpec(getContext().getDeclaredType(Cached.class)));
-        return spec;
-    }
-
-    @Override
-    public SpecializationData create(TemplateMethod method, boolean invalid) {
-        return parseSpecialization(method);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return Specialization.class;
-    }
-
-    private SpecializationData parseSpecialization(TemplateMethod method) {
-        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
-        if (method.getMethod() != null) {
-            AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
-            List<TypeMirror> exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
-            List<TypeMirror> rewriteOnTypes = new ArrayList<>();
-            for (TypeMirror exceptionType : exceptionTypes) {
-                SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
-                if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
-                    method.addError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @%s method must specify a throws clause with the exception type '%s'.",
-                                    Specialization.class.getSimpleName(), ElementUtils.getQualifiedName(exceptionType));
-                }
-                rewriteOnTypes.add(throwsData.getJavaClass());
-                exceptionData.add(throwsData);
-            }
-
-            for (TypeMirror typeMirror : method.getMethod().getThrownTypes()) {
-                if (!ElementUtils.canThrowType(rewriteOnTypes, typeMirror)) {
-                    method.addError(rewriteValue, "A checked exception '%s' is thrown but is not specified using the rewriteOn property. "
-                                    + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.",
-                                    ElementUtils.getQualifiedName(typeMirror));
-                }
-            }
-
-            Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
-
-                @Override
-                public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
-                    return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
-                }
-            });
-        }
-        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData);
-
-        if (method.getMethod() != null) {
-            String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
-            if (!insertBeforeName.equals("")) {
-                specialization.setInsertBeforeName(insertBeforeName);
-            }
-
-            List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
-            Set<String> containsNames = specialization.getContainsNames();
-            containsNames.clear();
-            if (containsDefs != null) {
-                for (String include : containsDefs) {
-                    if (!containsNames.contains(include)) {
-                        specialization.getContainsNames().add(include);
-                    } else {
-                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
-                        specialization.addError(value, "Duplicate contains declaration '%s'.", include);
-                    }
-                }
-
-            }
-        }
-
-        return specialization;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
-
-    protected final T template;
-    private final ProcessorContext context;
-    private final MethodSpecParser parser;
-
-    private boolean parseNullOnError;
-
-    public TemplateMethodParser(ProcessorContext context, T template) {
-        this.template = template;
-        this.context = context;
-        this.parser = new MethodSpecParser(template);
-    }
-
-    public void setParseNullOnError(boolean parseNullOnError) {
-        this.parseNullOnError = parseNullOnError;
-    }
-
-    public boolean isParseNullOnError() {
-        return parseNullOnError;
-    }
-
-    public MethodSpecParser getParser() {
-        return parser;
-    }
-
-    public ProcessorContext getContext() {
-        return context;
-    }
-
-    public TypeSystemData getTypeSystem() {
-        return template.getTypeSystem();
-    }
-
-    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
-
-    public abstract E create(TemplateMethod method, boolean invalid);
-
-    public abstract boolean isParsable(ExecutableElement method);
-
-    public Class<? extends Annotation> getAnnotationType() {
-        return null;
-    }
-
-    public final List<E> parse(List<? extends Element> elements) {
-        List<ExecutableElement> methods = new ArrayList<>();
-        methods.addAll(ElementFilter.methodsIn(elements));
-
-        List<E> parsedMethods = new ArrayList<>();
-        boolean valid = true;
-        int naturalOrder = 0;
-        for (ExecutableElement method : methods) {
-            if (!isParsable(method)) {
-                continue;
-            }
-
-            Class<? extends Annotation> annotationType = getAnnotationType();
-            AnnotationMirror mirror = null;
-            if (annotationType != null) {
-                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
-            }
-
-            E parsedMethod = parse(naturalOrder, method, mirror);
-
-            if (method.getModifiers().contains(Modifier.PRIVATE) && parser.isEmitErrors()) {
-                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
-                parsedMethods.add(parsedMethod);
-                valid = false;
-                continue;
-            }
-
-            if (parsedMethod != null) {
-                parsedMethods.add(parsedMethod);
-            } else {
-                valid = false;
-            }
-            naturalOrder++;
-        }
-        Collections.sort(parsedMethods);
-
-        if (!valid && isParseNullOnError()) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
-        MethodSpec methodSpecification = createSpecification(method, annotation);
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        TemplateMethod templateMethod = parser.parse(methodSpecification, method, annotation, naturalOrder);
-        if (templateMethod != null) {
-            return create(templateMethod, templateMethod.hasErrors());
-        }
-        return null;
-    }
-
-    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<VariableElement> parameterTypes) {
-        TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
-        if (method != null) {
-            return create(method, method.hasErrors());
-        }
-        return null;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
-
-    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "value");
-        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetTypeMirror);
-        returnTypeSpec.setAllowSubclasses(false);
-        MethodSpec spec = new MethodSpec(returnTypeSpec);
-        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
-        return spec;
-    }
-
-    @Override
-    public TypeCastData create(TemplateMethod method, boolean invalid) {
-        TypeMirror targetType = resolveCastOrCheck(method);
-        TypeMirror sourceType = getContext().getType(Object.class);
-        return new TypeCastData(method, sourceType, targetType);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCast.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
-
-    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
-        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
-        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
-        return spec;
-    }
-
-    @Override
-    public TypeCheckData create(TemplateMethod method, boolean invalid) {
-        TypeMirror targetType = resolveCastOrCheck(method);
-        return new TypeCheckData(method, targetType, targetType);
-    }
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeCheck.class;
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
-
-    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
-        super(context, typeSystem);
-    }
-
-    @Override
-    public final boolean isParsable(ExecutableElement method) {
-        return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
-    }
-
-    protected final TypeMirror resolveCastOrCheck(TemplateMethod method) {
-        Class<?> annotationType = getAnnotationType();
-        TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, method.getMessageAnnotation(), "value");
-        if (!method.getMethod().getModifiers().contains(Modifier.PUBLIC) || !method.getMethod().getModifiers().contains(Modifier.STATIC)) {
-            method.addError("@%s annotated method %s must be public and static.", annotationType.getSimpleName(), method.getMethodName());
-        }
-        return targetTypeMirror;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.parser;
-
-import java.lang.annotation.*;
-import java.util.*;
-
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.dsl.processor.java.*;
-import com.oracle.truffle.dsl.processor.model.*;
-
-@DSLOptions
-public class TypeSystemParser extends AbstractParser<TypeSystemData> {
-
-    public static final List<Class<TypeSystem>> ANNOTATIONS = Arrays.asList(TypeSystem.class);
-
-    @Override
-    public Class<? extends Annotation> getAnnotationType() {
-        return TypeSystem.class;
-    }
-
-    @Override
-    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
-        TypeElement templateType = (TypeElement) element;
-        AnnotationMirror templateTypeAnnotation = mirror;
-        DSLOptions options = element.getAnnotation(DSLOptions.class);
-        if (options == null) {
-            options = TypeSystemParser.class.getAnnotation(DSLOptions.class);
-        }
-        assert options != null;
-
-        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options, false);
-
-        // annotation type on class path!?
-        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
-        if (annotationTypeElement == null) {
-            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
-        }
-        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
-            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
-        }
-
-        if (templateType.getModifiers().contains(Modifier.FINAL)) {
-            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
-        }
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-
-        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
-
-        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
-        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
-        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
-        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
-
-        if (casts == null || checks == null || implicitCasts == null) {
-            return typeSystem;
-        }
-
-        List<TypeMirror> legacyTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
-        for (int i = 0; i < legacyTypes.size(); i++) {
-            legacyTypes.set(i, ElementUtils.fillInGenericWildcards(legacyTypes.get(i)));
-        }
-
-        typeSystem.getLegacyTypes().addAll(legacyTypes);
-        verifyTypes(typeSystem);
-        typeSystem.getLegacyTypes().add(context.getType(Object.class));
-        typeSystem.getLegacyTypes().add(context.getType(void.class));
-        verifyNamesUnique(typeSystem);
-
-        typeSystem.getImplicitCasts().addAll(implicitCasts);
-        typeSystem.getCasts().addAll(casts);
-        typeSystem.getChecks().addAll(checks);
-
-        if (typeSystem.hasErrors()) {
-            return typeSystem;
-        }
-        return typeSystem;
-    }
-
-    private void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
-        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
-        for (ExecutableElement method : methods) {
-            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
-            for (int i = 0; i < annotationTypes.length; i++) {
-                Class<?> annotationType = annotationTypes[i];
-                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
-                if (mirror != null) {
-                    foundAnnotations.add(mirror);
-                }
-            }
-            if (foundAnnotations.size() > 1) {
-                List<String> annotationNames = new ArrayList<>();
-                for (AnnotationMirror mirror : foundAnnotations) {
-                    annotationNames.add("@" + ElementUtils.getSimpleName(mirror.getAnnotationType()));
-                }
-
-                template.addError("Non exclusive usage of annotations %s.", annotationNames);
-            }
-        }
-    }
-
-    private void verifyTypes(TypeSystemData typeSystem) {
-        for (TypeMirror type : typeSystem.getLegacyTypes()) {
-            if (isPrimitiveWrapper(type)) {
-                typeSystem.addError("Types must not contain primitive wrapper types.");
-            }
-
-            if (ElementUtils.typeEquals(type, context.getType(Object.class))) {
-                typeSystem.addError("Types must not contain the generic type java.lang.Object.");
-            }
-        }
-
-        verifyTypeOrder(typeSystem);
-    }
-
-    private static void verifyTypeOrder(TypeSystemData typeSystem) {
-        Map<String, List<String>> invalidTypes = new HashMap<>();
-
-        for (int i = typeSystem.getLegacyTypes().size() - 1; i >= 0; i--) {
-            TypeMirror typeData = typeSystem.getLegacyTypes().get(i);
-            TypeMirror type = typeSystem.boxType(typeData);
-            if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) {
-                typeSystem.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)),
-                                ElementUtils.getQualifiedName(type));
-            }
-            TypeElement element = ElementUtils.fromTypeMirror(type);
-            List<String> nextInvalidTypes = new ArrayList<>();
-            if (element != null) {
-                nextInvalidTypes.addAll(ElementUtils.getQualifiedSuperTypeNames(element));
-            }
-            nextInvalidTypes.add(ElementUtils.getQualifiedName(type));
-
-            for (String qualifiedName : nextInvalidTypes) {
-                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
-                if (inheritedTypes == null) {
-                    inheritedTypes = new ArrayList<>();
-                    invalidTypes.put(qualifiedName, inheritedTypes);
-                }
-                inheritedTypes.add(ElementUtils.getQualifiedName(typeSystem.boxType(typeData)));
-            }
-        }
-    }
-
-    private boolean isPrimitiveWrapper(TypeMirror type) {
-        Types types = context.getEnvironment().getTypeUtils();
-        for (TypeKind kind : TypeKind.values()) {
-            if (!kind.isPrimitive()) {
-                continue;
-            }
-            if (ElementUtils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static void verifyNamesUnique(TypeSystemData typeSystem) {
-        Set<String> usedNames = new HashSet<>();
-        for (TypeMirror type : typeSystem.getLegacyTypes()) {
-            String boxedName = ElementUtils.getSimpleName(typeSystem.boxType(type));
-            String primitiveName = ElementUtils.getSimpleName(type);
-            if (usedNames.contains(boxedName)) {
-                typeSystem.addError("Two types result in the same boxed name: %s.", boxedName);
-            } else if (usedNames.contains(primitiveName)) {
-                typeSystem.addError("Two types result in the same primitive name: %s.", primitiveName);
-            }
-            usedNames.add(boxedName);
-            usedNames.add(primitiveName);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.util;
-
-import java.util.*;
-
-public class Filterator<T> implements Iterator<T> {
-
-    private final Predicate<T> includePredicate;
-    private final Iterator<T> elements;
-
-    private boolean hasCached;
-    private T cached;
-
-    public Filterator(Iterator<T> elements, Predicate<T> includePredicate) {
-        this.elements = elements;
-        this.includePredicate = includePredicate;
-    }
-
-    public boolean hasNext() {
-        if (hasCached) {
-            return true;
-        }
-        nextValue();
-        return hasCached;
-    }
-
-    private void nextValue() {
-        while (!hasCached && elements.hasNext()) {
-            T element = elements.next();
-            if (includePredicate.evaluate(element)) {
-                cached = element;
-                hasCached = true;
-            }
-        }
-    }
-
-    public T next() {
-        T foundCached = getCached();
-        if (foundCached != null) {
-            return foundCached;
-        } else {
-            nextValue();
-            if (!hasCached) {
-                throw new NoSuchElementException();
-            }
-            return getCached();
-        }
-    }
-
-    private T getCached() {
-        if (hasCached) {
-            hasCached = false;
-            T value = cached;
-            cached = null;
-            return value;
-        }
-        return null;
-    }
-
-    @Override
-    public void remove() {
-        elements.remove();
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.util;
-
-import java.util.*;
-
-public class FilteredIterable<E> implements Iterable<E> {
-
-    private final Iterable<E> delegate;
-    private final Predicate<E> containedPredicate;
-
-    public FilteredIterable(Iterable<E> delegate, Predicate<E> containedPredicate) {
-        this.delegate = delegate;
-        this.containedPredicate = containedPredicate;
-    }
-
-    public Iterator<E> iterator() {
-        return new Filterator<>(delegate.iterator(), containedPredicate);
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.util;
-
-public interface Predicate<T> {
-
-    boolean evaluate(T value);
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/verify/VerifyTruffleProcessor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.dsl.processor.verify;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-import static java.util.Collections.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.annotation.processing.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.tools.Diagnostic.Kind;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.dsl.processor.*;
-
-@SupportedAnnotationTypes({"com.oracle.truffle.api.CompilerDirectives.TruffleBoundary", "com.oracle.truffle.api.nodes.Node.Child"})
-public class VerifyTruffleProcessor extends AbstractProcessor {
-    @Override
-    public SourceVersion getSupportedSourceVersion() {
-        return SourceVersion.latest();
-    }
-
-    /**
-     * Node class currently being processed.
-     */
-    private Element scope;
-
-    public static boolean isEnclosedIn(Element e, Element scopeElement) {
-        List<Element> elementHierarchy = getElementHierarchy(e);
-        return elementHierarchy.contains(scopeElement);
-    }
-
-    void errorMessage(Element element, String format, Object... args) {
-        message(Kind.ERROR, element, format, args);
-    }
-
-    void message(Kind kind, Element element, String format, Object... args) {
-        if (scope != null && !isEnclosedIn(element, scope)) {
-            // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=428357#c1
-            List<Element> elementHierarchy = getElementHierarchy(element);
-            reverse(elementHierarchy);
-
-            StringBuilder str = new StringBuilder();
-            for (Element e : elementHierarchy) {
-                if (e.getKind() != ElementKind.PACKAGE) {
-                    str.append(str.length() == 0 ? "" : ".");
-                    str.append(e);
-                }
-            }
-            processingEnv.getMessager().printMessage(kind, String.format(str + ": " + format, args), scope);
-        } else {
-            processingEnv.getMessager().printMessage(kind, String.format(format, args), element);
-        }
-    }
-
-    /**
-     * Bugs in an annotation processor can cause silent failure so try to report any exception
-     * throws as errors.
-     */
-    private void reportException(Kind kind, Element element, Throwable t) {
-        StringWriter buf = new StringWriter();
-        t.printStackTrace(new PrintWriter(buf));
-        buf.toString();
-        message(kind, element, "Exception thrown during processing: %s", buf.toString());
-    }
-
-    @Override
-    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-        if (roundEnv.processingOver()) {
-            return false;
-        }
-
-        TypeElement virtualFrameType = processingEnv.getElementUtils().getTypeElement("com.oracle.truffle.api.frame.VirtualFrame");
-
-        for (Element element : roundEnv.getElementsAnnotatedWith(TruffleBoundary.class)) {
-            scope = element;
-            try {
-                ExecutableElement method = (ExecutableElement) element;
-
-                for (VariableElement parameter : method.getParameters()) {
-                    Element paramType = processingEnv.getTypeUtils().asElement(parameter.asType());
-                    if (paramType != null && paramType.equals(virtualFrameType)) {
-                        errorMessage(element, "Method %s cannot be annotated with @%s and have a parameter of type %s", method.getSimpleName(), TruffleBoundary.class.getSimpleName(),
-                                        paramType.getSimpleName());
-                    }
-                }
-            } catch (Throwable t) {
-                reportException(isBug367599(t) ? Kind.NOTE : Kind.ERROR, element, t);
-            } finally {
-                scope = null;
-            }
-        }
-
-        for (Element e : roundEnv.getElementsAnnotatedWith(Child.class)) {
-            if (e.getModifiers().contains(Modifier.FINAL)) {
-                emitError("@Child field cannot be final", e);
-                continue;
-            }
-            assertNoErrorExpected(e);
-        }
-        return false;
-    }
-
-    void assertNoErrorExpected(Element element) {
-        ExpectError.assertNoErrorExpected(processingEnv, element);
-    }
-
-    void emitError(String message, Element element) {
-        if (ExpectError.isExpectedError(processingEnv, element, message)) {
-            return;
-        }
-        processingEnv.getMessager().printMessage(Kind.ERROR, message, element);
-    }
-
-    /**
-     * Determines if a given exception is (most likely) caused by <a
-     * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599</a>.
-     */
-    public static boolean isBug367599(Throwable t) {
-        if (t instanceof FilerException) {
-            for (StackTraceElement ste : t.getStackTrace()) {
-                if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) {
-                    // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599
-                    return true;
-                }
-            }
-        }
-        if (t.getCause() != null) {
-            return isBug367599(t.getCause());
-        }
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/META-INF/services/com.oracle.truffle.api.object.LayoutFactory	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-com.oracle.truffle.object.basic.DefaultLayoutFactory
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicAllocator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import static com.oracle.truffle.object.basic.BasicLocations.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
-import com.oracle.truffle.object.Locations.ConstantLocation;
-import com.oracle.truffle.object.Locations.DeclaredDualLocation;
-import com.oracle.truffle.object.Locations.DualLocation;
-import com.oracle.truffle.object.Locations.ValueLocation;
-import com.oracle.truffle.object.basic.BasicLocations.BooleanLocationDecorator;
-import com.oracle.truffle.object.basic.BasicLocations.DoubleLocationDecorator;
-import com.oracle.truffle.object.basic.BasicLocations.IntLocationDecorator;
-import com.oracle.truffle.object.basic.BasicLocations.LongArrayLocation;
-import com.oracle.truffle.object.basic.BasicLocations.LongFieldLocation;
-import com.oracle.truffle.object.basic.BasicLocations.ObjectArrayLocation;
-
-public abstract class BasicAllocator extends ShapeImpl.BaseAllocator {
-
-    public BasicAllocator(LayoutImpl layout) {
-        super(layout);
-        advance(((BasicLayout) layout).getPrimitiveArrayLocation());
-    }
-
-    public BasicAllocator(ShapeImpl shape) {
-        super(shape);
-    }
-
-    private BasicLayout getLayout() {
-        return (BasicLayout) layout;
-    }
-
-    @Override
-    protected Location moveLocation(Location oldLocation) {
-        if (oldLocation instanceof DeclaredDualLocation) {
-            return advance(newDeclaredDualLocation(((DeclaredDualLocation) oldLocation).get(null, false)));
-        } else if (oldLocation instanceof DualLocation) {
-            return advance(newDualLocation(((DualLocation) oldLocation).getType()));
-        } else if (oldLocation instanceof LongLocation) {
-            return newLongLocation(oldLocation.isFinal());
-        } else if (oldLocation instanceof IntLocation) {
-            return newIntLocation(oldLocation.isFinal());
-        } else if (oldLocation instanceof DoubleLocation) {
-            return newDoubleLocation(oldLocation.isFinal());
-        } else if (oldLocation instanceof BooleanLocation) {
-            return newBooleanLocation(oldLocation.isFinal());
-        } else if (oldLocation instanceof ObjectLocation) {
-            return newObjectLocation(oldLocation.isFinal(), ((ObjectLocation) oldLocation).isNonNull());
-        } else {
-            assert oldLocation instanceof ValueLocation;
-            return advance(oldLocation);
-        }
-    }
-
-    @Override
-    public Location newObjectLocation(boolean useFinal, boolean nonNull) {
-        if (ObjectStorageOptions.InObjectFields) {
-            int insertPos = objectFieldSize;
-            while (insertPos + OBJECT_SIZE <= getLayout().getObjectFieldCount()) {
-                return advance((Location) getLayout().getObjectFieldLocation(insertPos));
-            }
-        }
-        return newObjectArrayLocation(useFinal, nonNull);
-    }
-
-    @SuppressWarnings("unused")
-    private Location newObjectArrayLocation(boolean useFinal, boolean nonNull) {
-        return advance(new ObjectArrayLocation(objectArraySize, getLayout().getObjectArrayLocation()));
-    }
-
-    @Override
-    public Location newTypedObjectLocation(boolean useFinal, Class<?> type, boolean nonNull) {
-        return newObjectLocation(useFinal, nonNull);
-    }
-
-    @Override
-    public Location newIntLocation(boolean useFinal) {
-        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.IntegerLocations) {
-            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
-                return advance(new IntLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize)));
-            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
-                return advance(new IntLocationDecorator(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation())));
-            }
-        }
-        return newObjectLocation(useFinal, true);
-    }
-
-    @Override
-    public Location newDoubleLocation(boolean useFinal) {
-        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.DoubleLocations) {
-            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
-                return advance(new DoubleLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize), getLayout().isAllowedIntToDouble()));
-            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
-                return advance(new DoubleLocationDecorator(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation()), getLayout().isAllowedIntToDouble()));
-            }
-        }
-        return newObjectLocation(useFinal, true);
-    }
-
-    @Override
-    public Location newLongLocation(boolean useFinal) {
-        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.LongLocations) {
-            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
-                return advance((Location) LongFieldLocation.create(getLayout().getPrimitiveFieldLocation(primitiveFieldSize), getLayout().isAllowedIntToLong()));
-            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
-                return advance(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation(), getLayout().isAllowedIntToLong()));
-            }
-        }
-        return newObjectLocation(useFinal, true);
-    }
-
-    @Override
-    public Location newBooleanLocation(boolean useFinal) {
-        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.BooleanLocations) {
-            if (primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
-                return advance(new BooleanLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize)));
-            }
-        }
-        return newObjectLocation(useFinal, true);
-    }
-
-    private boolean isPrimitiveExtensionArrayAvailable() {
-        return hasPrimitiveArray;
-    }
-
-    @Override
-    protected Location locationForValueUpcast(Object value, Location oldLocation) {
-        assert !(value instanceof Class);
-        if (oldLocation instanceof DualLocation) {
-            DualLocation dualLocation = (DualLocation) oldLocation;
-            if (dualLocation.getType() == null) {
-                if (value instanceof Integer) {
-                    return dualLocation.changeType(int.class);
-                } else if (value instanceof Double) {
-                    return dualLocation.changeType(double.class);
-                } else if (value instanceof Long) {
-                    return dualLocation.changeType(long.class);
-                } else if (value instanceof Boolean) {
-                    return dualLocation.changeType(boolean.class);
-                } else {
-                    return dualLocation.changeType(Object.class);
-                }
-            } else if (dualLocation.getType().isPrimitive()) {
-                return dualLocation.changeType(Object.class);
-            } else {
-                throw new UnsupportedOperationException();
-            }
-        } else if (oldLocation instanceof ConstantLocation) {
-            return constantLocation(value);
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Override
-    protected DeclaredDualLocation newDeclaredDualLocation(Object value) {
-        return new DeclaredDualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), value, layout);
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLayout.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.api.object.Shape.Allocator;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
-import com.oracle.truffle.object.Locations.DualLocation;
-import com.oracle.truffle.object.basic.BasicLocations.ObjectFieldLocation;
-import com.oracle.truffle.object.basic.BasicLocations.SimpleObjectFieldLocation;
-
-public class BasicLayout extends LayoutImpl {
-    private final ObjectLocation[] objectFields;
-    private final InternalLongLocation[] primitiveFields;
-    private final Location objectArrayLocation;
-    private final Location primitiveArrayLocation;
-
-    BasicLayout(EnumSet<ImplicitCast> allowedImplicitCasts, LayoutStrategy strategy) {
-        super(allowedImplicitCasts, DynamicObjectBasic.class, strategy);
-        this.objectFields = DynamicObjectBasic.OBJECT_FIELD_LOCATIONS;
-        this.primitiveFields = DynamicObjectBasic.PRIMITIVE_FIELD_LOCATIONS;
-        this.primitiveArrayLocation = DynamicObjectBasic.PRIMITIVE_ARRAY_LOCATION;
-        this.objectArrayLocation = DynamicObjectBasic.OBJECT_ARRAY_LOCATION;
-    }
-
-    static LayoutImpl createLayoutImpl(EnumSet<ImplicitCast> allowedImplicitCasts, LayoutStrategy strategy) {
-        return new BasicLayout(allowedImplicitCasts, strategy);
-    }
-
-    @Override
-    public DynamicObject newInstance(Shape shape) {
-        return new DynamicObjectBasic(shape);
-    }
-
-    @Override
-    public Shape createShape(ObjectType operations, Object sharedData, int id) {
-        return new ShapeBasic(this, sharedData, operations, id);
-    }
-
-    @Override
-    protected boolean hasObjectExtensionArray() {
-        return true;
-    }
-
-    @Override
-    protected boolean hasPrimitiveExtensionArray() {
-        return true;
-    }
-
-    @Override
-    protected int getObjectFieldCount() {
-        return objectFields.length;
-    }
-
-    @Override
-    protected int getPrimitiveFieldCount() {
-        return primitiveFields.length;
-    }
-
-    @Override
-    protected Location getObjectArrayLocation() {
-        return objectArrayLocation;
-    }
-
-    @Override
-    protected Location getPrimitiveArrayLocation() {
-        return primitiveArrayLocation;
-    }
-
-    protected ObjectLocation getObjectFieldLocation(int index) {
-        return objectFields[index];
-    }
-
-    protected InternalLongLocation getPrimitiveFieldLocation(int index) {
-        return primitiveFields[index];
-    }
-
-    @Override
-    public Allocator createAllocator() {
-        LayoutImpl layout = this;
-        Allocator allocator = getStrategy().createAllocator(layout);
-        return allocator;
-    }
-
-    @Override
-    protected int objectFieldIndex(Location location) {
-        if (location instanceof DualLocation) {
-            return objectFieldIndex((Location) ((DualLocation) location).getObjectLocation());
-        } else if (location instanceof ObjectFieldLocation) {
-            return ((ObjectFieldLocation) location).getIndex();
-        } else if (location instanceof SimpleObjectFieldLocation) {
-            return ((SimpleObjectFieldLocation) location).getIndex();
-        } else {
-            return 0;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLocations.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,717 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import java.lang.invoke.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
-
-/**
- * Property location.
- *
- * @see Shape
- * @see Property
- * @see DynamicObject
- */
-public abstract class BasicLocations {
-    static final int LONG_SIZE = 1;
-    static final int OBJECT_SIZE = 1;
-
-    public abstract static class ArrayLocation extends LocationImpl {
-        protected final int index;
-        protected final Location arrayLocation;
-
-        public ArrayLocation(int index, Location arrayLocation) {
-            this.index = index;
-            this.arrayLocation = arrayLocation;
-        }
-
-        protected final Object getArray(DynamicObject store, boolean condition) {
-            // non-null cast
-            return arrayLocation.get(store, condition);
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + index;
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!super.equals(obj)) {
-                return false;
-            }
-            ArrayLocation other = (ArrayLocation) obj;
-            if (index != other.index) {
-                return false;
-            }
-            return true;
-        }
-
-        public final int getIndex() {
-            return index;
-        }
-
-        @Override
-        protected String getWhereString() {
-            return "[" + index + "]";
-        }
-    }
-
-    public abstract static class FieldLocation extends LocationImpl {
-        private final int index;
-
-        public FieldLocation(int index) {
-            this.index = index;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + index;
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!super.equals(obj)) {
-                return false;
-            }
-            FieldLocation other = (FieldLocation) obj;
-            if (index != other.index) {
-                return false;
-            }
-            return true;
-        }
-
-        public final int getIndex() {
-            return index;
-        }
-
-        @Override
-        protected String getWhereString() {
-            return "@" + index;
-        }
-    }
-
-    public abstract static class MethodHandleFieldLocation extends FieldLocation {
-        protected final MethodHandle getter;
-        protected final MethodHandle setter;
-
-        public MethodHandleFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
-            super(index);
-            this.getter = getter;
-            this.setter = setter;
-        }
-    }
-
-    public static class ObjectArrayLocation extends ArrayLocation implements ObjectLocation {
-        public ObjectArrayLocation(int index, Location arrayLocation) {
-            super(index, arrayLocation);
-        }
-
-        @Override
-        public Object get(DynamicObject store, boolean condition) {
-            return ((Object[]) getArray(store, condition))[index];
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            ((Object[]) getArray(store, false))[index] = value;
-        }
-
-        @Override
-        public boolean canStore(Object value) {
-            return true;
-        }
-
-        public Class<? extends Object> getType() {
-            return Object.class;
-        }
-
-        public final boolean isNonNull() {
-            return false;
-        }
-
-        @Override
-        public int objectArrayCount() {
-            return OBJECT_SIZE;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitObjectArray(index, OBJECT_SIZE);
-        }
-    }
-
-    public static class ObjectFieldLocation extends MethodHandleFieldLocation implements ObjectLocation {
-
-        public ObjectFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
-            super(index, getter, setter);
-        }
-
-        @Override
-        public Object get(DynamicObject store, boolean condition) {
-            try {
-                return getter.invokeExact(store);
-            } catch (Throwable e) {
-                CompilerDirectives.transferToInterpreter();
-                throw new IllegalStateException(e);
-            }
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            try {
-                setter.invokeExact(store, value);
-            } catch (Throwable e) {
-                CompilerDirectives.transferToInterpreter();
-                throw new IllegalStateException(e);
-            }
-        }
-
-        @Override
-        public boolean canStore(Object value) {
-            return true;
-        }
-
-        public Class<? extends Object> getType() {
-            return Object.class;
-        }
-
-        public boolean isNonNull() {
-            return false;
-        }
-
-        @Override
-        public int objectFieldCount() {
-            return OBJECT_SIZE;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitObjectField(getIndex(), OBJECT_SIZE);
-        }
-    }
-
-    public abstract static class SimpleObjectFieldLocation extends FieldLocation implements ObjectLocation {
-
-        public SimpleObjectFieldLocation(int index) {
-            super(index);
-        }
-
-        @Override
-        public abstract Object get(DynamicObject store, boolean condition);
-
-        @Override
-        public abstract void setInternal(DynamicObject store, Object value);
-
-        @Override
-        public boolean canStore(Object value) {
-            return true;
-        }
-
-        public Class<? extends Object> getType() {
-            return Object.class;
-        }
-
-        public boolean isNonNull() {
-            return false;
-        }
-
-        @Override
-        public int objectFieldCount() {
-            return OBJECT_SIZE;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitObjectField(getIndex(), OBJECT_SIZE);
-        }
-    }
-
-    public static class LongArrayLocation extends ArrayLocation implements InternalLongLocation {
-        protected final boolean allowInt;
-
-        public LongArrayLocation(int index, Location arrayLocation, boolean allowInt) {
-            super(index, arrayLocation);
-            this.allowInt = allowInt;
-        }
-
-        public LongArrayLocation(int index, Location arrayLocation) {
-            this(index, arrayLocation, false);
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getLong(store, condition);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setLongInternal(store, ((Number) value).longValue());
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        @Override
-        public long getLong(DynamicObject store, boolean condition) {
-            return ((long[]) getArray(store, condition))[index];
-        }
-
-        public final void setLongInternal(DynamicObject store, long value) {
-            ((long[]) getArray(store, false))[index] = value;
-        }
-
-        @Override
-        public void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException {
-            setLongInternal(store, value);
-        }
-
-        @Override
-        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setLongInternal(store, value);
-        }
-
-        @Override
-        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
-            setLong(store, value, null);
-        }
-
-        public final long getLong(DynamicObject store, Shape shape) {
-            return getLong(store, checkShape(store, shape));
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Long || (allowInt && value instanceof Integer);
-        }
-
-        public final Class<Long> getType() {
-            return long.class;
-        }
-
-        @Override
-        public int primitiveArrayCount() {
-            return LONG_SIZE;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitPrimitiveArray(getIndex(), LONG_SIZE);
-        }
-    }
-
-    public static class LongFieldLocation extends MethodHandleFieldLocation implements InternalLongLocation {
-        public LongFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
-            super(index, getter, setter);
-        }
-
-        public static LongLocation create(InternalLongLocation longLocation, boolean allowInt) {
-            if ((!allowInt && (longLocation instanceof LongLocationDecorator)) || (longLocation instanceof LongLocationDecorator && ((LongLocationDecorator) longLocation).allowInt == allowInt)) {
-                return longLocation;
-            } else {
-                return new LongLocationDecorator(longLocation, allowInt);
-            }
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getLong(store, condition);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setLongInternal(store, (long) value);
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Long;
-        }
-
-        @Override
-        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setLongInternal(store, value);
-        }
-
-        public long getLong(DynamicObject store, boolean condition) {
-            try {
-                return (long) getter.invokeExact(store);
-            } catch (Throwable e) {
-                CompilerDirectives.transferToInterpreter();
-                throw new IllegalStateException(e);
-            }
-        }
-
-        public void setLong(DynamicObject store, long value, Shape shape) {
-            setLongInternal(store, value);
-        }
-
-        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
-            setLong(store, value, null);
-        }
-
-        public final void setLongInternal(DynamicObject store, long value) {
-            try {
-                setter.invokeExact(store, value);
-            } catch (Throwable e) {
-                CompilerDirectives.transferToInterpreter();
-                throw new IllegalStateException(e);
-            }
-        }
-
-        public final long getLong(DynamicObject store, Shape shape) {
-            return getLong(store, checkShape(store, shape));
-        }
-
-        @Override
-        public final int primitiveFieldCount() {
-            return LONG_SIZE;
-        }
-
-        public final Class<Long> getType() {
-            return long.class;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitPrimitiveField(getIndex(), LONG_SIZE);
-        }
-    }
-
-    public static class LongLocationDecorator extends PrimitiveLocationDecorator implements InternalLongLocation {
-        protected final boolean allowInt;
-
-        public LongLocationDecorator(InternalLongLocation longLocation, boolean allowInt) {
-            super(longLocation);
-            this.allowInt = allowInt;
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getLong(store, condition);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setLongInternal(store, ((Number) value).longValue());
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Long || (allowInt && value instanceof Integer);
-        }
-
-        @Override
-        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setLongInternal(store, value);
-        }
-
-        public Class<Long> getType() {
-            return long.class;
-        }
-    }
-
-    public abstract static class SimpleLongFieldLocation extends FieldLocation implements InternalLongLocation {
-
-        public SimpleLongFieldLocation(int index) {
-            super(index);
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getLong(store, condition);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setLongInternal(store, ((Number) value).longValue());
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Long;
-        }
-
-        @Override
-        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setLongInternal(store, value);
-        }
-
-        public abstract long getLong(DynamicObject store, boolean condition);
-
-        public final long getLong(DynamicObject store, Shape shape) {
-            return getLong(store, checkShape(store, shape));
-        }
-
-        public final void setLong(DynamicObject store, long value) {
-            setLong(store, value, null);
-        }
-
-        public void setLong(DynamicObject store, long value, Shape shape) {
-            setLongInternal(store, value);
-        }
-
-        public abstract void setLongInternal(DynamicObject store, long value);
-
-        @Override
-        public final int primitiveFieldCount() {
-            return LONG_SIZE;
-        }
-
-        public final Class<Long> getType() {
-            return long.class;
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            locationVisitor.visitPrimitiveField(getIndex(), LONG_SIZE);
-        }
-    }
-
-    public abstract static class PrimitiveLocationDecorator extends LocationImpl {
-        private final InternalLongLocation longLocation;
-
-        public PrimitiveLocationDecorator(InternalLongLocation longLocation) {
-            this.longLocation = longLocation;
-        }
-
-        public final long getLong(DynamicObject store, Shape shape) {
-            return longLocation.getLong(store, shape);
-        }
-
-        public final long getLong(DynamicObject store, boolean condition) {
-            return longLocation.getLong(store, condition);
-        }
-
-        public final void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException {
-            longLocation.setLong(store, value, shape);
-        }
-
-        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
-            longLocation.setLong(store, value);
-        }
-
-        public final void setLongInternal(DynamicObject store, long value) {
-            longLocation.setLongInternal(store, value);
-        }
-
-        @Override
-        public final int primitiveFieldCount() {
-            return ((LocationImpl) longLocation).primitiveFieldCount();
-        }
-
-        @Override
-        public final int primitiveArrayCount() {
-            return ((LocationImpl) longLocation).primitiveArrayCount();
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            ((LocationImpl) longLocation).accept(locationVisitor);
-        }
-    }
-
-    public static class IntLocationDecorator extends PrimitiveLocationDecorator implements IntLocation {
-        public IntLocationDecorator(InternalLongLocation longLocation) {
-            super(longLocation);
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getInt(store, condition);
-        }
-
-        public int getInt(DynamicObject store, boolean condition) {
-            return (int) getLong(store, condition);
-        }
-
-        public void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException {
-            setLong(store, value, shape);
-        }
-
-        @Override
-        public final void setInt(DynamicObject store, int value) throws FinalLocationException {
-            setInt(store, value, null);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setLongInternal(store, (int) value);
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        public final int getInt(DynamicObject store, Shape shape) {
-            return getInt(store, checkShape(store, shape));
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Integer;
-        }
-
-        @Override
-        public final void setInt(DynamicObject store, int value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setLongInternal(store, value);
-        }
-
-        public Class<Integer> getType() {
-            return int.class;
-        }
-    }
-
-    public static class DoubleLocationDecorator extends PrimitiveLocationDecorator implements DoubleLocation {
-        private final boolean allowInt;
-
-        public DoubleLocationDecorator(InternalLongLocation longLocation, boolean allowInt) {
-            super(longLocation);
-            this.allowInt = allowInt;
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getDouble(store, condition);
-        }
-
-        public double getDouble(DynamicObject store, boolean condition) {
-            return Double.longBitsToDouble(getLong(store, condition));
-        }
-
-        public void setDouble(DynamicObject store, double value, Shape shape) {
-            setLongInternal(store, Double.doubleToRawLongBits(value));
-        }
-
-        public void setDouble(DynamicObject store, double value) {
-            setDouble(store, value, null);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setDouble(store, ((Number) value).doubleValue(), null);
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        public final double getDouble(DynamicObject store, Shape shape) {
-            return getDouble(store, checkShape(store, shape));
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Double || (allowInt && value instanceof Integer);
-        }
-
-        @Override
-        public final void setDouble(DynamicObject store, double value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setDouble(store, value, newShape);
-        }
-
-        public Class<Double> getType() {
-            return double.class;
-        }
-    }
-
-    public static class BooleanLocationDecorator extends PrimitiveLocationDecorator implements BooleanLocation {
-        public BooleanLocationDecorator(InternalLongLocation longLocation) {
-            super(longLocation);
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return getBoolean(store, condition);
-        }
-
-        public boolean getBoolean(DynamicObject store, boolean condition) {
-            return getLong(store, condition) != 0;
-        }
-
-        public void setBoolean(DynamicObject store, boolean value, Shape shape) {
-            setLongInternal(store, value ? 1 : 0);
-        }
-
-        public void setBoolean(DynamicObject store, boolean value) {
-            setBoolean(store, value, null);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (canStore(value)) {
-                setBoolean(store, (boolean) value, null);
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        public final boolean getBoolean(DynamicObject store, Shape shape) {
-            return getBoolean(store, checkShape(store, shape));
-        }
-
-        @Override
-        public final boolean canStore(Object value) {
-            return value instanceof Boolean;
-        }
-
-        @Override
-        public final void setBoolean(DynamicObject store, boolean value, Shape oldShape, Shape newShape) {
-            store.setShapeAndGrow(oldShape, newShape);
-            setBoolean(store, value, newShape);
-        }
-
-        public Class<Boolean> getType() {
-            return boolean.class;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultLayoutFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-
-public class DefaultLayoutFactory implements LayoutFactory {
-    public Layout createLayout(LayoutBuilder layoutBuilder) {
-        return BasicLayout.createLayoutImpl(layoutBuilder.getAllowedImplicitCasts(), new DefaultStrategy());
-    }
-
-    public Property createProperty(Object id, Location location) {
-        return createProperty(id, location, 0);
-    }
-
-    public Property createProperty(Object id, Location location, int flags) {
-        return new PropertyImpl(id, location, flags);
-    }
-
-    public int getPriority() {
-        return 10;
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
-
-class DefaultStrategy implements LayoutStrategy {
-    public boolean updateShape(DynamicObject object) {
-        assert object.getShape().isValid();
-        return false;
-    }
-
-    public Shape returnCached(Shape newShape) {
-        assert newShape.isValid();
-        return newShape;
-    }
-
-    private static boolean assertLocationInRange(Shape shape, Location location) {
-        BasicLayout layout = (BasicLayout) shape.getLayout();
-        assert (shape.getPrimitiveFieldSize() + ((LocationImpl) location).primitiveFieldCount() <= layout.getPrimitiveFieldCount());
-        assert (shape.getObjectFieldSize() + ((LocationImpl) location).objectFieldCount() <= layout.getObjectFieldCount());
-        return true;
-    }
-
-    public Shape ensureSpace(Shape shape, Location location) {
-        Objects.requireNonNull(location);
-        assert assertLocationInRange(shape, location);
-        return shape;
-    }
-
-    public boolean isAutoExtArray() {
-        return false;
-    }
-
-    public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value) {
-        Shape oldShape = object.getShape();
-        Location oldLocation = oldProperty.getLocation();
-        Location newLocation = ((BasicAllocator) oldShape.allocator()).locationForValueUpcast(value, oldLocation);
-        Property newProperty = oldProperty.relocate(newLocation);
-        Shape newShape = oldShape.replaceProperty(oldProperty, newProperty);
-        newProperty.setSafe(object, value, oldShape, newShape);
-        return newProperty;
-    }
-
-    public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape currentShape, Shape oldNewShape) {
-        Location oldLocation = oldProperty.getLocation();
-        Location newLocation = ((BasicAllocator) currentShape.allocator()).locationForValueUpcast(value, oldLocation);
-        Property newProperty = oldProperty.relocate(newLocation);
-        Shape newShape = oldNewShape.replaceProperty(oldProperty, newProperty);
-        newProperty.setSafe(object, value, currentShape, newShape);
-        return newProperty;
-    }
-
-    public BaseAllocator createAllocator(Shape shape) {
-        return new DefaultAllocatorImpl((ShapeImpl) shape);
-    }
-
-    public BaseAllocator createAllocator(Layout layout) {
-        return new DefaultAllocatorImpl((LayoutImpl) layout);
-    }
-
-    public static class DefaultAllocatorImpl extends BasicAllocator {
-        protected DefaultAllocatorImpl(LayoutImpl layout) {
-            super(layout);
-        }
-
-        protected DefaultAllocatorImpl(ShapeImpl shape) {
-            super(shape);
-        }
-
-        @Override
-        public Location locationForValue(Object value, boolean useFinal, boolean nonNull) {
-            return super.newDualLocationForValue(value);
-        }
-
-        @Override
-        public Location declaredLocation(Object value) {
-            return super.newDeclaredDualLocation(value);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DynamicObjectBasic.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import java.lang.annotation.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.basic.BasicLocations.SimpleLongFieldLocation;
-import com.oracle.truffle.object.basic.BasicLocations.SimpleObjectFieldLocation;
-
-public class DynamicObjectBasic extends DynamicObjectImpl {
-    @Retention(RetentionPolicy.RUNTIME)
-    protected @interface DynamicField {
-    }
-
-    @DynamicField private long primitive1;
-    @DynamicField private long primitive2;
-    @DynamicField private long primitive3;
-    @DynamicField private Object object1;
-    @DynamicField private Object object2;
-    @DynamicField private Object object3;
-    @DynamicField private Object object4;
-    private Object[] objext;
-    private long[] primext;
-
-    public DynamicObjectBasic(Shape shape) {
-        super(shape);
-    }
-
-    @Override
-    protected final void initialize(Shape shape) {
-        assert getObjectStore(shape) == null;
-        int capacity = ((ShapeImpl) shape).getObjectArrayCapacity();
-        if (capacity != 0) {
-            this.setObjectStore(new Object[capacity], shape);
-        }
-        if (((ShapeImpl) shape).getPrimitiveArrayCapacity() != 0) {
-            this.setPrimitiveStore(new long[((ShapeImpl) shape).getPrimitiveArrayCapacity()], shape);
-        }
-    }
-
-    /**
-     * Simpler version of {@link #resizeObjectStore} when the object is only increasing in size.
-     */
-    @Override
-    protected final void growObjectStore(Shape oldShape, Shape newShape) {
-        int oldObjectArrayCapacity = ((ShapeImpl) oldShape).getObjectArrayCapacity();
-        int newObjectArrayCapacity = ((ShapeImpl) newShape).getObjectArrayCapacity();
-        if (oldObjectArrayCapacity != newObjectArrayCapacity) {
-            growObjectStoreIntl(oldObjectArrayCapacity, newObjectArrayCapacity, oldShape);
-        }
-    }
-
-    private void growObjectStoreIntl(int oldObjectArrayCapacity, int newObjectArrayCapacity, Shape newShape) {
-        Object[] newObjectStore = new Object[newObjectArrayCapacity];
-        if (oldObjectArrayCapacity != 0) {
-            // monotonic growth assumption
-            assert oldObjectArrayCapacity < newObjectArrayCapacity;
-            Object[] oldObjectStore = this.getObjectStore(newShape);
-            for (int i = 0; i < oldObjectArrayCapacity; ++i) {
-                newObjectStore[i] = oldObjectStore[i];
-            }
-        }
-        this.setObjectStore(newObjectStore, newShape);
-    }
-
-    /**
-     * Simpler version of {@link #resizePrimitiveStore} when the object is only increasing in size.
-     */
-    @Override
-    protected final void growPrimitiveStore(Shape oldShape, Shape newShape) {
-        assert ((ShapeImpl) newShape).hasPrimitiveArray();
-        int oldPrimitiveCapacity = oldShape.getPrimitiveArrayCapacity();
-        int newPrimitiveCapacity = newShape.getPrimitiveArrayCapacity();
-        if (newPrimitiveCapacity == 0) {
-            // due to obsolescence, we might have to reserve an empty primitive array slot
-            this.setPrimitiveStore(null, newShape);
-        } else if (oldPrimitiveCapacity != newPrimitiveCapacity) {
-            growPrimitiveStoreIntl(oldPrimitiveCapacity, newPrimitiveCapacity, oldShape);
-        }
-    }
-
-    private void growPrimitiveStoreIntl(int oldPrimitiveCapacity, int newPrimitiveCapacity, Shape newShape) {
-        long[] newPrimitiveArray = new long[newPrimitiveCapacity];
-        if (oldPrimitiveCapacity != 0) {
-            // primitive array can shrink due to type changes
-            long[] oldPrimitiveArray = this.getPrimitiveStore(newShape);
-            for (int i = 0; i < Math.min(oldPrimitiveCapacity, newPrimitiveCapacity); ++i) {
-                newPrimitiveArray[i] = oldPrimitiveArray[i];
-            }
-        }
-        this.setPrimitiveStore(newPrimitiveArray, newShape);
-    }
-
-    @Override
-    protected final void resizeObjectStore(Shape oldShape, Shape newShape) {
-        Object[] newObjectStore = null;
-        int destinationCapacity = newShape.getObjectArrayCapacity();
-        if (destinationCapacity != 0) {
-            newObjectStore = new Object[destinationCapacity];
-            int sourceCapacity = oldShape.getObjectArrayCapacity();
-            if (sourceCapacity != 0) {
-                Object[] oldObjectStore = getObjectStore(newShape);
-                for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) {
-                    newObjectStore[i] = oldObjectStore[i];
-                }
-            }
-        }
-        this.setObjectStore(newObjectStore, newShape);
-    }
-
-    private Object[] getObjectStore(@SuppressWarnings("unused") Shape currentShape) {
-        return objext;
-    }
-
-    private void setObjectStore(Object[] newArray, @SuppressWarnings("unused") Shape currentShape) {
-        objext = newArray;
-    }
-
-    private long[] getPrimitiveStore(@SuppressWarnings("unused") Shape currentShape) {
-        return primext;
-    }
-
-    private void setPrimitiveStore(long[] newArray, @SuppressWarnings("unused") Shape currentShape) {
-        primext = newArray;
-    }
-
-    @Override
-    protected final void resizePrimitiveStore(Shape oldShape, Shape newShape) {
-        assert newShape.hasPrimitiveArray();
-        long[] newPrimitiveArray = null;
-        int destinationCapacity = newShape.getPrimitiveArrayCapacity();
-        if (destinationCapacity != 0) {
-            newPrimitiveArray = new long[destinationCapacity];
-            int sourceCapacity = oldShape.getPrimitiveArrayCapacity();
-            if (sourceCapacity != 0) {
-                long[] oldPrimitiveArray = this.getPrimitiveStore(newShape);
-                for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) {
-                    newPrimitiveArray[i] = oldPrimitiveArray[i];
-                }
-            }
-        }
-        this.setPrimitiveStore(newPrimitiveArray, newShape);
-    }
-
-    /**
-     * Check whether fast transition is valid.
-     *
-     * @see #setShapeAndGrow
-     */
-    @SuppressWarnings("unused")
-    private boolean checkSetShape(Shape oldShape, Shape newShape) {
-        Shape currentShape = getShape();
-        assert oldShape != newShape : "Wrong old shape assumption?";
-        assert newShape != currentShape : "Redundant shape change? shape=" + currentShape;
-        assert oldShape == currentShape || oldShape.getParent() == currentShape : "Out-of-order shape change?" + "\nparentShape=" + currentShape + "\noldShape=" + oldShape + "\nnewShape=" + newShape;
-        return true;
-    }
-
-    /**
-     * Check whether the extension arrays are in accordance with the description in the shape.
-     */
-    @Override
-    protected final boolean checkExtensionArrayInvariants(Shape newShape) {
-        assert getShape() == newShape;
-        assert (getObjectStore(newShape) == null && newShape.getObjectArrayCapacity() == 0) ||
-                        (getObjectStore(newShape) != null && getObjectStore(newShape).length == newShape.getObjectArrayCapacity());
-        if (newShape.hasPrimitiveArray()) {
-            assert (getPrimitiveStore(newShape) == null && newShape.getPrimitiveArrayCapacity() == 0) ||
-                            (getPrimitiveStore(newShape) != null && getPrimitiveStore(newShape).length == newShape.getPrimitiveArrayCapacity());
-        }
-        return true;
-    }
-
-    @Override
-    protected final DynamicObject cloneWithShape(Shape currentShape) {
-        assert this.getShape() == currentShape;
-        final DynamicObjectBasic clone = (DynamicObjectBasic) super.clone();
-        if (this.getObjectStore(currentShape) != null) {
-            clone.setObjectStore(this.getObjectStore(currentShape).clone(), currentShape);
-        }
-        if (currentShape.hasPrimitiveArray() && this.getPrimitiveStore(currentShape) != null) {
-            clone.setPrimitiveStore(this.getPrimitiveStore(currentShape).clone(), currentShape);
-        }
-        return clone;
-    }
-
-    protected final void reshape(ShapeImpl newShape) {
-        reshapeCount.inc();
-
-        ShapeImpl oldShape = getShape();
-        ShapeImpl commonAncestor = ShapeImpl.findCommonAncestor(oldShape, newShape);
-        if (ObjectStorageOptions.TraceReshape) {
-            int limit = 150;
-            System.out.printf("RESHAPE\nOLD %s\nNEW %s\nLCA %s\nDIFF %s\n---\n", oldShape.toStringLimit(limit), newShape.toStringLimit(limit), commonAncestor.toStringLimit(limit),
-                            ShapeImpl.diff(oldShape, newShape));
-        }
-
-        DynamicObject original = this.cloneWithShape(oldShape);
-        setShapeAndGrow(oldShape, newShape);
-        assert !((newShape.hasPrimitiveArray() && newShape.getPrimitiveArrayCapacity() == 0)) || getPrimitiveStore(newShape) == null;
-        copyProperties(original, commonAncestor);
-        assert checkExtensionArrayInvariants(newShape);
-    }
-
-    static final SimpleObjectFieldLocation[] OBJECT_FIELD_LOCATIONS;
-    static final SimpleLongFieldLocation[] PRIMITIVE_FIELD_LOCATIONS;
-
-    static final SimpleObjectFieldLocation OBJECT_ARRAY_LOCATION;
-    static final SimpleObjectFieldLocation PRIMITIVE_ARRAY_LOCATION;
-
-    static {
-        int index;
-
-        index = 0;
-        PRIMITIVE_FIELD_LOCATIONS = new SimpleLongFieldLocation[]{new SimpleLongFieldLocation(index++) {
-            @Override
-            public long getLong(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).primitive1;
-            }
-
-            @Override
-            public void setLongInternal(DynamicObject store, long value) {
-                ((DynamicObjectBasic) store).primitive1 = value;
-            }
-        }, new SimpleLongFieldLocation(index++) {
-            @Override
-            public long getLong(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).primitive2;
-            }
-
-            @Override
-            public void setLongInternal(DynamicObject store, long value) {
-                ((DynamicObjectBasic) store).primitive2 = value;
-            }
-        }, new SimpleLongFieldLocation(index++) {
-            @Override
-            public long getLong(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).primitive3;
-            }
-
-            @Override
-            public void setLongInternal(DynamicObject store, long value) {
-                ((DynamicObjectBasic) store).primitive3 = value;
-            }
-        }};
-
-        index = 0;
-        OBJECT_FIELD_LOCATIONS = new SimpleObjectFieldLocation[]{new SimpleObjectFieldLocation(index++) {
-            @Override
-            public Object get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).object1;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).object1 = value;
-            }
-        }, new SimpleObjectFieldLocation(index++) {
-            @Override
-            public Object get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).object2;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).object2 = value;
-            }
-        }, new SimpleObjectFieldLocation(index++) {
-            @Override
-            public Object get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).object3;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).object3 = value;
-            }
-        }, new SimpleObjectFieldLocation(index++) {
-            @Override
-            public Object get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).object4;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).object4 = value;
-            }
-        }};
-
-        OBJECT_ARRAY_LOCATION = new SimpleObjectFieldLocation(index++) {
-            @Override
-            public Object[] get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).objext;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).objext = (Object[]) value;
-            }
-        };
-
-        PRIMITIVE_ARRAY_LOCATION = new SimpleObjectFieldLocation(index++) {
-            @Override
-            public long[] get(DynamicObject store, boolean condition) {
-                return ((DynamicObjectBasic) store).primext;
-            }
-
-            @Override
-            public void setInternal(DynamicObject store, Object value) {
-                ((DynamicObjectBasic) store).primext = (long[]) value;
-            }
-        };
-    }
-}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.basic;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-
-public final class ShapeBasic extends ShapeImpl {
-    public ShapeBasic(Layout layout, Object sharedData, ObjectType operations, int id) {
-        super(layout, operations, sharedData, id);
-    }
-
-    public ShapeBasic(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
-        super(layout, parent, objectType, sharedData, propertyMap, transition, allocator, id);
-    }
-
-    @SuppressWarnings("hiding")
-    @Override
-    protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
-        return new ShapeBasic(layout, sharedData, parent, objectType, propertyMap, transition, allocator, id);
-    }
-
-    @Override
-    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
-        return directReplaceProperty(oldProperty, newProperty);
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.object.debug.*;
-
-class Debug {
-    private static Collection<ShapeImpl> allShapes;
-
-    static void registerShape(ShapeImpl newShape) {
-        allShapes.add(newShape);
-    }
-
-    static {
-        if (ObjectStorageOptions.DumpShapes) {
-            allShapes = new ConcurrentLinkedQueue<>();
-        }
-
-        if (ObjectStorageOptions.DumpShapes) {
-            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-                public void run() {
-                    try (PrintWriter out = new PrintWriter("shapes.json", "UTF-8")) {
-                        out.println("{\"shapes\": [");
-                        boolean first = true;
-                        for (ShapeImpl shape : allShapes) {
-                            if (!first) {
-                                out.println(",");
-                            }
-                            first = false;
-                            out.print(shape.accept(new JSONShapeVisitor()));
-                        }
-                        if (!first) {
-                            out.println();
-                        }
-                        out.println("]}");
-                    } catch (FileNotFoundException | UnsupportedEncodingException e) {
-                        throw new RuntimeException(e);
-                    }
-                }
-            }));
-        }
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugShapeVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-
-public abstract class DebugShapeVisitor<R> implements ShapeVisitor<R> {
-    public R visitShape(Shape shape) {
-        return visitShape(shape, Collections.unmodifiableMap(((ShapeImpl) shape).getTransitionMapForRead()));
-    }
-
-    public abstract R visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions);
-
-    public static String getId(Shape shape) {
-        return Integer.toHexString(shape.hashCode());
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,381 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.interop.*;
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.Locations.ValueLocation;
-import com.oracle.truffle.object.debug.*;
-
-public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable {
-    private ShapeImpl shape;
-
-    public static final DebugCounter reshapeCount = DebugCounter.create("Reshape count");
-
-    public DynamicObjectImpl(Shape shape) {
-        assert shape instanceof ShapeImpl;
-        initialize(shape);
-        setShape(shape);
-
-        if (ObjectStorageOptions.Profile) {
-            trackObject(this);
-        }
-    }
-
-    public Object getTypeIdentifier() {
-        return getShape();
-    }
-
-    @Override
-    public ShapeImpl getShape() {
-        return shape;
-    }
-
-    protected void setShape(Shape shape) {
-        assert shape.getLayout().getType().isInstance(this);
-        this.shape = (ShapeImpl) shape;
-    }
-
-    protected abstract void initialize(Shape initialShape);
-
-    public final void setShapeAndResize(Shape newShape) {
-        setShapeAndResize(getShape(), newShape);
-    }
-
-    @Override
-    public final void setShapeAndResize(Shape oldShape, Shape newShape) {
-        assert getShape() == oldShape : "wrong old shape";
-        if (oldShape != newShape) {
-            setShape(newShape);
-            resizeStore(oldShape, newShape);
-
-            assert checkExtensionArrayInvariants(newShape);
-        }
-    }
-
-    /**
-     * Set shape to an immediate child of the current shape, optionally growing the extension array.
-     * Typically this would add a single property. Cannot shrink or grow more than one property at a
-     * time.
-     *
-     * @see #setShapeAndResize(Shape, Shape)
-     */
-    @Override
-    public final void setShapeAndGrow(Shape oldShape, Shape newShape) {
-        assert getShape() == oldShape : "wrong old shape";
-        if (oldShape != newShape) {
-            assert checkSetShape(oldShape, newShape);
-
-            setShape(newShape);
-            growStore(oldShape, newShape);
-
-            assert checkExtensionArrayInvariants(newShape);
-        }
-    }
-
-    /**
-     * Simpler version of {@link #resizeStore} when the object is only increasing in size.
-     */
-    private void growStore(Shape oldShape, Shape newShape) {
-        growObjectStore(oldShape, newShape);
-        if (((ShapeImpl) newShape).hasPrimitiveArray) {
-            growPrimitiveStore(oldShape, newShape);
-        }
-    }
-
-    protected abstract void growObjectStore(Shape oldShape, Shape newShape);
-
-    protected abstract void growPrimitiveStore(Shape oldShape, Shape newShape);
-
-    private void resizeStore(Shape oldShape, Shape newShape) {
-        resizeObjectStore(oldShape, newShape);
-        if (((ShapeImpl) newShape).hasPrimitiveArray) {
-            resizePrimitiveStore(oldShape, newShape);
-        }
-    }
-
-    protected abstract void resizePrimitiveStore(Shape oldShape, Shape newShape);
-
-    protected abstract void resizeObjectStore(Shape oldShape, Shape newShape);
-
-    /**
-     * Check whether fast transition is valid.
-     *
-     * @see #setShapeAndGrow
-     */
-    private boolean checkSetShape(Shape oldShape, Shape newShape) {
-        Shape currentShape = getShape();
-        assert oldShape != newShape : "Wrong old shape assumption?";
-        assert newShape != currentShape : "Redundant shape change? shape=" + currentShape;
-        // assert oldShape == currentShape || (oldShape.getLastProperty() == ((EnterpriseLayout)
-        // oldShape.getLayout()).getPrimitiveArrayProperty() && oldShape.getParent() ==
-        // currentShape) : "Out-of-order shape change?" + "\nparentShape=" + currentShape +
-        // "\noldShape=" + oldShape + "\nnewShape=" + newShape;
-        return true;
-    }
-
-    /**
-     * Check whether the extension arrays are in accordance with the description in the shape.
-     */
-    protected abstract boolean checkExtensionArrayInvariants(Shape newShape);
-
-    @Override
-    protected final DynamicObject clone() {
-        try {
-            return (DynamicObject) super.clone();
-        } catch (CloneNotSupportedException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    protected abstract DynamicObject cloneWithShape(Shape currentShape);
-
-    void reshapeAfterDelete(final Shape newShape, final Shape deletedParentShape) {
-        DynamicObject original = this.cloneWithShape(getShape());
-        setShapeAndResize(newShape);
-        copyProperties(original, deletedParentShape);
-    }
-
-    public final void copyProperties(DynamicObject fromObject, Shape ancestor) {
-        ShapeImpl fromShape = (ShapeImpl) fromObject.getShape();
-        ShapeImpl toShape = getShape();
-        assert toShape.isRelated(ancestor);
-        assert toShape.isValid();
-        assert ancestor.isValid();
-        PropertyMap ancestorMap = ((ShapeImpl) ancestor).getPropertyMap();
-        PropertyMap fromMap = fromShape.getPropertyMap();
-        for (PropertyMap toMap = toShape.getPropertyMap(); !toMap.isEmpty() && toMap != ancestorMap; toMap = toMap.getParentMap()) {
-            Property toProperty = toMap.getLastProperty();
-            Property fromProperty = fromMap.get(toProperty.getKey());
-
-            // copy only if property has a location and it's not the same as the source location
-            if (toProperty.getLocation() != null && !(toProperty.getLocation() instanceof ValueLocation) && !toProperty.getLocation().equals(fromProperty.getLocation())) {
-                toProperty.setInternal(this, fromProperty.get(fromObject, false));
-                assert toShape.isValid();
-            }
-
-            if (fromProperty == fromMap.getLastProperty()) {
-                // no property is looked up twice, so we can skip over to parent
-                fromMap = fromMap.getParentMap();
-            }
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public boolean changeFlags(Object id, int newFlags) {
-        Shape oldShape = getShape();
-        Property existing = oldShape.getProperty(id);
-        if (existing != null) {
-            if (existing.getFlags() != newFlags) {
-                Property newProperty = existing.copyWithFlags(newFlags);
-                Shape newShape = oldShape.replaceProperty(existing, newProperty);
-                this.setShape(newShape);
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public boolean changeFlags(Object id, FlagsFunction updateFunction) {
-        Shape oldShape = getShape();
-        Property existing = oldShape.getProperty(id);
-        if (existing != null) {
-            int newFlags = updateFunction.apply(existing.getFlags());
-            if (existing.getFlags() != newFlags) {
-                Property newProperty = existing.copyWithFlags(newFlags);
-                Shape newShape = oldShape.replaceProperty(existing, newProperty);
-                this.setShape(newShape);
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public String debugDump(int level) {
-        return debugDump(0, level);
-    }
-
-    public String debugDump(int level, int levelStop) {
-        List<Property> properties = this.getShape().getPropertyListInternal(true);
-        StringBuilder sb = new StringBuilder(properties.size() * 10);
-        sb.append("{\n");
-        for (Property property : properties) {
-            indent(sb, level + 1);
-
-            sb.append(property.getKey());
-            sb.append('[').append(property.getLocation()).append(']');
-            Object value = property.get(this, false);
-            if (value instanceof DynamicObjectImpl) {
-                if (level < levelStop) {
-                    value = ((DynamicObjectImpl) value).debugDump(level + 1, levelStop);
-                } else {
-                    value = value.toString();
-                }
-            }
-            sb.append(": ");
-            sb.append(value);
-            if (property != properties.get(properties.size() - 1)) {
-                sb.append(",");
-            }
-            sb.append("\n");
-        }
-        indent(sb, level);
-        sb.append("}");
-        return sb.toString();
-    }
-
-    private static StringBuilder indent(StringBuilder sb, int level) {
-        for (int i = 0; i < level; i++) {
-            sb.append(' ');
-        }
-        return sb;
-    }
-
-    @Override
-    public String toString() {
-        return getShape().getObjectType().toString(this);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return getShape().getObjectType().equals(this, obj);
-    }
-
-    @Override
-    public int hashCode() {
-        return getShape().getObjectType().hashCode(this);
-    }
-
-    @Override
-    @TruffleBoundary
-    public Object get(Object id, Object defaultValue) {
-        Property existing = getShape().getProperty(id);
-        if (existing != null) {
-            return existing.get(this, false);
-        } else {
-            return defaultValue;
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public boolean set(Object id, Object value) {
-        Property existing = getShape().getProperty(id);
-        if (existing != null) {
-            existing.setGeneric(this, value, null);
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void define(Object id, Object value, int flags) {
-        ShapeImpl oldShape = getShape();
-        Property existing = oldShape.getProperty(id);
-        if (existing == null) {
-            updateShape();
-            oldShape = getShape();
-            Shape newShape = oldShape.addProperty(Property.create(id, oldShape.allocator().locationForValue(value, true, true), flags));
-            updateShape();
-            newShape.getLastProperty().setGeneric(this, value, oldShape, newShape);
-        } else {
-            defineExisting(id, value, flags, existing, oldShape);
-        }
-    }
-
-    private void defineExisting(Object id, Object value, int flags, Property existing, ShapeImpl oldShape) {
-        if (existing.getFlags() == flags) {
-            existing.setGeneric(this, value, null);
-        } else {
-            Property newProperty = Property.create(id, oldShape.getLayout().existingLocationForValue(value, existing.getLocation(), oldShape), flags);
-            Shape newShape = oldShape.replaceProperty(existing, newProperty);
-            this.setShapeAndResize(newShape);
-            newProperty.setInternal(this, value);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void define(Object id, Object value, int flags, LocationFactory locationFactory) {
-        ShapeImpl oldShape = getShape();
-        Property existing = oldShape.getProperty(id);
-        if (existing == null) {
-            updateShape();
-            oldShape = getShape();
-            Shape newShape = oldShape.addProperty(Property.create(id, locationFactory.createLocation(oldShape, value), flags));
-            updateShape();
-            newShape.getLastProperty().setGeneric(this, value, oldShape, newShape);
-        } else {
-            defineExisting(id, value, flags, existing, oldShape);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public boolean delete(Object id) {
-        ShapeImpl oldShape = getShape();
-        Property existing = oldShape.getProperty(id);
-        if (existing != null) {
-            ShapeImpl newShape = oldShape.removeProperty(existing);
-            this.reshapeAfterDelete(newShape, ShapeImpl.findCommonAncestor(oldShape, newShape));
-            // TODO ancestor should be the parent of found property's shape
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public int size() {
-        return getShape().getPropertyCount();
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    @Override
-    public final boolean updateShape() {
-        return getShape().getLayout().getStrategy().updateShape(this);
-    }
-
-    private static void trackObject(DynamicObject obj) {
-        ShapeProfiler.getInstance().track(obj);
-    }
-
-    @Override
-    public ForeignAccess getForeignAccess() {
-        return getShape().getForeignAccessFactory();
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.api.object.Shape.Allocator;
-import com.oracle.truffle.object.LocationImpl.EffectivelyFinalLocation;
-import com.oracle.truffle.object.LocationImpl.TypedObjectLocation;
-import com.oracle.truffle.object.Locations.ConstantLocation;
-import com.oracle.truffle.object.Locations.DeclaredLocation;
-import com.oracle.truffle.object.Locations.DualLocation;
-import com.oracle.truffle.object.Locations.ValueLocation;
-import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
-
-public abstract class LayoutImpl extends Layout {
-    private static final int INT_TO_DOUBLE_FLAG = 1;
-    private static final int INT_TO_LONG_FLAG = 2;
-
-    private final LayoutStrategy strategy;
-    private final Class<? extends DynamicObject> clazz;
-    private final int allowedImplicitCasts;
-
-    protected LayoutImpl(EnumSet<ImplicitCast> allowedImplicitCasts, Class<? extends DynamicObjectImpl> clazz, LayoutStrategy strategy) {
-        this.strategy = strategy;
-        this.clazz = clazz;
-
-        this.allowedImplicitCasts = (allowedImplicitCasts.contains(ImplicitCast.IntToDouble) ? INT_TO_DOUBLE_FLAG : 0) | (allowedImplicitCasts.contains(ImplicitCast.IntToLong) ? INT_TO_LONG_FLAG : 0);
-    }
-
-    @Override
-    public abstract DynamicObject newInstance(Shape shape);
-
-    @Override
-    public Class<? extends DynamicObject> getType() {
-        return clazz;
-    }
-
-    @Override
-    public final Shape createShape(ObjectType operations, Object sharedData) {
-        return createShape(operations, sharedData, 0);
-    }
-
-    @Override
-    public final Shape createShape(ObjectType operations) {
-        return createShape(operations, null);
-    }
-
-    public boolean isAllowedIntToDouble() {
-        return (allowedImplicitCasts & INT_TO_DOUBLE_FLAG) != 0;
-    }
-
-    public boolean isAllowedIntToLong() {
-        return (allowedImplicitCasts & INT_TO_LONG_FLAG) != 0;
-    }
-
-    protected abstract boolean hasObjectExtensionArray();
-
-    protected abstract boolean hasPrimitiveExtensionArray();
-
-    protected abstract int getObjectFieldCount();
-
-    protected abstract int getPrimitiveFieldCount();
-
-    protected abstract Location getObjectArrayLocation();
-
-    protected abstract Location getPrimitiveArrayLocation();
-
-    protected abstract int objectFieldIndex(Location location);
-
-    protected boolean isLocationAssignableFrom(Location destination, Location source) {
-        LayoutImpl layout = this;
-        if (destination.isFinal()) {
-            // allowed Final<X>Location => Final<X>Location
-            // allowed FinalIntLocation => Final{Int,Double}Location
-            // allowed: Final{Int,Double,TypedObject}Location => FinalObjectLocation
-            if (!source.isFinal()) {
-                return false;
-            }
-        }
-
-        if (destination instanceof IntLocation) {
-            return (source instanceof IntLocation);
-        } else if (destination instanceof DoubleLocation) {
-            return (source instanceof DoubleLocation || (layout.isAllowedIntToDouble() && source instanceof IntLocation));
-        } else if (destination instanceof LongLocation) {
-            return (source instanceof LongLocation || (layout.isAllowedIntToLong() && source instanceof IntLocation));
-        } else if (destination instanceof BooleanLocation) {
-            return (source instanceof BooleanLocation);
-        } else if (destination instanceof TypedObjectLocation) {
-            return source instanceof TypedObjectLocation && ((TypedObjectLocation<?>) destination).getType().isAssignableFrom(((TypedObjectLocation<?>) source).getType());
-        } else if (destination instanceof ValueLocation) {
-            return false;
-        } else {
-            assert destination instanceof ObjectLocation || destination instanceof DualLocation;
-            return true;
-        }
-    }
-
-    protected Location existingLocationForValue(Object value, Location oldLocation, Shape oldShape) {
-        assert oldShape.getLayout() == this;
-        Location newLocation;
-        if (oldLocation instanceof IntLocation && value instanceof Integer) {
-            newLocation = oldLocation;
-        } else if (oldLocation instanceof DoubleLocation && (value instanceof Double || this.isAllowedIntToDouble() && value instanceof Integer)) {
-            newLocation = oldLocation;
-        } else if (oldLocation instanceof LongLocation && (value instanceof Long || this.isAllowedIntToLong() && value instanceof Long)) {
-            newLocation = oldLocation;
-        } else if (oldLocation instanceof DeclaredLocation) {
-            return oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull));
-        } else if (oldLocation instanceof ConstantLocation) {
-            return LocationImpl.valueEquals(oldLocation.get(null, false), value) ? oldLocation : new Locations.ConstantLocation(value);
-        } else if (oldLocation instanceof TypedObjectLocation && !((TypedObjectLocation<?>) oldLocation).getType().isAssignableFrom(value.getClass())) {
-            newLocation = (((TypedObjectLocation<?>) oldLocation).toUntypedLocation());
-        } else if (oldLocation instanceof DualLocation) {
-            if (oldLocation.canStore(value)) {
-                newLocation = oldLocation;
-            } else {
-                newLocation = ((BaseAllocator) oldShape.allocator()).locationForValueUpcast(value, oldLocation);
-            }
-        } else if (oldLocation instanceof ObjectLocation) {
-            newLocation = oldLocation;
-        } else {
-            return oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.NonNull));
-        }
-        if (newLocation instanceof EffectivelyFinalLocation) {
-            newLocation = ((EffectivelyFinalLocation<?>) newLocation).toNonFinalLocation();
-        }
-        return newLocation;
-    }
-
-    /**
-     * Is this property an upcast of the other property?
-     *
-     * @param other the property being compared to
-     * @return true if this is a upcast of the other property, false otherwise
-     */
-    public boolean isPropertyUpcastOf(Property thiz, Property other) {
-        if (thiz.getLocation() != null && other.getLocation() != null && other.getKey().equals(thiz.getKey()) && other.getFlags() == thiz.getFlags()) {
-            if (isLocationAssignableFrom(thiz.getLocation(), other.getLocation())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public abstract Allocator createAllocator();
-
-    public LayoutStrategy getStrategy() {
-        return strategy;
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
-
-public interface LayoutStrategy {
-    boolean updateShape(DynamicObject object);
-
-    Shape returnCached(Shape newShape);
-
-    Shape ensureSpace(Shape shape, Location location);
-
-    boolean isAutoExtArray();
-
-    Property generalizeProperty(DynamicObject object, Property oldProperty, Object value);
-
-    Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape oldShape, Shape newShape);
-
-    BaseAllocator createAllocator(Layout shape);
-
-    BaseAllocator createAllocator(Shape shape);
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import com.oracle.truffle.api.object.*;
-
-public abstract class LocationImpl extends Location {
-
-    public interface EffectivelyFinalLocation<T extends Location> {
-        T toNonFinalLocation();
-    }
-
-    public interface TypedObjectLocation<T extends Location & ObjectLocation> extends ObjectLocation {
-        T toUntypedLocation();
-    }
-
-    public interface InternalLongLocation extends LongLocation {
-        void setLongInternal(DynamicObject store, long value);
-    }
-
-    public interface LocationVisitor {
-        void visitObjectField(int index, int count);
-
-        void visitObjectArray(int index, int count);
-
-        void visitPrimitiveField(int index, int count);
-
-        void visitPrimitiveArray(int index, int count);
-    }
-
-    @Override
-    public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
-        setInternal(store, value);
-    }
-
-    @Override
-    protected final Object getInternal(DynamicObject store) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    protected abstract void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException;
-
-    @Override
-    public final boolean canSet(DynamicObject store, Object value) {
-        return canStore(value) && canStoreFinal(store, value);
-    }
-
-    @Override
-    public boolean canStore(Object value) {
-        return true;
-    }
-
-    @SuppressWarnings("unused")
-    protected boolean canStoreFinal(DynamicObject store, Object value) {
-        return true;
-    }
-
-    @Override
-    public boolean isFinal() {
-        return false;
-    }
-
-    @Override
-    public boolean isConstant() {
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (isFinal() ? 1231 : 1237);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        Location other = (Location) obj;
-        if (isFinal() != other.isFinal()) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        String finalString = isFinal() ? "f" : "";
-        String typeString = this instanceof IntLocation ? "i" : (this instanceof DoubleLocation ? "d" : (this instanceof BooleanLocation ? "b"
-                        : (this instanceof TypedLocation ? ((TypedLocation) this).getType().getSimpleName() : "o")));
-        return finalString + typeString + getWhereString();
-    }
-
-    protected String getWhereString() {
-        return "";
-    }
-
-    /**
-     * Get the number of object array elements this location requires.
-     */
-    public int objectArrayCount() {
-        return 0;
-    }
-
-    /**
-     * Get the number of in-object {@link Object} fields this location requires.
-     */
-    public int objectFieldCount() {
-        return 0;
-    }
-
-    /**
-     * Get the number of in-object primitive fields this location requires.
-     */
-    public int primitiveFieldCount() {
-        return 0;
-    }
-
-    /**
-     * Get the number of primitive array elements this location requires.
-     */
-    public int primitiveArrayCount() {
-        return 0;
-    }
-
-    /**
-     * Accept a visitor for location allocation for this and every nested location.
-     *
-     * @param locationVisitor visitor to be notified of every allocated slot in use by this location
-     */
-    public abstract void accept(LocationVisitor locationVisitor);
-
-    /**
-     * Boxed values need to be compared by value not by reference.
-     *
-     * The first parameter should be the one with the more precise type information.
-     *
-     * For sets to final locations, otherValue.equals(thisValue) seems more beneficial, since we
-     * usually know more about the value to be set.
-     */
-    public static boolean valueEquals(Object val1, Object val2) {
-        return val1 == val2 || (val1 != null && val1.equals(val2));
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.object.*;
-
-/**
- * Property location.
- *
- * @see Location
- * @see Shape
- * @see Property
- * @see DynamicObject
- */
-public abstract class Locations {
-    public abstract static class ValueLocation extends LocationImpl {
-
-        private final Object value;
-
-        public ValueLocation(Object value) {
-            assert !(value instanceof Location);
-            this.value = value;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + ((value == null) ? 0 : 0 /* value.hashCode() */);
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!super.equals(obj)) {
-                return false;
-            }
-            ValueLocation other = (ValueLocation) obj;
-            if (value == null) {
-                if (other.value != null) {
-                    return false;
-                }
-            } else if (!value.equals(other.value)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public final Object get(DynamicObject store, boolean condition) {
-            return value;
-        }
-
-        @Override
-        public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
-            if (!canStoreFinal(store, value)) {
-                throw finalLocation();
-            }
-        }
-
-        @Override
-        protected boolean canStoreFinal(DynamicObject store, Object val) {
-            return valueEquals(this.value, val);
-        }
-
-        @Override
-        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (!canStoreFinal(store, value)) {
-                CompilerDirectives.transferToInterpreter();
-                throw new UnsupportedOperationException();
-            }
-        }
-
-        @Override
-        public String toString() {
-            return "=" + String.valueOf(value);
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-        }
-    }
-
-    public static final class ConstantLocation extends ValueLocation {
-
-        public ConstantLocation(Object value) {
-            super(value);
-        }
-
-        @Override
-        public boolean isConstant() {
-            return true;
-        }
-    }
-
-    public static final class DeclaredLocation extends ValueLocation {
-
-        public DeclaredLocation(Object value) {
-            super(value);
-        }
-    }
-
-    public static class DualLocation extends LocationImpl implements TypedLocation {
-        protected final InternalLongLocation primitiveLocation;
-        protected final ObjectLocation objectLocation;
-        protected final LayoutImpl layout;
-        private final Class<?> type;
-
-        public DualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, LayoutImpl layout) {
-            this(primitiveLocation, objectLocation, layout, null);
-        }
-
-        public DualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, LayoutImpl layout, Class<?> type) {
-            this.primitiveLocation = primitiveLocation;
-            this.objectLocation = objectLocation;
-            this.layout = layout;
-            this.type = type;
-        }
-
-        @Override
-        public Object get(DynamicObject store, boolean condition) {
-            if (type == Object.class) {
-                return objectLocation.get(store, condition);
-            } else {
-                long rawValue = primitiveLocation.getLong(store, condition);
-                if (type == int.class) {
-                    return (int) rawValue;
-                } else if (type == long.class) {
-                    return rawValue;
-                } else if (type == double.class) {
-                    return Double.longBitsToDouble(rawValue);
-                } else if (type == boolean.class) {
-                    return rawValue != 0;
-                } else {
-                    CompilerDirectives.transferToInterpreter();
-                    throw new IllegalStateException();
-                }
-            }
-        }
-
-        @Override
-        public void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (type == Object.class) {
-                ((LocationImpl) objectLocation).setInternal(store, value);
-            } else {
-                long rawValue;
-                if (type == int.class && value instanceof Integer) {
-                    rawValue = (int) value;
-                } else if (type == long.class && value instanceof Long) {
-                    rawValue = (long) value;
-                } else if (type == long.class && layout.isAllowedIntToLong() && value instanceof Integer) {
-                    rawValue = (int) value;
-                } else if (type == double.class && value instanceof Double) {
-                    rawValue = Double.doubleToRawLongBits((double) value);
-                } else if (type == double.class && layout.isAllowedIntToDouble() && value instanceof Integer) {
-                    rawValue = Double.doubleToRawLongBits((int) value);
-                } else if (type == boolean.class && value instanceof Boolean) {
-                    rawValue = (boolean) value ? 1 : 0;
-                } else {
-                    throw incompatibleLocation();
-                }
-
-                primitiveLocation.setLongInternal(store, rawValue);
-            }
-        }
-
-        @Override
-        public int primitiveFieldCount() {
-            return ((LocationImpl) primitiveLocation).primitiveFieldCount();
-        }
-
-        @Override
-        public int primitiveArrayCount() {
-            return ((LocationImpl) primitiveLocation).primitiveArrayCount();
-        }
-
-        @Override
-        public int objectFieldCount() {
-            return ((LocationImpl) objectLocation).objectFieldCount();
-        }
-
-        @Override
-        public int objectArrayCount() {
-            return ((LocationImpl) objectLocation).objectArrayCount();
-        }
-
-        @Override
-        public final void accept(LocationVisitor locationVisitor) {
-            ((LocationImpl) primitiveLocation).accept(locationVisitor);
-            ((LocationImpl) objectLocation).accept(locationVisitor);
-        }
-
-        @Override
-        public String toString() {
-            return objectLocation.toString() + "," + primitiveLocation.toString() + "," + type;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!super.equals(obj)) {
-                return false;
-            }
-            DualLocation other = (DualLocation) obj;
-            return getObjectLocation().equals(other.getObjectLocation()) && primitiveLocation.equals(other.primitiveLocation) && layout.equals(other.layout) && Objects.equals(type, other.type);
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + (getObjectLocation() == null ? 0 : getObjectLocation().hashCode());
-            result = prime * result + (primitiveLocation == null ? 0 : primitiveLocation.hashCode());
-            result = prime * result + (type == null ? 0 : type.hashCode());
-            return result;
-        }
-
-        public ObjectLocation getObjectLocation() {
-            return objectLocation;
-        }
-
-        public DualLocation changeType(Class<?> newType) {
-            return new DualLocation(primitiveLocation, objectLocation, layout, newType);
-        }
-
-        public Class<?> getType() {
-            return type;
-        }
-
-        public boolean isNonNull() {
-            return false;
-        }
-
-        @Override
-        public boolean canStore(Object value) {
-            if (type == null) {
-                return false;
-            } else if (type == int.class) {
-                return value instanceof Integer;
-            } else if (type == long.class) {
-                return value instanceof Long || (layout.isAllowedIntToLong() && value instanceof Integer);
-            } else if (type == double.class) {
-                return value instanceof Double || (layout.isAllowedIntToDouble() && value instanceof Integer);
-            } else if (type == boolean.class) {
-                return value instanceof Boolean;
-            } else if (type == Object.class) {
-                return true;
-            } else {
-                throw new IllegalStateException();
-            }
-        }
-    }
-
-    public static class DeclaredDualLocation extends DualLocation {
-        private final Object defaultValue;
-
-        public DeclaredDualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, Object defaultValue, LayoutImpl layout) {
-            super(primitiveLocation, objectLocation, layout);
-            this.defaultValue = defaultValue;
-        }
-
-        @Override
-        public Object get(DynamicObject store, boolean condition) {
-            return defaultValue;
-        }
-
-        @Override
-        public void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
-            if (valueEquals(defaultValue, value)) {
-                return;
-            } else {
-                throw incompatibleLocation();
-            }
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return super.equals(obj) && Objects.equals(defaultValue, ((DeclaredDualLocation) obj).defaultValue);
-        }
-
-        @Override
-        public int hashCode() {
-            return super.hashCode();
-        }
-
-        @Override
-        public DualLocation changeType(Class<?> newType) {
-            return new DualLocation(primitiveLocation, objectLocation, layout, newType);
-        }
-
-        @Override
-        public boolean canStore(Object value) {
-            return valueEquals(defaultValue, value);
-        }
-
-        @Override
-        public String toString() {
-            return objectLocation.toString() + "," + primitiveLocation.toString() + ",unset";
-        }
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import static com.oracle.truffle.api.object.Layout.*;
-
-public class ObjectStorageOptions {
-    // Shape configuration
-    /** Primitive location switch. */
-    public static boolean PrimitiveLocations = booleanOption(OPTION_PREFIX + "PrimitiveLocations", true);
-    public static boolean IntegerLocations = booleanOption(OPTION_PREFIX + "IntegerLocations", true);
-    public static boolean DoubleLocations = booleanOption(OPTION_PREFIX + "DoubleLocations", true);
-    public static boolean LongLocations = booleanOption(OPTION_PREFIX + "LongLocations", true);
-    public static boolean BooleanLocations = booleanOption(OPTION_PREFIX + "BooleanLocations", true);
-    public static boolean TypedObjectLocations = booleanOption(OPTION_PREFIX + "TypedObjectLocations", true);
-
-    /** Allocation of in-object fields. */
-    public static boolean InObjectFields = booleanOption(OPTION_PREFIX + "InObjectFields", true);
-
-    // Debug options (should be final)
-    public static final boolean TraceReshape = booleanOption(OPTION_PREFIX + "TraceReshape", false);
-    public static final boolean DumpShapes = booleanOption(OPTION_PREFIX + "DumpShapes", false);
-
-    public static final boolean Profile = booleanOption(OPTION_PREFIX + "Profile", false);
-    public static final int ProfileTopResults = Integer.getInteger(OPTION_PREFIX + "ProfileTopResults", -1);
-
-    public static boolean booleanOption(String name, boolean defaultValue) {
-        String value = System.getProperty(name);
-        return value == null ? defaultValue : value.equalsIgnoreCase("true");
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.Locations.DeclaredLocation;
-
-/**
- * Property objects represent the mapping between property identifiers (keys) and storage locations.
- * Optionally, properties may have metadata attached to them.
- */
-public class PropertyImpl extends Property {
-    private final Object key;
-    private final Location location;
-    private final int flags;
-    private final boolean shadow;
-    private final boolean relocatable;
-
-    /**
-     * Generic, usual-case constructor for properties storing at least a name.
-     *
-     * @param key the name of the property
-     * @param location the storage location used to access the property
-     * @param flags property flags (optional)
-     */
-    protected PropertyImpl(Object key, Location location, int flags, boolean shadow, boolean relocatable) {
-        this.key = Objects.requireNonNull(key);
-        this.location = Objects.requireNonNull(location);
-        this.flags = flags;
-        this.shadow = shadow;
-        this.relocatable = relocatable;
-    }
-
-    public PropertyImpl(Object name, Location location, int flags) {
-        this(name, location, flags, false, true);
-    }
-
-    @Override
-    public final Object getKey() {
-        return key;
-    }
-
-    @Override
-    public int getFlags() {
-        return flags;
-    }
-
-    @Override
-    public Property relocate(Location newLocation) {
-        if (!getLocation().equals(newLocation) && relocatable) {
-            return construct(key, newLocation, flags);
-        }
-        return this;
-    }
-
-    @Override
-    public final Object get(DynamicObject store, Shape shape) {
-        return getLocation().get(store, shape);
-    }
-
-    @Override
-    public final Object get(DynamicObject store, boolean condition) {
-        return getLocation().get(store, condition);
-    }
-
-    @Override
-    public final void setInternal(DynamicObject store, Object value) {
-        try {
-            ((LocationImpl) getLocation()).setInternal(store, value);
-        } catch (IncompatibleLocationException e) {
-            throw new IllegalStateException();
-        }
-    }
-
-    @Override
-    public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
-        assert shape == null || store.getShape() == shape : "wrong shape";
-        getLocation().set(store, value, shape);
-    }
-
-    @Override
-    public final void setSafe(DynamicObject store, Object value, Shape shape) {
-        assert shape == null || store.getShape() == shape : "wrong shape";
-        try {
-            getLocation().set(store, value, shape);
-        } catch (IncompatibleLocationException | FinalLocationException ex) {
-            throw new IllegalStateException();
-        }
-    }
-
-    @Override
-    public final void setGeneric(DynamicObject store, Object value, Shape shape) {
-        assert shape == null || store.getShape() == shape : "wrong shape";
-        try {
-            set(store, value, shape);
-        } catch (IncompatibleLocationException | FinalLocationException ex) {
-            setSlowCase(store, value);
-        }
-    }
-
-    @Override
-    public final void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException {
-        assert store.getShape() == oldShape : "wrong shape";
-        assert newShape.isValid();
-        assert getLocation() != null;
-        getLocation().set(store, value, oldShape, newShape);
-    }
-
-    @Override
-    public final void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
-        assert store.getShape() == oldShape : "wrong old shape";
-        assert newShape.isValid();
-        assert getLocation() != null;
-        try {
-            getLocation().set(store, value, oldShape, newShape);
-        } catch (IncompatibleLocationException ex) {
-            throw new IllegalStateException();
-        }
-    }
-
-    @Override
-    public final void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
-        assert store.getShape() == oldShape : "wrong old shape";
-        assert newShape.isValid();
-        assert getLocation() != null;
-        try {
-            getLocation().set(store, value, oldShape, newShape);
-        } catch (IncompatibleLocationException ex) {
-            setWithShapeSlowCase(store, value, oldShape, newShape);
-        }
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-
-        PropertyImpl other = (PropertyImpl) obj;
-        return key.equals(other.key) && location.equals(other.location) && flags == other.flags && shadow == other.shadow && relocatable == other.relocatable;
-    }
-
-    @Override
-    public boolean isSame(Property obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-
-        PropertyImpl other = (PropertyImpl) obj;
-        return key.equals(other.key) && flags == other.flags;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + getClass().hashCode();
-        result = prime * result + key.hashCode();
-        result = prime * result + location.hashCode();
-        result = prime * result + flags;
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "\"" + key + "\"" + ":" + location;
-    }
-
-    @Override
-    public final Location getLocation() {
-        return location;
-    }
-
-    private void setSlowCase(DynamicObject store, Object value) {
-        if (getLocation() instanceof DeclaredLocation) {
-            setDeclaredLocation(store, value);
-        } else {
-            generalize(store, value);
-        }
-    }
-
-    private void setDeclaredLocation(DynamicObject store, Object value) {
-        store.updateShape();
-        Shape oldShape = store.getShape();
-        Shape newShape = oldShape.addProperty(this.relocateShadow(oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull))));
-        store.updateShape();
-        newShape.getLastProperty().setGeneric(store, value, oldShape, newShape);
-    }
-
-    private Property generalize(DynamicObject store, Object value) {
-        return ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value);
-    }
-
-    private void setWithShapeSlowCase(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
-        ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value, oldShape, newShape);
-    }
-
-    @Override
-    public final boolean isHidden() {
-        return key instanceof HiddenKey;
-    }
-
-    @Override
-    public final boolean isShadow() {
-        return shadow;
-    }
-
-    private Property relocateShadow(Location newLocation) {
-        assert !isShadow() && getLocation() instanceof DeclaredLocation && relocatable;
-        return new PropertyImpl(key, newLocation, flags, true, relocatable);
-    }
-
-    @SuppressWarnings("hiding")
-    protected Property construct(Object name, Location location, int flags) {
-        return new PropertyImpl(name, location, flags, shadow, relocatable);
-    }
-
-    @Override
-    public Property copyWithFlags(int newFlags) {
-        return construct(key, location, newFlags);
-    }
-
-    @Override
-    public Property copyWithRelocatable(boolean newRelocatable) {
-        if (this.relocatable != newRelocatable) {
-            return new PropertyImpl(key, location, flags, shadow, newRelocatable);
-        }
-        return this;
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-
-public final class PropertyMap implements Map<Object, Property> {
-    private final PropertyMap car;
-    private final Property cdr;
-    private final int size;
-
-    private static final PropertyMap EMPTY = new PropertyMap();
-
-    private PropertyMap() {
-        this.car = null;
-        this.cdr = null;
-        this.size = 0;
-    }
-
-    private PropertyMap(PropertyMap parent, Property added) {
-        this.car = Objects.requireNonNull(parent);
-        this.cdr = added;
-        this.size = parent.size + 1;
-    }
-
-    public static PropertyMap empty() {
-        return EMPTY;
-    }
-
-    public int size() {
-        return size;
-    }
-
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    public boolean containsKey(Object key) {
-        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
-            if (entry.getKey().equals(key)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean containsValue(Object value) {
-        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
-            if (entry.getValue().equals(value)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public Property get(Object key) {
-        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
-            if (entry.getKey().equals(key)) {
-                return entry.getValue();
-            }
-        }
-        return null;
-    }
-
-    public Property put(Object key, Property value) {
-        throw unmodifiableException();
-    }
-
-    public Property remove(Object key) {
-        throw unmodifiableException();
-    }
-
-    public void putAll(Map<? extends Object, ? extends Property> m) {
-        throw unmodifiableException();
-    }
-
-    public void clear() {
-        throw unmodifiableException();
-    }
-
-    public Set<Object> keySet() {
-        return new AbstractSet<Object>() {
-            @Override
-            public Iterator<Object> iterator() {
-                Object[] keys = new Object[size()];
-                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
-                for (int pos = size() - 1; pos >= 0; pos--) {
-                    keys[pos] = iterator.next().getKey();
-                }
-                return Arrays.asList(keys).iterator();
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    public Collection<Property> values() {
-        return new AbstractSet<Property>() {
-            @Override
-            public Iterator<Property> iterator() {
-                Property[] values = new Property[size()];
-                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
-                for (int pos = size() - 1; pos >= 0; pos--) {
-                    values[pos] = iterator.next().getValue();
-                }
-                return Arrays.asList(values).iterator();
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    public Set<Map.Entry<Object, Property>> entrySet() {
-        return new AbstractSet<Map.Entry<Object, Property>>() {
-            @Override
-            public Iterator<Map.Entry<Object, Property>> iterator() {
-                @SuppressWarnings("unchecked")
-                Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()];
-                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
-                for (int pos = size() - 1; pos >= 0; pos--) {
-                    entries[pos] = iterator.next();
-                }
-                return Arrays.asList(entries).iterator();
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    public Set<Map.Entry<Object, Property>> reverseOrderEntrySet() {
-        return new AbstractSet<Map.Entry<Object, Property>>() {
-            @Override
-            public Iterator<Map.Entry<Object, Property>> iterator() {
-                return new Iterator<Map.Entry<Object, Property>>() {
-                    PropertyMap current = PropertyMap.this;
-
-                    public Entry<Object, Property> next() {
-                        if (hasNext()) {
-                            try {
-                                return new MapEntryImpl(current.cdr);
-                            } finally {
-                                current = current.car;
-                            }
-                        } else {
-                            throw new NoSuchElementException();
-                        }
-                    }
-
-                    public boolean hasNext() {
-                        return current != empty();
-                    }
-
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    public Set<Object> reverseOrderKeys() {
-        return new AbstractSet<Object>() {
-            @Override
-            public Iterator<Object> iterator() {
-                return new Iterator<Object>() {
-                    PropertyMap current = PropertyMap.this;
-
-                    public Object next() {
-                        if (hasNext()) {
-                            try {
-                                return current.cdr.getKey();
-                            } finally {
-                                current = current.car;
-                            }
-                        } else {
-                            throw new NoSuchElementException();
-                        }
-                    }
-
-                    public boolean hasNext() {
-                        return current != empty();
-                    }
-
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    public Set<Property> reverseOrderValues() {
-        return new AbstractSet<Property>() {
-            @Override
-            public Iterator<Property> iterator() {
-                return new Iterator<Property>() {
-                    PropertyMap current = PropertyMap.this;
-
-                    public Property next() {
-                        if (hasNext()) {
-                            try {
-                                return current.cdr;
-                            } finally {
-                                current = current.car;
-                            }
-                        } else {
-                            throw new NoSuchElementException();
-                        }
-                    }
-
-                    public boolean hasNext() {
-                        return current != empty();
-                    }
-
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-                };
-            }
-
-            @Override
-            public int size() {
-                return PropertyMap.this.size();
-            }
-        };
-    }
-
-    private static final class MapEntryImpl implements Map.Entry<Object, Property> {
-        private final Property backingProperty;
-
-        public MapEntryImpl(Property backingProperty) {
-            this.backingProperty = backingProperty;
-        }
-
-        public Object getKey() {
-            return backingProperty.getKey();
-        }
-
-        public Property getValue() {
-            return backingProperty;
-        }
-
-        public Property setValue(Property value) {
-            throw unmodifiableException();
-        }
-    }
-
-    private static UnsupportedOperationException unmodifiableException() {
-        throw new UnsupportedOperationException("unmodifiable");
-    }
-
-    public PropertyMap putCopy(Property value) {
-        return new PropertyMap(this, value);
-    }
-
-    public PropertyMap removeCopy(Property value) {
-        Deque<Property> shelve = new ArrayDeque<>();
-        PropertyMap current = this;
-        while (!current.isEmpty()) {
-            if (current.getLastProperty().equals(value)) {
-                PropertyMap newMap = current.getParentMap();
-                for (Property property : shelve) {
-                    newMap = newMap.putCopy(property);
-                }
-                return newMap;
-            } else {
-                shelve.push(current.getLastProperty());
-                current = current.getParentMap();
-            }
-        }
-        return this;
-    }
-
-    public PropertyMap replaceCopy(Property oldValue, Property newValue) {
-        Deque<Property> shelve = new ArrayDeque<>();
-        PropertyMap current = this;
-        while (!current.isEmpty()) {
-            if (current.getLastProperty().equals(oldValue)) {
-                PropertyMap newMap = current.getParentMap();
-                newMap = newMap.putCopy(newValue);
-                for (Property property : shelve) {
-                    newMap = newMap.putCopy(property);
-                }
-                return newMap;
-            } else {
-                shelve.push(current.getLastProperty());
-                current = current.getParentMap();
-            }
-        }
-        return this;
-    }
-
-    public PropertyMap getOwningMap(Property value) {
-        PropertyMap current = this;
-        while (!current.isEmpty()) {
-            if (current.getLastProperty().equals(value)) {
-                return current;
-            }
-            current = current.getParentMap();
-        }
-        return null;
-    }
-
-    PropertyMap getParentMap() {
-        return car;
-    }
-
-    public Property getLastProperty() {
-        return cdr;
-    }
-
-    @Override
-    public String toString() {
-        return values().toString();
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1074 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.interop.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
-import com.oracle.truffle.object.LocationImpl.LocationVisitor;
-import com.oracle.truffle.object.Locations.ConstantLocation;
-import com.oracle.truffle.object.Locations.DeclaredDualLocation;
-import com.oracle.truffle.object.Locations.DeclaredLocation;
-import com.oracle.truffle.object.Locations.DualLocation;
-import com.oracle.truffle.object.Locations.ValueLocation;
-import com.oracle.truffle.object.Transition.AddPropertyTransition;
-import com.oracle.truffle.object.Transition.DirectReplacePropertyTransition;
-import com.oracle.truffle.object.Transition.ObjectTypeTransition;
-import com.oracle.truffle.object.Transition.PropertyTransition;
-import com.oracle.truffle.object.Transition.RemovePropertyTransition;
-import com.oracle.truffle.object.Transition.ReservePrimitiveArrayTransition;
-
-/**
- * Shape objects create a mapping of Property objects to indexes. The mapping of those indexes to an
- * actual store is not part of Shape's role, but JSObject's. Shapes are immutable; adding or
- * deleting a property yields a new Shape which links to the old one. This allows inline caching to
- * simply check the identity of an object's Shape to determine if the cache is valid. There is one
- * exception to this immutability, the transition map, but that is used simply to assure that an
- * identical series of property additions and deletions will yield the same Shape object.
- *
- * @see DynamicObject
- * @see Property
- * @see Locations
- */
-public abstract class ShapeImpl extends Shape {
-    private final int id;
-
-    protected final LayoutImpl layout;
-    protected final ObjectType objectType;
-    protected final ShapeImpl parent;
-    protected final PropertyMap propertyMap;
-
-    private final Object extraData;
-    private final Object sharedData;
-    private final ShapeImpl root;
-
-    protected final int objectArraySize;
-    protected final int objectArrayCapacity;
-    protected final int objectFieldSize;
-    protected final int primitiveFieldSize;
-    protected final int primitiveArraySize;
-    protected final int primitiveArrayCapacity;
-    protected final boolean hasPrimitiveArray;
-
-    protected final int depth;
-    protected final int propertyCount;
-
-    protected final Assumption validAssumption;
-    @CompilationFinal protected volatile Assumption leafAssumption;
-
-    /**
-     * Shape transition map; lazily initialized.
-     *
-     * @see #getTransitionMapForRead()
-     * @see #getTransitionMapForWrite()
-     */
-    private volatile Map<Transition, ShapeImpl> transitionMap;
-
-    private final Transition transitionFromParent;
-
-    /**
-     * Private constructor.
-     *
-     * @param parent predecessor shape
-     * @param transitionFromParent direct transition from parent shape
-     * @see #ShapeImpl(Layout, ShapeImpl, ObjectType, Object, PropertyMap, Transition,
-     *      BaseAllocator, int)
-     */
-    private ShapeImpl(Layout layout, ShapeImpl parent, ObjectType objectType, Object sharedData, PropertyMap propertyMap, Transition transitionFromParent, int objectArraySize, int objectFieldSize,
-                    int primitiveFieldSize, int primitiveArraySize, boolean hasPrimitiveArray, int id) {
-        this.layout = (LayoutImpl) layout;
-        this.objectType = Objects.requireNonNull(objectType);
-        this.propertyMap = Objects.requireNonNull(propertyMap);
-        this.root = parent != null ? parent.getRoot() : this;
-        this.parent = parent;
-        this.transitionFromParent = transitionFromParent;
-        this.objectArraySize = objectArraySize;
-        this.objectArrayCapacity = capacityFromSize(objectArraySize);
-        this.objectFieldSize = objectFieldSize;
-        this.primitiveFieldSize = primitiveFieldSize;
-        this.primitiveArraySize = primitiveArraySize;
-        this.primitiveArrayCapacity = capacityFromSize(primitiveArraySize);
-        this.hasPrimitiveArray = hasPrimitiveArray;
-
-        if (parent != null) {
-            this.propertyCount = makePropertyCount(parent, propertyMap);
-            this.depth = parent.depth + 1;
-        } else {
-            this.propertyCount = 0;
-            this.depth = 0;
-        }
-
-        this.validAssumption = createValidAssumption();
-
-        this.id = id;
-        shapeCount.inc();
-
-        this.sharedData = sharedData;
-        this.extraData = objectType.createShapeData(this);
-
-        debugRegisterShape(this);
-    }
-
-    protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
-        this(layout, parent, operations, sharedData, propertyMap, transition, ((BaseAllocator) allocator).objectArraySize, ((BaseAllocator) allocator).objectFieldSize,
-                        ((BaseAllocator) allocator).primitiveFieldSize, ((BaseAllocator) allocator).primitiveArraySize, ((BaseAllocator) allocator).hasPrimitiveArray, id);
-    }
-
-    @SuppressWarnings("hiding")
-    protected abstract ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Transition transition, Allocator allocator, int id);
-
-    protected ShapeImpl(Layout layout, ObjectType operations, Object sharedData, int id) {
-        this(layout, null, operations, sharedData, PropertyMap.empty(), null, layout.createAllocator(), id);
-    }
-
-    private static int makePropertyCount(ShapeImpl parent, PropertyMap propertyMap) {
-        return parent.propertyCount + ((propertyMap.size() > parent.propertyMap.size() && !propertyMap.getLastProperty().isHidden() && !propertyMap.getLastProperty().isShadow()) ? 1 : 0);
-    }
-
-    @Override
-    public final Property getLastProperty() {
-        return propertyMap.getLastProperty();
-    }
-
-    @Override
-    public final int getId() {
-        return this.id;
-    }
-
-    /**
-     * Calculate array size for the given number of elements.
-     */
-    private static int capacityFromSize(int size) {
-        if (size == 0) {
-            return 0;
-        } else if (size < 4) {
-            return 4;
-        } else if (size < 32) {
-            return ((size + 7) / 8) * 8;
-        } else {
-            return ((size + 15) / 16) * 16;
-        }
-    }
-
-    @Override
-    public final int getObjectArraySize() {
-        return objectArraySize;
-    }
-
-    @Override
-    public final int getObjectFieldSize() {
-        return objectFieldSize;
-    }
-
-    @Override
-    public final int getPrimitiveFieldSize() {
-        return primitiveFieldSize;
-    }
-
-    @Override
-    public final int getObjectArrayCapacity() {
-        return objectArrayCapacity;
-    }
-
-    @Override
-    public final int getPrimitiveArrayCapacity() {
-        return primitiveArrayCapacity;
-    }
-
-    @Override
-    public final int getPrimitiveArraySize() {
-        return primitiveArraySize;
-    }
-
-    @Override
-    public final boolean hasPrimitiveArray() {
-        return hasPrimitiveArray;
-    }
-
-    /**
-     * Get the (parent) shape that holds the given property.
-     */
-    public final ShapeImpl getShapeFromProperty(Object propertyName) {
-        ShapeImpl current = this;
-        while (current != getRoot()) {
-            if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().getKey().equals(propertyName)) {
-                return current;
-            }
-            current = current.getParent();
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the (parent) shape that holds the given property.
-     */
-    public final ShapeImpl getShapeFromProperty(Property prop) {
-        ShapeImpl current = this;
-        while (current != getRoot()) {
-            if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().equals(prop)) {
-                return current;
-            }
-            current = current.parent;
-        }
-
-        return null;
-    }
-
-    /**
-     * Get a property entry by string name.
-     *
-     * @param key the name to look up
-     * @return a Property object, or null if not found
-     */
-    @Override
-    @TruffleBoundary
-    public Property getProperty(Object key) {
-        return propertyMap.get(key);
-    }
-
-    protected final void addDirectTransition(Transition transition, ShapeImpl next) {
-        assert next.getParent() == this && transition.isDirect();
-        addTransitionInternal(transition, next);
-    }
-
-    public final void addIndirectTransition(Transition transition, ShapeImpl next) {
-        assert next.getParent() != this && !transition.isDirect();
-        addTransitionInternal(transition, next);
-    }
-
-    private void addTransitionInternal(Transition transition, ShapeImpl next) {
-        getTransitionMapForWrite().put(transition, next);
-    }
-
-    public final Map<Transition, ShapeImpl> getTransitionMapForRead() {
-        return transitionMap != null ? transitionMap : Collections.<Transition, ShapeImpl> emptyMap();
-    }
-
-    private Map<Transition, ShapeImpl> getTransitionMapForWrite() {
-        if (transitionMap != null) {
-            return transitionMap;
-        } else {
-            synchronized (getMutex()) {
-                if (transitionMap != null) {
-                    return transitionMap;
-                }
-                invalidateLeafAssumption();
-                return transitionMap = new ConcurrentHashMap<>();
-            }
-        }
-    }
-
-    public final PropertyMap getPropertyMap() {
-        return propertyMap;
-    }
-
-    protected final ShapeImpl queryTransition(Transition transition) {
-        ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition);
-        if (cachedShape != null) { // Shape already exists?
-            shapeCacheHitCount.inc();
-            return (ShapeImpl) layout.getStrategy().returnCached(cachedShape);
-        }
-        shapeCacheMissCount.inc();
-
-        return null;
-    }
-
-    /**
-     * Add a new property in the map, yielding a new or cached Shape object.
-     *
-     * @param property the property to add
-     * @return the new Shape
-     */
-    @TruffleBoundary
-    @Override
-    public ShapeImpl addProperty(Property property) {
-        assert isValid();
-        onPropertyTransition(property);
-        return addPropertyInternal(property);
-    }
-
-    private void onPropertyTransition(Property property) {
-        if (sharedData instanceof ShapeListener) {
-            ((ShapeListener) sharedData).onPropertyTransition(property.getKey());
-        }
-    }
-
-    /**
-     * Add a new property in the map, yielding a new or cached Shape object.
-     *
-     * In contrast to {@link ShapeImpl#addProperty(Property)}, this method does not care about
-     * obsolete shapes.
-     *
-     * @see #addProperty(Property)
-     */
-    private ShapeImpl addPropertyInternal(Property prop) {
-        CompilerAsserts.neverPartOfCompilation();
-        assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property " + prop.getKey();
-
-        AddPropertyTransition addTransition = new AddPropertyTransition(prop);
-        ShapeImpl cachedShape = queryTransition(addTransition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-
-        ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, prop.getLocation());
-
-        ShapeImpl newShape = makeShapeWithAddedProperty(oldShape, addTransition);
-        oldShape.addDirectTransition(addTransition, newShape);
-        return newShape;
-    }
-
-    protected ShapeImpl cloneRoot(ShapeImpl from, Object newSharedData) {
-        return createShape(from.layout, newSharedData, null, from.objectType, from.propertyMap, null, from.allocator(), from.id);
-    }
-
-    /**
-     * Create a separate clone of a shape.
-     *
-     * @param newParent the cloned parent shape
-     */
-    protected final ShapeImpl cloneOnto(ShapeImpl newParent) {
-        ShapeImpl from = this;
-        ShapeImpl newShape = createShape(newParent.layout, newParent.sharedData, newParent, from.objectType, from.propertyMap, from.transitionFromParent, from.allocator(), newParent.id);
-
-        shapeCloneCount.inc();
-
-        // (aw) need to have this transition for obsolescence
-        newParent.addDirectTransition(from.transitionFromParent, newShape);
-        return newShape;
-    }
-
-    public final Transition getTransitionFromParent() {
-        return transitionFromParent;
-    }
-
-    /**
-     * Create a new shape that adds a property to the parent shape.
-     */
-    private static ShapeImpl makeShapeWithAddedProperty(ShapeImpl parent, AddPropertyTransition addTransition) {
-        Property addend = addTransition.getProperty();
-        BaseAllocator allocator = parent.allocator().addLocation(addend.getLocation());
-
-        PropertyMap newPropertyMap = parent.propertyMap.putCopy(addend);
-
-        ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, newPropertyMap, addTransition, allocator, parent.id);
-        assert ((LocationImpl) addend.getLocation()).primitiveArrayCount() == 0 || newShape.hasPrimitiveArray;
-        assert newShape.depth == allocator.depth;
-        return newShape;
-    }
-
-    /**
-     * Create a new shape that reserves the primitive extension array field.
-     */
-    private static ShapeImpl makeShapeWithPrimitiveExtensionArray(ShapeImpl parent, Transition transition) {
-        assert parent.getLayout().hasPrimitiveExtensionArray();
-        assert !parent.hasPrimitiveArray();
-        BaseAllocator allocator = parent.allocator().addLocation(parent.getLayout().getPrimitiveArrayLocation());
-        ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, parent.propertyMap, transition, allocator, parent.id);
-        assert newShape.hasPrimitiveArray();
-        assert newShape.depth == allocator.depth;
-        return newShape;
-    }
-
-    private ShapeImpl addPrimitiveExtensionArray() {
-        assert layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray();
-        Transition transition = new ReservePrimitiveArrayTransition();
-        ShapeImpl cachedShape = queryTransition(transition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-
-        ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, layout.getPrimitiveArrayLocation());
-        ShapeImpl newShape = makeShapeWithPrimitiveExtensionArray(oldShape, transition);
-        oldShape.addDirectTransition(transition, newShape);
-        return newShape;
-    }
-
-    /**
-     * Are these two shapes related, i.e. do they have the same root?
-     *
-     * @param other Shape to compare to
-     * @return true if one shape is an upcast of the other, or the Shapes are equal
-     */
-    @Override
-    public boolean isRelated(Shape other) {
-        if (this == other) {
-            return true;
-        }
-        if (this.getRoot() == getRoot()) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Get a list of all properties that this Shape stores.
-     *
-     * @return list of properties
-     */
-    @TruffleBoundary
-    @Override
-    public final List<Property> getPropertyList(Pred<Property> filter) {
-        LinkedList<Property> props = new LinkedList<>();
-        next: for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
-            if (!currentProperty.isHidden() && filter.test(currentProperty)) {
-                if (currentProperty.getLocation() instanceof DeclaredLocation) {
-                    for (Iterator<Property> iter = props.iterator(); iter.hasNext();) {
-                        Property other = iter.next();
-                        if (other.isShadow() && other.getKey().equals(currentProperty.getKey())) {
-                            iter.remove();
-                            props.addFirst(other);
-                            continue next;
-                        }
-                    }
-                }
-                props.addFirst(currentProperty);
-            }
-        }
-        return props;
-    }
-
-    @Override
-    public final List<Property> getPropertyList() {
-        return getPropertyList(ALL);
-    }
-
-    /**
-     * Returns all (also hidden) Property objects in this shape.
-     *
-     * @param ascending desired order
-     */
-    @TruffleBoundary
-    @Override
-    public final List<Property> getPropertyListInternal(boolean ascending) {
-        LinkedList<Property> props = new LinkedList<>();
-        for (Property current : this.propertyMap.reverseOrderValues()) {
-            if (ascending) {
-                props.addFirst(current);
-            } else {
-                props.add(current);
-            }
-        }
-        return props;
-    }
-
-    /**
-     * Get a list of all (visible) property names in insertion order.
-     *
-     * @return list of property names
-     */
-    @TruffleBoundary
-    @Override
-    public final List<Object> getKeyList(Pred<Property> filter) {
-        LinkedList<Object> keys = new LinkedList<>();
-        for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
-            if (!currentProperty.isHidden() && filter.test(currentProperty) && !currentProperty.isShadow()) {
-                keys.addFirst(currentProperty.getKey());
-            }
-        }
-        return keys;
-    }
-
-    @Override
-    public final List<Object> getKeyList() {
-        return getKeyList(ALL);
-    }
-
-    @Override
-    public Iterable<Object> getKeys() {
-        return getKeyList();
-    }
-
-    @Override
-    public final boolean isValid() {
-        return getValidAssumption().isValid();
-    }
-
-    @Override
-    public final Assumption getValidAssumption() {
-        return validAssumption;
-    }
-
-    private static Assumption createValidAssumption() {
-        return Truffle.getRuntime().createAssumption("valid shape");
-    }
-
-    public final void invalidateValidAssumption() {
-        getValidAssumption().invalidate();
-    }
-
-    @Override
-    public final boolean isLeaf() {
-        return leafAssumption == null || leafAssumption.isValid();
-    }
-
-    @Override
-    public final Assumption getLeafAssumption() {
-        if (leafAssumption == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            synchronized (getMutex()) {
-                if (leafAssumption == null) {
-                    leafAssumption = isLeafHelper() ? createLeafAssumption() : NeverValidAssumption.INSTANCE;
-                }
-            }
-        }
-        return leafAssumption;
-    }
-
-    private boolean isLeafHelper() {
-        return getTransitionMapForRead().isEmpty();
-    }
-
-    private static Assumption createLeafAssumption() {
-        return Truffle.getRuntime().createAssumption("leaf shape");
-    }
-
-    private void invalidateLeafAssumption() {
-        Assumption assumption = leafAssumption;
-        if (assumption != null) {
-            assumption.invalidate();
-        } else {
-            leafAssumption = NeverValidAssumption.INSTANCE;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return toStringLimit(Integer.MAX_VALUE);
-    }
-
-    @TruffleBoundary
-    public String toStringLimit(int limit) {
-        StringBuilder sb = new StringBuilder();
-        sb.append('@');
-        sb.append(Integer.toHexString(hashCode()));
-        if (!isValid()) {
-            sb.append('!');
-        }
-
-        sb.append("{");
-        for (Iterator<Property> iterator = propertyMap.reverseOrderValues().iterator(); iterator.hasNext();) {
-            Property p = iterator.next();
-            sb.append(p);
-            if (iterator.hasNext()) {
-                sb.append(", ");
-            }
-            if (sb.length() >= limit) {
-                sb.append("...");
-                break;
-            }
-            sb.append("\n");
-        }
-        sb.append("}");
-
-        return sb.toString();
-    }
-
-    @Override
-    public final ShapeImpl getParent() {
-        return parent;
-    }
-
-    public final int getDepth() {
-        return depth;
-    }
-
-    @Override
-    public final boolean hasProperty(Object name) {
-        return getProperty(name) != null;
-    }
-
-    @TruffleBoundary
-    @Override
-    public final ShapeImpl removeProperty(Property prop) {
-        onPropertyTransition(prop);
-
-        RemovePropertyTransition transition = new RemovePropertyTransition(prop);
-        ShapeImpl cachedShape = queryTransition(transition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-
-        ShapeImpl shape = getShapeFromProperty(prop.getKey());
-        if (shape != null) {
-            List<Transition> transitionList = new ArrayList<>();
-            ShapeImpl current = this;
-            while (current != shape) {
-                if (!(current.getTransitionFromParent() instanceof Transition.DirectReplacePropertyTransition) ||
-                                !((Transition.DirectReplacePropertyTransition) current.getTransitionFromParent()).getPropertyBefore().getKey().equals(prop.getKey())) {
-                    transitionList.add(current.getTransitionFromParent());
-                }
-                current = current.parent;
-            }
-            ShapeImpl newShape = shape.parent;
-            for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) {
-                Transition previous = iterator.previous();
-                newShape = newShape.applyTransition(previous, true);
-            }
-
-            addIndirectTransition(transition, newShape);
-            return newShape;
-        } else {
-            return null;
-        }
-    }
-
-    @TruffleBoundary
-    @Override
-    public final ShapeImpl append(Property oldProperty) {
-        return addProperty(oldProperty.relocate(allocator().moveLocation(oldProperty.getLocation())));
-    }
-
-    public final ShapeImpl applyTransition(Transition transition, boolean append) {
-        if (transition instanceof AddPropertyTransition) {
-            return append ? append(((AddPropertyTransition) transition).getProperty()) : addProperty(((AddPropertyTransition) transition).getProperty());
-        } else if (transition instanceof ObjectTypeTransition) {
-            return changeType(((ObjectTypeTransition) transition).getObjectType());
-        } else if (transition instanceof ReservePrimitiveArrayTransition) {
-            return reservePrimitiveExtensionArray();
-        } else if (transition instanceof DirectReplacePropertyTransition) {
-            Property oldProperty = ((DirectReplacePropertyTransition) transition).getPropertyBefore();
-            Property newProperty = ((DirectReplacePropertyTransition) transition).getPropertyAfter();
-            if (append) {
-                assert oldProperty.getLocation() instanceof DualLocation && newProperty.getLocation() instanceof DualLocation;
-                oldProperty = getProperty(oldProperty.getKey());
-                newProperty = newProperty.relocate(((DualLocation) oldProperty.getLocation()).changeType(((DualLocation) newProperty.getLocation()).getType()));
-            }
-            return replaceProperty(oldProperty, newProperty);
-        } else {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    @Override
-    public final BaseAllocator allocator() {
-        return layout.getStrategy().createAllocator(this);
-    }
-
-    /**
-     * Duplicate shape exchanging existing property with new property.
-     */
-    @Override
-    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
-        return indirectReplaceProperty(oldProperty, newProperty);
-    }
-
-    protected final ShapeImpl indirectReplaceProperty(Property oldProperty, Property newProperty) {
-        assert oldProperty.getKey().equals(newProperty.getKey());
-
-        Transition replacePropertyTransition = new Transition.IndirectReplacePropertyTransition(oldProperty, newProperty);
-        ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-
-        ShapeImpl top = this;
-        List<Transition> transitionList = new ArrayList<>();
-        boolean found = false;
-        while (top != getRoot() && !found) {
-            Transition transition = top.getTransitionFromParent();
-            transitionList.add(transition);
-            if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) {
-                found = true;
-            }
-            top = top.parent;
-        }
-        ShapeImpl newShape = top;
-        for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) {
-            Transition transition = iterator.previous();
-            if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) {
-                newShape = newShape.addProperty(newProperty);
-            } else {
-                newShape = newShape.applyTransition(transition, false);
-            }
-        }
-
-        addIndirectTransition(replacePropertyTransition, newShape);
-        return newShape;
-    }
-
-    protected final ShapeImpl directReplaceProperty(Property oldProperty, Property newProperty) {
-        assert oldProperty.getKey().equals(newProperty.getKey());
-        onPropertyTransition(oldProperty);
-
-        Transition replacePropertyTransition = new Transition.DirectReplacePropertyTransition(oldProperty, newProperty);
-        ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-        PropertyMap newPropertyMap = this.getPropertyMap().replaceCopy(oldProperty, newProperty);
-        ShapeImpl newShape = createShape(getLayout(), getSharedData(), this, getObjectType(), newPropertyMap, replacePropertyTransition, allocator(), getId());
-
-        addDirectTransition(replacePropertyTransition, newShape);
-        return newShape;
-    }
-
-    /**
-     * Find lowest common ancestor of two related shapes.
-     */
-    public static ShapeImpl findCommonAncestor(ShapeImpl left, ShapeImpl right) {
-        if (!left.isRelated(right)) {
-            throw new IllegalArgumentException("shapes must have the same root");
-        } else if (left == right) {
-            return left;
-        }
-        int leftLength = left.depth;
-        int rightLength = right.depth;
-        ShapeImpl leftPtr = left;
-        ShapeImpl rightPtr = right;
-        while (leftLength > rightLength) {
-            leftPtr = leftPtr.parent;
-            leftLength--;
-        }
-        while (rightLength > leftLength) {
-            rightPtr = rightPtr.parent;
-            rightLength--;
-        }
-        while (leftPtr != rightPtr) {
-            leftPtr = leftPtr.parent;
-            rightPtr = rightPtr.parent;
-        }
-        return leftPtr;
-    }
-
-    @Override
-    public final int getPropertyCount() {
-        return propertyCount;
-    }
-
-    /**
-     * Find difference between two shapes.
-     *
-     * @see ObjectStorageOptions#TraceReshape
-     */
-    public static List<Property> diff(Shape oldShape, Shape newShape) {
-        List<Property> oldList = oldShape.getPropertyListInternal(false);
-        List<Property> newList = newShape.getPropertyListInternal(false);
-
-        List<Property> diff = new ArrayList<>(oldList);
-        diff.addAll(newList);
-        List<Property> intersection = new ArrayList<>(oldList);
-        intersection.retainAll(newList);
-        diff.removeAll(intersection);
-        return diff;
-    }
-
-    @Override
-    public ObjectType getObjectType() {
-        return objectType;
-    }
-
-    @Override
-    public ShapeImpl getRoot() {
-        return root;
-    }
-
-    @Override
-    public final boolean check(DynamicObject subject) {
-        return subject.getShape() == this;
-    }
-
-    @Override
-    public final LayoutImpl getLayout() {
-        return layout;
-    }
-
-    @Override
-    public final Object getData() {
-        return extraData;
-    }
-
-    @Override
-    public final Object getSharedData() {
-        return sharedData;
-    }
-
-    @TruffleBoundary
-    @Override
-    public final boolean hasTransitionWithKey(Object key) {
-        for (Transition transition : getTransitionMapForRead().keySet()) {
-            if (transition instanceof PropertyTransition) {
-                if (((PropertyTransition) transition).getProperty().getKey().equals(key)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Clone off a separate shape with new shared data.
-     */
-    @TruffleBoundary
-    @Override
-    public final ShapeImpl createSeparateShape(Object newSharedData) {
-        if (parent == null) {
-            return cloneRoot(this, newSharedData);
-        } else {
-            return this.cloneOnto(parent.createSeparateShape(newSharedData));
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public final ShapeImpl changeType(ObjectType newOps) {
-        ObjectTypeTransition transition = new ObjectTypeTransition(newOps);
-        ShapeImpl cachedShape = queryTransition(transition);
-        if (cachedShape != null) {
-            return cachedShape;
-        }
-
-        ShapeImpl newShape = createShape(layout, sharedData, this, newOps, propertyMap, transition, allocator(), id);
-        addDirectTransition(transition, newShape);
-        return newShape;
-    }
-
-    @Override
-    public final ShapeImpl reservePrimitiveExtensionArray() {
-        if (layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray()) {
-            return addPrimitiveExtensionArray();
-        }
-        return this;
-    }
-
-    @Override
-    public final Iterable<Property> getProperties() {
-        return getPropertyList();
-    }
-
-    @Override
-    public final DynamicObject newInstance() {
-        return layout.newInstance(this);
-    }
-
-    @Override
-    public final DynamicObjectFactory createFactory() {
-        final List<Property> properties = getPropertyListInternal(true);
-        for (Iterator<Property> iterator = properties.iterator(); iterator.hasNext();) {
-            Property property = iterator.next();
-            // skip non-instance fields
-            assert property.getLocation() != layout.getPrimitiveArrayLocation();
-            if (property.getLocation() instanceof ValueLocation) {
-                iterator.remove();
-            }
-        }
-
-        return new DynamicObjectFactory() {
-            @CompilationFinal private final PropertyImpl[] instanceFields = properties.toArray(new PropertyImpl[properties.size()]);
-
-            @ExplodeLoop
-            public DynamicObject newInstance(Object... initialValues) {
-                DynamicObject store = ShapeImpl.this.newInstance();
-                for (int i = 0; i < instanceFields.length; i++) {
-                    instanceFields[i].setInternal(store, initialValues[i]);
-                }
-                return store;
-            }
-
-            public Shape getShape() {
-                return ShapeImpl.this;
-            }
-        };
-    }
-
-    @Override
-    public Object getMutex() {
-        return getRoot();
-    }
-
-    @Override
-    public Shape tryMerge(Shape other) {
-        return null;
-    }
-
-    public abstract static class BaseAllocator extends Allocator implements LocationVisitor {
-        protected final LayoutImpl layout;
-        protected int objectArraySize;
-        protected int objectFieldSize;
-        protected int primitiveFieldSize;
-        protected int primitiveArraySize;
-        protected boolean hasPrimitiveArray;
-        protected int depth;
-
-        protected BaseAllocator(LayoutImpl layout) {
-            this.layout = layout;
-        }
-
-        protected BaseAllocator(ShapeImpl shape) {
-            this(shape.getLayout());
-            this.objectArraySize = shape.objectArraySize;
-            this.objectFieldSize = shape.objectFieldSize;
-            this.primitiveFieldSize = shape.primitiveFieldSize;
-            this.primitiveArraySize = shape.primitiveArraySize;
-            this.hasPrimitiveArray = shape.hasPrimitiveArray;
-            this.depth = shape.depth;
-        }
-
-        protected abstract Location moveLocation(Location oldLocation);
-
-        protected abstract Location newObjectLocation(boolean useFinal, boolean nonNull);
-
-        protected abstract Location newTypedObjectLocation(boolean useFinal, Class<?> type, boolean nonNull);
-
-        protected abstract Location newIntLocation(boolean useFinal);
-
-        protected abstract Location newDoubleLocation(boolean useFinal);
-
-        protected abstract Location newLongLocation(boolean useFinal);
-
-        protected abstract Location newBooleanLocation(boolean useFinal);
-
-        @Override
-        public final Location constantLocation(Object value) {
-            return new ConstantLocation(value);
-        }
-
-        @Override
-        protected Location locationForValue(Object value, boolean useFinal, boolean nonNull) {
-            if (value instanceof Integer) {
-                return newIntLocation(useFinal);
-            } else if (value instanceof Double) {
-                return newDoubleLocation(useFinal);
-            } else if (value instanceof Long) {
-                return newLongLocation(useFinal);
-            } else if (value instanceof Boolean) {
-                return newBooleanLocation(useFinal);
-            } else if (ObjectStorageOptions.TypedObjectLocations && value != null) {
-                return newTypedObjectLocation(useFinal, value.getClass(), nonNull);
-            }
-            return newObjectLocation(useFinal, nonNull && value != null);
-        }
-
-        protected abstract Location locationForValueUpcast(Object value, Location oldLocation);
-
-        @Override
-        protected Location locationForType(Class<?> type, boolean useFinal, boolean nonNull) {
-            if (type == int.class) {
-                return newIntLocation(useFinal);
-            } else if (type == double.class) {
-                return newDoubleLocation(useFinal);
-            } else if (type == long.class) {
-                return newLongLocation(useFinal);
-            } else if (type == boolean.class) {
-                return newBooleanLocation(useFinal);
-            } else if (ObjectStorageOptions.TypedObjectLocations && type != null && type != Object.class) {
-                assert !type.isPrimitive() : "unsupported primitive type";
-                return newTypedObjectLocation(useFinal, type, nonNull);
-            }
-            return newObjectLocation(useFinal, nonNull);
-        }
-
-        protected Location newDualLocation(Class<?> type) {
-            return new DualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), layout, type);
-        }
-
-        protected DualLocation newDualLocationForValue(Object value) {
-            Class<?> initialType = null;
-            if (value instanceof Integer) {
-                initialType = int.class;
-            } else if (value instanceof Double) {
-                initialType = double.class;
-            } else if (value instanceof Boolean) {
-                initialType = boolean.class;
-            } else {
-                initialType = Object.class;
-            }
-            return new DualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), layout, initialType);
-        }
-
-        protected Location newDeclaredDualLocation(Object value) {
-            return new DeclaredDualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), value, layout);
-        }
-
-        protected <T extends Location> T advance(T location0) {
-            if (location0 instanceof LocationImpl) {
-                LocationImpl location = (LocationImpl) location0;
-                if (location != layout.getPrimitiveArrayLocation()) {
-                    location.accept(this);
-                }
-                if (layout.hasPrimitiveExtensionArray()) {
-                    hasPrimitiveArray |= location == layout.getPrimitiveArrayLocation() || primitiveArraySize > 0;
-                } else {
-                    assert !hasPrimitiveArray && primitiveArraySize == 0;
-                }
-            }
-            depth++;
-            return location0;
-        }
-
-        @Override
-        public BaseAllocator addLocation(Location location) {
-            advance(location);
-            return this;
-        }
-
-        public void visitObjectField(int index, int count) {
-            objectFieldSize = Math.max(objectFieldSize, index + count);
-        }
-
-        public void visitObjectArray(int index, int count) {
-            objectArraySize = Math.max(objectArraySize, index + count);
-        }
-
-        public void visitPrimitiveArray(int index, int count) {
-            primitiveArraySize = Math.max(primitiveArraySize, index + count);
-        }
-
-        public void visitPrimitiveField(int index, int count) {
-            primitiveFieldSize = Math.max(primitiveFieldSize, index + count);
-        }
-    }
-
-    private static void debugRegisterShape(ShapeImpl newShape) {
-        if (ObjectStorageOptions.DumpShapes) {
-            Debug.registerShape(newShape);
-        }
-    }
-
-    /**
-     * Match all filter.
-     */
-    private static final Pred<Property> ALL = new Pred<Property>() {
-        public boolean test(Property t) {
-            return true;
-        }
-    };
-
-    private static final DebugCounter shapeCount = DebugCounter.create("Shapes allocated total");
-    private static final DebugCounter shapeCloneCount = DebugCounter.create("Shapes allocated cloned");
-    private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits");
-    private static final DebugCounter shapeCacheMissCount = DebugCounter.create("Shape cache misses");
-
-    public ForeignAccess getForeignAccessFactory() {
-        return getObjectType().getForeignAccessFactory();
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object;
-
-import java.util.*;
-
-import com.oracle.truffle.api.object.*;
-
-public abstract class Transition {
-    @Override
-    public int hashCode() {
-        int result = 1;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        return true;
-    }
-
-    public abstract boolean isDirect();
-
-    public abstract static class PropertyTransition extends Transition {
-        private final Property property;
-
-        public PropertyTransition(Property property) {
-            this.property = property;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + ((property == null) ? 0 : property.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!super.equals(obj)) {
-                return false;
-            }
-            PropertyTransition other = (PropertyTransition) obj;
-            if (!Objects.equals(property, other.property)) {
-                return false;
-            }
-            return true;
-        }
-
-        public Property getProperty() {
-            return property;
-        }
-    }
-
-    public static final class AddPropertyTransition extends PropertyTransition {
-        public AddPropertyTransition(Property property) {
-            super(property);
-        }
-
-        @Override
-        public boolean isDirect() {
-            return true;
-        }
-    }
-
-    public static final class RemovePropertyTransition extends PropertyTransition {
-        public RemovePropertyTransition(Property property) {
-            super(property);
-        }
-
-        @Override
-        public boolean isDirect() {
-            return false;
-        }
-    }
-
-    public static final class ObjectTypeTransition extends Transition {
-        private final ObjectType objectType;
-
-        public ObjectTypeTransition(ObjectType objectType) {
-            this.objectType = objectType;
-        }
-
-        public ObjectType getObjectType() {
-            return objectType;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            return super.equals(other) && Objects.equals(objectType, ((ObjectTypeTransition) other).objectType);
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + ((objectType == null) ? 0 : objectType.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean isDirect() {
-            return true;
-        }
-    }
-
-    public abstract static class AbstractReplacePropertyTransition extends PropertyTransition {
-        private final Property after;
-
-        public AbstractReplacePropertyTransition(Property before, Property after) {
-            super(before);
-            this.after = after;
-        }
-
-        public Property getPropertyBefore() {
-            return this.getProperty();
-        }
-
-        public Property getPropertyAfter() {
-            return after;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            return super.equals(obj) && this.after.equals(((AbstractReplacePropertyTransition) obj).after);
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = super.hashCode();
-            result = prime * result + after.hashCode();
-            return result;
-        }
-    }
-
-    public static final class IndirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
-        public IndirectReplacePropertyTransition(Property before, Property after) {
-            super(before, after);
-        }
-
-        @Override
-        public boolean isDirect() {
-            return false;
-        }
-    }
-
-    public static final class DirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
-        public DirectReplacePropertyTransition(Property before, Property after) {
-            super(before, after);
-        }
-
-        @Override
-        public boolean isDirect() {
-            return true;
-        }
-    }
-
-    public static final class ReservePrimitiveArrayTransition extends Transition {
-        public ReservePrimitiveArrayTransition() {
-        }
-
-        @Override
-        public boolean isDirect() {
-            return true;
-        }
-    }
-
-    public String getShortName() {
-        return this.getClass().getSimpleName().replaceFirst("Transition$", "").toLowerCase();
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.debug;
-
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-
-public class GraphvizShapeVisitor extends DebugShapeVisitor<GraphvizShapeVisitor> {
-    private final Set<Shape> drawn;
-    private final StringBuilder sb = new StringBuilder();
-
-    public GraphvizShapeVisitor() {
-        this.drawn = new HashSet<>();
-    }
-
-    @Override
-    public GraphvizShapeVisitor visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions) {
-        if (!drawn.add(shape)) {
-            return null;
-        }
-
-        String prefix = "s";
-        sb.append(prefix).append(getId(shape));
-        sb.append(" [label=\"");
-        if (shape.getLastProperty() != null) {
-            sb.append(escapeString(shape.getLastProperty().toString()));
-        } else {
-            sb.append("ROOT");
-        }
-        sb.append("\"");
-        sb.append(", shape=\"rectangle\"");
-        if (!shape.isValid()) {
-            sb.append(", color=\"red\", style=dotted");
-        }
-        sb.append("];");
-
-        for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
-            Shape dst = entry.getValue();
-            dst.accept(this);
-            assert drawn.contains(dst);
-
-            sb.append(prefix).append(getId(shape)).append("->").append(prefix).append(getId(dst));
-            sb.append(" [label=\"").append(escapeString(entry.getKey().getShortName())).append("\"]");
-            sb.append(";");
-        }
-
-        return this;
-    }
-
-    private static String escapeString(String str) {
-        return str.replaceAll("\\\\", "\\\\").replaceAll("\"", "\\\\\"");
-    }
-
-    @Override
-    public String toString() {
-        return new StringBuilder("digraph{").append(sb).append("}").toString();
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/JSONShapeVisitor.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.debug;
-
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.api.utilities.JSONHelper.JSONArrayBuilder;
-import com.oracle.truffle.api.utilities.JSONHelper.JSONObjectBuilder;
-import com.oracle.truffle.object.*;
-import com.oracle.truffle.object.Transition.PropertyTransition;
-
-public class JSONShapeVisitor extends DebugShapeVisitor<JSONObjectBuilder> {
-    @Override
-    public JSONObjectBuilder visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions) {
-        JSONObjectBuilder sb = JSONHelper.object();
-        JSONArrayBuilder transitionarray = JSONHelper.array();
-        for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
-            transitionarray.add(JSONHelper.object().add("transition", dumpTransition(entry.getKey())).add("successor", getId(entry.getValue())));
-        }
-        JSONArrayBuilder propertiesarray = JSONHelper.array();
-        for (Property p : shape.getPropertyList()) {
-            propertiesarray.add(dumpProperty(p));
-        }
-        sb.add("id", getId(shape));
-        sb.add("properties", propertiesarray);
-        sb.add("transitions", transitionarray);
-        sb.add("predecessor", shape.getParent() != null ? getId(shape.getParent()) : null);
-        sb.add("valid", shape.isValid());
-        return sb;
-    }
-
-    public JSONObjectBuilder dumpProperty(Property property) {
-        return JSONHelper.object().add("id", property.getKey().toString()).add("location", dumpLocation(property.getLocation())).add("flags", property.getFlags());
-    }
-
-    public JSONObjectBuilder dumpTransition(Transition transition) {
-        JSONObjectBuilder sb = JSONHelper.object().add("type", transition.getShortName());
-        if (transition instanceof PropertyTransition) {
-            sb.add("property", dumpProperty(((PropertyTransition) transition).getProperty()));
-        }
-        return sb;
-    }
-
-    public JSONObjectBuilder dumpLocation(Location location) {
-        JSONObjectBuilder obj = JSONHelper.object();
-        obj.add("type", (location instanceof TypedLocation ? ((TypedLocation) location).getType() : Object.class).getName());
-        // if (location instanceof Locations.FieldLocation) {
-        // obj.add("offset", ((Locations.FieldLocation) location).getOffset());
-        // }
-        // if (location instanceof Locations.ArrayLocation) {
-        // obj.add("index", ((Locations.ArrayLocation) location).getIndex());
-        // }
-        if (location instanceof Locations.ValueLocation) {
-            obj.add("value", String.valueOf(((Locations.ValueLocation) location).get(null, false)));
-        }
-        return obj;
-    }
-}
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.object.debug;
-
-import java.io.*;
-import java.text.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.object.*;
-
-public class ShapeProfiler {
-    private static final String LINE_SEPARATOR = "***********************************************";
-    private static final String BULLET = "* ";
-    private static final String TOKEN_SEPARATOR = "\t";
-    private final ConcurrentLinkedQueue<DynamicObject> queue;
-
-    public ShapeProfiler() {
-        queue = new ConcurrentLinkedQueue<>();
-    }
-
-    public void track(DynamicObject obj) {
-        queue.add(obj);
-    }
-
-    public void dump(PrintWriter out) {
-        ShapeStats globalStats = new ShapeStats("Cumulative results for all shapes");
-        for (DynamicObject obj : queue) {
-            Shape shape = obj.getShape();
-            globalStats.profile(shape);
-        }
-
-        globalStats.dump(out);
-    }
-
-    public void dump(PrintWriter out, int topResults) {
-        if (topResults > 0) {
-            IdentityHashMap<Shape, ShapeStats> shapeMap = new IdentityHashMap<>();
-
-            for (DynamicObject obj : queue) {
-                Shape shape = obj.getShape();
-                ShapeStats stats = shapeMap.get(shape);
-                if (stats == null) {
-                    shapeMap.put(shape, stats = new ShapeStats(createLabel(shape)));
-                }
-                stats.profile(shape);
-            }
-
-            List<ShapeStats> allStats = new ArrayList<>(shapeMap.values());
-            Collections.sort(allStats, new Comparator<ShapeStats>() {
-                public int compare(ShapeStats a, ShapeStats b) {
-                    return Long.compare(b.jsObjects, a.jsObjects);
-                }
-            });
-
-            ShapeStats avgStats = new ShapeStats("Cumulative results for top " + topResults + " shapes");
-            for (int i = 0; i < topResults; i++) {
-                ShapeStats stats = allStats.get(i);
-                stats.setLabel("Shape " + (i + 1) + ": " + stats.getLabel());
-                stats.dump(out);
-                avgStats.add(stats);
-            }
-            avgStats.dump(out);
-        }
-        // Dump also cumulative results.
-        dump(out);
-    }
-
-    private static String createLabel(Shape shape) {
-        String label = shape.toString();
-        return label.substring(label.indexOf('{') + 1, label.lastIndexOf('}'));
-    }
-
-    private static class ShapeStats {
-        private String label;
-        private long jsObjects;
-        private long oac;
-        private long oas;
-        private long ofs;
-        private long pac;
-        private long pas;
-        private long pfs;
-
-        public ShapeStats(String label) {
-            this.label = label;
-        }
-
-        public String getLabel() {
-            return label;
-        }
-
-        public void setLabel(String label) {
-            this.label = label;
-        }
-
-        public void profile(Shape shape) {
-            jsObjects++;
-            oac += shape.getObjectArrayCapacity();
-            oas += shape.getObjectArraySize();
-            ofs += shape.getObjectFieldSize();
-            pac += shape.getPrimitiveArrayCapacity();
-            pas += shape.getPrimitiveArraySize();
-            pfs += shape.getPrimitiveFieldSize();
-        }
-
-        public void add(ShapeStats stats) {
-            jsObjects += stats.jsObjects;
-            oac += stats.oac;
-            oas += stats.oas;
-            ofs += stats.ofs;
-            oac += stats.oac;
-            oas += stats.oas;
-            ofs += stats.ofs;
-        }
-
-        public void dump(PrintWriter out) {
-            DecimalFormat format = new DecimalFormat("###.####");
-            out.println(LINE_SEPARATOR);
-            out.println(BULLET + label);
-            out.println(LINE_SEPARATOR);
-            out.println(BULLET + "Allocated objects:\t" + jsObjects);
-            out.println(BULLET + "Total object array capacity:\t" + oac);
-            out.println(BULLET + "Total object array size:\t" + oas);
-            out.println(BULLET + "Total object field size:\t" + ofs);
-            out.println(BULLET + "Average object array capacity:\t" + avgOAC(format));
-            out.println(BULLET + "Average object array size:\t" + avgOAS(format));
-            out.println(BULLET + "Average object field size:\t" + avgOFS(format));
-            out.println(LINE_SEPARATOR);
-            out.println(BULLET + "Total primitive array capacity:\t" + pac);
-            out.println(BULLET + "Total primitive array size:\t" + pas);
-            out.println(BULLET + "Total primitive field size:\t" + pfs);
-            out.println(BULLET + "Average primitive array capacity:\t" + avgPAC(format));
-            out.println(BULLET + "Average primitive array size:\t" + avgPAS(format));
-            out.println(BULLET + "Average primitive field size:\t" + avgPFS(format));
-            out.println(LINE_SEPARATOR);
-            out.println(BULLET + toString());
-            out.println(LINE_SEPARATOR + "\n");
-            out.flush();
-        }
-
-        @Override
-        public String toString() {
-            DecimalFormat format = new DecimalFormat("###.####");
-            // @formatter:off
-            return "{" + label + "}" + TOKEN_SEPARATOR
-                   + jsObjects + TOKEN_SEPARATOR
-                   + avgOAC(format) + TOKEN_SEPARATOR
-                   + avgOAS(format) + TOKEN_SEPARATOR
-                   + avgOFS(format) + TOKEN_SEPARATOR
-                   + avgPAC(format) + TOKEN_SEPARATOR
-                   + avgPAS(format) + TOKEN_SEPARATOR
-                   + avgPFS(format);
-            // @formatter:on
-        }
-
-        private String avgOAC(DecimalFormat format) {
-            return format.format((double) oac / jsObjects);
-        }
-
-        private String avgOAS(DecimalFormat format) {
-            return format.format((double) oas / jsObjects);
-        }
-
-        private String avgOFS(DecimalFormat format) {
-            return format.format((double) ofs / jsObjects);
-        }
-
-        private String avgPAC(DecimalFormat format) {
-            return format.format((double) pac / jsObjects);
-        }
-
-        private String avgPAS(DecimalFormat format) {
-            return format.format((double) pas / jsObjects);
-        }
-
-        private String avgPFS(DecimalFormat format) {
-            return format.format((double) pfs / jsObjects);
-        }
-    }
-
-    public static ShapeProfiler getInstance() {
-        return shapeProf;
-    }
-
-    private static final ShapeProfiler shapeProf;
-    static {
-        if (ObjectStorageOptions.Profile) {
-            shapeProf = new ShapeProfiler();
-            Runtime.getRuntime().addShutdownHook(new Thread() {
-                @Override
-                public void run() {
-                    getInstance().dump(new PrintWriter(System.out), ObjectStorageOptions.ProfileTopResults);
-                }
-            });
-        } else {
-            shapeProf = null;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test;
-
-import org.junit.*;
-import org.junit.runner.*;
-
-@RunWith(SLTestRunner.class)
-@SLTestSuite({"graal/com.oracle.truffle.sl.test/tests", "tests"})
-public class SLSimpleTestSuite {
-
-    public static void main(String[] args) throws Exception {
-        SLTestRunner.runInMain(SLSimpleTestSuite.class, args);
-    }
-
-    /*
-     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
-     * an empty method, this class gets included and the test suite is properly executed.
-     */
-    @Test
-    public void unittest() {
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test;
-
-import com.oracle.truffle.tck.TruffleTCK;
-import com.oracle.truffle.api.vm.TruffleVM;
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-/**
- * This is the way to verify your language implementation is compatible.
- *
- */
-public class SLTckTest extends TruffleTCK {
-    @Test
-    public void testVerifyPresence() {
-        TruffleVM vm = TruffleVM.newVM().build();
-        assertTrue("Our language is present", vm.getLanguages().containsKey("application/x-sl"));
-    }
-
-    @Override
-    protected TruffleVM prepareVM() throws Exception {
-        TruffleVM vm = TruffleVM.newVM().build();
-        // @formatter:off
-        vm.eval("application/x-sl",
-            "function fourtyTwo() {\n" +
-            "  return 42;\n" + //
-            "}\n" +
-            "function plus(a, b) {\n" +
-            "  return a + b;\n" +
-            "}\n" +
-            "function null() {\n" +
-            "}\n"
-        );
-        // @formatter:on
-        return vm;
-    }
-
-    @Override
-    protected String mimeType() {
-        return "application/x-sl";
-    }
-
-    @Override
-    protected String fourtyTwo() {
-        return "fourtyTwo";
-    }
-
-    @Override
-    protected String plusInt() {
-        return "plus";
-    }
-
-    @Override
-    protected String returnsNull() {
-        return "null";
-    }
-
-    @Override
-    protected String invalidCode() {
-        // @formatter:off
-        return
-            "f unction main() {\n" +
-            "  retu rn 42;\n" +
-            "}\n";
-        // @formatter:on
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.util.*;
-
-import org.junit.*;
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.manipulation.*;
-import org.junit.runner.notification.*;
-import org.junit.runners.*;
-import org.junit.runners.model.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.vm.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.builtins.*;
-import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
-
-public final class SLTestRunner extends ParentRunner<TestCase> {
-
-    private static int repeats = 1;
-
-    private static final String SOURCE_SUFFIX = ".sl";
-    private static final String INPUT_SUFFIX = ".input";
-    private static final String OUTPUT_SUFFIX = ".output";
-
-    private static final String LF = System.getProperty("line.separator");
-
-    static class TestCase {
-        protected final Description name;
-        protected final Path path;
-        protected final String sourceName;
-        protected final String testInput;
-        protected final String expectedOutput;
-        protected String actualOutput;
-
-        protected TestCase(Class<?> testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) {
-            this.name = Description.createTestDescription(testClass, baseName);
-            this.sourceName = sourceName;
-            this.path = path;
-            this.testInput = testInput;
-            this.expectedOutput = expectedOutput;
-        }
-    }
-
-    private final List<TestCase> testCases;
-
-    public SLTestRunner(Class<?> runningClass) throws InitializationError {
-        super(runningClass);
-        try {
-            testCases = createTests(runningClass);
-        } catch (IOException e) {
-            throw new InitializationError(e);
-        }
-    }
-
-    @Override
-    protected Description describeChild(TestCase child) {
-        return child.name;
-    }
-
-    @Override
-    protected List<TestCase> getChildren() {
-        return testCases;
-    }
-
-    protected static List<TestCase> createTests(final Class<?> c) throws IOException, InitializationError {
-        SLTestSuite suite = c.getAnnotation(SLTestSuite.class);
-        if (suite == null) {
-            throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLTestSuite.class.getSimpleName(), c.getName(), SLTestRunner.class.getSimpleName()));
-        }
-
-        String[] pathes = suite.value();
-
-        Path root = null;
-        for (String path : pathes) {
-            root = FileSystems.getDefault().getPath(path);
-            if (Files.exists(root)) {
-                break;
-            }
-        }
-        if (root == null && pathes.length > 0) {
-            throw new FileNotFoundException(pathes[0]);
-        }
-
-        final Path rootPath = root;
-
-        final List<TestCase> foundCases = new ArrayList<>();
-        Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
-                String sourceName = sourceFile.getFileName().toString();
-                if (sourceName.endsWith(SOURCE_SUFFIX)) {
-                    String baseName = sourceName.substring(0, sourceName.length() - SOURCE_SUFFIX.length());
-
-                    Path inputFile = sourceFile.resolveSibling(baseName + INPUT_SUFFIX);
-                    String testInput = "";
-                    if (Files.exists(inputFile)) {
-                        testInput = readAllLines(inputFile);
-                    }
-
-                    Path outputFile = sourceFile.resolveSibling(baseName + OUTPUT_SUFFIX);
-                    String expectedOutput = "";
-                    if (Files.exists(outputFile)) {
-                        expectedOutput = readAllLines(outputFile);
-                    }
-
-                    foundCases.add(new TestCase(c, baseName, sourceName, sourceFile, testInput, expectedOutput));
-                }
-                return FileVisitResult.CONTINUE;
-            }
-        });
-        return foundCases;
-    }
-
-    private static String readAllLines(Path file) throws IOException {
-        // fix line feeds for non unix os
-        StringBuilder outFile = new StringBuilder();
-        for (String line : Files.readAllLines(file, Charset.defaultCharset())) {
-            outFile.append(line).append(LF);
-        }
-        return outFile.toString();
-    }
-
-    public static void setRepeats(int repeats) {
-        SLTestRunner.repeats = repeats;
-    }
-
-    private static final List<NodeFactory<? extends SLBuiltinNode>> builtins = new ArrayList<>();
-
-    public static void installBuiltin(NodeFactory<? extends SLBuiltinNode> builtin) {
-        builtins.add(builtin);
-    }
-
-    @Override
-    protected void runChild(TestCase testCase, RunNotifier notifier) {
-        notifier.fireTestStarted(testCase.name);
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        PrintWriter printer = new PrintWriter(out);
-        try {
-            TruffleVM vm = TruffleVM.newVM().stdIn(new BufferedReader(new StringReader(repeat(testCase.testInput, repeats)))).stdOut(printer).build();
-
-            String script = readAllLines(testCase.path);
-            SLLanguage.run(vm, testCase.path.toUri(), null, printer, repeats, builtins);
-
-            printer.flush();
-            String actualOutput = new String(out.toByteArray());
-            Assert.assertEquals(script, repeat(testCase.expectedOutput, repeats), actualOutput);
-        } catch (Throwable ex) {
-            notifier.fireTestFailure(new Failure(testCase.name, new IllegalStateException("Cannot run " + testCase.sourceName, ex)));
-        } finally {
-            notifier.fireTestFinished(testCase.name);
-        }
-    }
-
-    private static String repeat(String s, int count) {
-        StringBuilder result = new StringBuilder(s.length() * count);
-        for (int i = 0; i < count; i++) {
-            result.append(s);
-        }
-        return result.toString();
-    }
-
-    public static void runInMain(Class<?> testClass, String[] args) throws InitializationError, NoTestsRemainException {
-        JUnitCore core = new JUnitCore();
-        core.addListener(new TextListener(System.out));
-        SLTestRunner suite = new SLTestRunner(testClass);
-        if (args.length > 0) {
-            suite.filter(new NameFilter(args[0]));
-        }
-        Result r = core.run(suite);
-        if (!r.wasSuccessful()) {
-            System.exit(1);
-        }
-    }
-
-    private static final class NameFilter extends Filter {
-        private final String pattern;
-
-        private NameFilter(String pattern) {
-            this.pattern = pattern.toLowerCase();
-        }
-
-        @Override
-        public boolean shouldRun(Description description) {
-            return description.getMethodName().toLowerCase().contains(pattern);
-        }
-
-        @Override
-        public String describe() {
-            return "Filter contains " + pattern;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestSuite.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface SLTestSuite {
-
-    /**
-     * Defines the base path of the test suite. Multiple base pathes can be specified. However only
-     * the first base that exists is used to lookup the test cases.
-     */
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,292 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test.instrument;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.nio.file.*;
-import java.nio.file.attribute.*;
-import java.util.*;
-
-import org.junit.*;
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.manipulation.*;
-import org.junit.runner.notification.*;
-import org.junit.runners.*;
-import org.junit.runners.model.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.factory.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
-import com.oracle.truffle.sl.nodes.local.*;
-import com.oracle.truffle.sl.parser.*;
-import com.oracle.truffle.sl.runtime.*;
-import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase;
-
-/**
- * This class builds and executes the tests for instrumenting SL. Although much of this class is
- * written with future automation in mind, at the moment the tests that are created are hard-coded
- * according to the file name of the test. To be automated, an automatic way of generating both the
- * node visitor and the node prober is necessary.
- *
- * Testing is done via JUnit via comparing execution outputs with expected outputs.
- */
-public final class SLInstrumentTestRunner extends ParentRunner<InstrumentTestCase> {
-
-    private static final String SOURCE_SUFFIX = ".sl";
-    private static final String INPUT_SUFFIX = ".input";
-    private static final String OUTPUT_SUFFIX = ".output";
-    private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount";
-
-    private static final String LF = System.getProperty("line.separator");
-    private static SLContext slContext;
-
-    static class InstrumentTestCase {
-        protected final Description name;
-        protected final Path path;
-        protected final String baseName;
-        protected final String sourceName;
-        protected final String testInput;
-        protected final String expectedOutput;
-        protected String actualOutput;
-
-        protected InstrumentTestCase(Class<?> testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) {
-            this.name = Description.createTestDescription(testClass, baseName);
-            this.baseName = baseName;
-            this.sourceName = sourceName;
-            this.path = path;
-            this.testInput = testInput;
-            this.expectedOutput = expectedOutput;
-        }
-    }
-
-    private final List<InstrumentTestCase> testCases;
-
-    public SLInstrumentTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-        final SLStandardASTProber prober = new SLStandardASTProber();
-        Probe.registerASTProber(prober);
-        try {
-            testCases = createTests(testClass);
-        } catch (IOException e) {
-            throw new InitializationError(e);
-        } finally {
-            Probe.unregisterASTProber(prober);
-        }
-    }
-
-    @Override
-    protected List<InstrumentTestCase> getChildren() {
-        return testCases;
-    }
-
-    @Override
-    protected Description describeChild(InstrumentTestCase child) {
-        return child.name;
-    }
-
-    /**
-     * Tests are created based on the files that exist in the directory specified in the passed in
-     * annotation. Each test must have a source file and an expected output file. Optionally, each
-     * test can also include an input file. Source files have an ".sl" extension. Expected output
-     * have a ".output" extension. Input files have an ".input" extension. All these files must
-     * share the same base name to be correctly grouped. For example: "test1_assnCount.sl",
-     * "test1_assnCount.output" and "test1_assnCount.input" would all be used to create a single
-     * test called "test1_assnCount".
-     *
-     * This method iterates over the files in the directory and creates a new InstrumentTestCase for
-     * each group of related files. Each file is also expected to end with an identified at the end
-     * of the base name to indicate what visitor needs to be attached. Currently, visitors are hard
-     * coded to work on specific lines, so the code here is not currently generalizable.
-     *
-     * @param c The annotation containing the directory with tests
-     * @return A list of {@link InstrumentTestCase}s to run.
-     * @throws IOException If the directory is invalid.
-     * @throws InitializationError If no directory is provided.
-     *
-     * @see #runChild(InstrumentTestCase, RunNotifier)
-     */
-    protected static List<InstrumentTestCase> createTests(final Class<?> c) throws IOException, InitializationError {
-        SLInstrumentTestSuite suite = c.getAnnotation(SLInstrumentTestSuite.class);
-        if (suite == null) {
-            throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLInstrumentTestSuite.class.getSimpleName(), c.getName(),
-                            SLInstrumentTestRunner.class.getSimpleName()));
-        }
-
-        String[] paths = suite.value();
-
-        Path root = null;
-        for (String path : paths) {
-            root = FileSystems.getDefault().getPath(path);
-            if (Files.exists(root)) {
-                break;
-            }
-        }
-        if (root == null && paths.length > 0) {
-            throw new FileNotFoundException(paths[0]);
-        }
-
-        final Path rootPath = root;
-
-        final List<InstrumentTestCase> testCases = new ArrayList<>();
-
-        // Scaffolding in place for future automation
-        Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
-                String sourceName = sourceFile.getFileName().toString();
-                if (sourceName.endsWith(SOURCE_SUFFIX)) {
-                    String baseName = sourceName.substring(0, sourceName.length() - SOURCE_SUFFIX.length());
-
-                    Path inputFile = sourceFile.resolveSibling(baseName + INPUT_SUFFIX);
-                    String testInput = "";
-                    if (Files.exists(inputFile)) {
-                        testInput = readAllLines(inputFile);
-                    }
-
-                    Path outputFile = sourceFile.resolveSibling(baseName + OUTPUT_SUFFIX);
-                    String expectedOutput = "";
-                    if (Files.exists(outputFile)) {
-                        expectedOutput = readAllLines(outputFile);
-                    }
-
-                    testCases.add(new InstrumentTestCase(c, baseName, sourceName, sourceFile, testInput, expectedOutput));
-
-                }
-                return FileVisitResult.CONTINUE;
-            }
-        });
-
-        return testCases;
-    }
-
-    private static String readAllLines(Path file) throws IOException {
-        // fix line feeds for non unix os
-        StringBuilder outFile = new StringBuilder();
-        for (String line : Files.readAllLines(file, Charset.defaultCharset())) {
-            outFile.append(line).append(LF);
-        }
-        return outFile.toString();
-    }
-
-    /**
-     * Executes the passed in test case. Instrumentation is added according to the name of the file
-     * as explained in {@link #createTests(Class)}. Note that this code is not generalizable.
-     */
-    @Override
-    protected void runChild(InstrumentTestCase testCase, RunNotifier notifier) {
-        // TODO Current tests are hard-coded, automate this eventually
-        notifier.fireTestStarted(testCase.name);
-
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        PrintWriter printer = new PrintWriter(out);
-        final ASTProber prober = new SLStandardASTProber();
-        Probe.registerASTProber(prober);
-        try {
-            // We use the name of the file to determine what visitor to attach to it.
-            if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
-                // Set up the execution context for Simple and register our two listeners
-                slContext = SLContextFactory.create(new BufferedReader(new StringReader(testCase.testInput)), printer);
-
-                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
-                Parser.parseSL(slContext, source);
-
-                // Attach an instrument to every probe tagged as an assignment
-                for (Probe probe : Probe.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
-                    SLPrintAssigmentValueListener slPrintAssigmentValueListener = new SLPrintAssigmentValueListener(printer);
-                    probe.attach(Instrument.create(slPrintAssigmentValueListener, "SL print assignment value"));
-                }
-
-                SLFunction main = slContext.getFunctionRegistry().lookup("main");
-                main.getCallTarget().call();
-            } else {
-                notifier.fireTestFailure(new Failure(testCase.name, new UnsupportedOperationException("No instrumentation found.")));
-            }
-
-            printer.flush();
-            String actualOutput = new String(out.toByteArray());
-            Assert.assertEquals(testCase.expectedOutput, actualOutput);
-        } catch (Throwable ex) {
-            notifier.fireTestFailure(new Failure(testCase.name, ex));
-        } finally {
-            Probe.unregisterASTProber(prober);
-            notifier.fireTestFinished(testCase.name);
-        }
-
-    }
-
-    public static void runInMain(Class<?> testClass, String[] args) throws InitializationError, NoTestsRemainException {
-        JUnitCore core = new JUnitCore();
-        core.addListener(new TextListener(System.out));
-        SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass);
-        if (args.length > 0) {
-            suite.filter(new NameFilter(args[0]));
-        }
-        Result r = core.run(suite);
-        if (!r.wasSuccessful()) {
-            System.exit(1);
-        }
-    }
-
-    private static final class NameFilter extends Filter {
-        private final String pattern;
-
-        private NameFilter(String pattern) {
-            this.pattern = pattern.toLowerCase();
-        }
-
-        @Override
-        public boolean shouldRun(Description description) {
-            return description.getMethodName().toLowerCase().contains(pattern);
-        }
-
-        @Override
-        public String describe() {
-            return "Filter contains " + pattern;
-        }
-    }
-
-    /**
-     * This sample listener provides prints the value of an assignment (after the assignment is
-     * complete) to the {@link PrintWriter} specified in the constructor. This listener can only be
-     * attached at {@link SLWriteLocalVariableNode}, but provides no guards to protect it from being
-     * attached elsewhere.
-     */
-    public final class SLPrintAssigmentValueListener extends DefaultSimpleInstrumentListener {
-
-        private PrintWriter output;
-
-        public SLPrintAssigmentValueListener(PrintWriter output) {
-            this.output = output;
-        }
-
-        @Override
-        public void returnValue(Probe probe, Object result) {
-            output.println(result);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test.instrument;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface SLInstrumentTestSuite {
-
-    /**
-     * Defines the base path of the test suite. Multiple base paths can be specified. However only
-     * the first base that exists is used to lookup the test cases.
-     */
-    String[] value();
-
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.test.instrument;
-
-import org.junit.*;
-import org.junit.runner.*;
-
-@RunWith(SLInstrumentTestRunner.class)
-@SLInstrumentTestSuite({"graal/com.oracle.truffle.sl.test/tests_instrumentation", "tests_instrumentation"})
-public class SLSimpleInstrumentTestSuite {
-
-    public static void main(String[] args) throws Exception {
-        SLInstrumentTestRunner.runInMain(SLSimpleInstrumentTestSuite.class, args);
-    }
-
-    /*
-     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
-     * an empty method, this class gets included and the test suite is properly executed.
-     */
-    @Test
-    public void unittest() {
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/tests/Add.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-7
-34
-34
-34
-4000000000003
-3000000000004
-7000000000000
--- a/graal/com.oracle.truffle.sl.test/tests/Add.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-function main() {  
-  println(3 + 4);  
-  println(3 + "4");  
-  println("3" + 4);  
-  println("3" + "4");  
-  println(3 + 4000000000000);  
-  println(3000000000000 + 4);  
-  println(3000000000000 + 4000000000000);  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Arithmetic.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-5
-1
--3
-14
-11
-5
--3
-1
-18
-11
--- a/graal/com.oracle.truffle.sl.test/tests/Arithmetic.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-function main() {  
-  println(3 + 4 - 2);  
-  println(3 - 4 + 2);  
-  println(3 - 4 - 2);  
-  println(3 * 4 + 2);  
-  println(3 + 4 * 2);  
-  println(3 + (4 - 2));  
-  println(3 - (4 + 2));  
-  println(3 - (4 - 2));  
-  println(3 * (4 + 2));  
-  println(3 + (4 * 2));  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Break.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-942
--- a/graal/com.oracle.truffle.sl.test/tests/Break.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-function main() {  
-  i = 0;  
-  while (i < 1000) {
-    if (i >= 942) {
-      break;
-    }  
-    i = i + 1;  
-  }
-  return i;  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Builtins.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Hello World!
--- a/graal/com.oracle.truffle.sl.test/tests/Builtins.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function main() {  
-  println("Hello World!");  
-  nanoTime();  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/CalcShell.input	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-i
-80
-c
-return cur + i;
-r
-c
-if (i <= 2) { return 1; } else { return prev + cur; }
-r
-i
-100
-r
-c
-if (i == 0) { return 1; } else { return cur * i; }
-r
-x
--- a/graal/com.oracle.truffle.sl.test/tests/CalcShell.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-available commands:
-x: exit
-c: define the calculation function with the parameters prev, cur, and i
-   prev and cur start with 0; i is the loop variable from 0 to n
-     example: 'return cur + i;' computes the sum of 1 to n
-     example: 'if (i == 0) { return 1; } else { return cur * i; }' computes the factorial of i
-     example: 'if (i <= 2) { return 1; } else { return prev + cur; }' computes the nth Fibonacci number
-i: define the number of iterations, i.e, the number n in the examples above
-r: Run the calculation loop often, and print the first and last result
-t: Run the calculation loop a couple of time, and print timing information for each run
-h: Print this help message
-
-cmd>
-n>
-cmd>
-function>
-cmd>
-** first: 3240
-** last:  3240
-cmd>
-function>
-cmd>
-** first: 23416728348467685
-** last:  23416728348467685
-cmd>
-n>
-cmd>
-** first: 354224848179261915075
-** last:  354224848179261915075
-cmd>
-function>
-cmd>
-** first: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
-** last:  93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
-cmd>
--- a/graal/com.oracle.truffle.sl.test/tests/CalcShell.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-function iterations() {
-  return 80;
-}
-
-function calcLoop(n) {
-  i = 0;
-  prev = cur = 0;
-  while (i <= n) {
-    next = calc(prev, cur, i);
-    prev = cur;
-    cur = next;  
-    i = i + 1;
-  }  
-  return cur;  
-}
-
-function timing(n) {
-  i = 0;
-  while (i < 20) {
-    start = nanoTime();
-    calcLoop(n);
-    end = nanoTime();
-    i = i + 1;
-
-    println("** run " + i + ": " + (end - start) + " ns");
-  }
-}
-
-function run(n) {
-  firstResult = calcLoop(n);
-  println("** first: " + firstResult);
-  i = 0;
-  while (i < 100) {
-    calcLoop(n);
-    i = i + 1;
-  }
-  lastResult = calcLoop(n);
-  println("** last:  " + lastResult);
-  
-  if (firstResult != lastResult) {
-    println("ERROR: result not stable");
-  }
-}  
-
-function help() {
-  println("available commands:");
-  println("x: exit");
-  println("c: define the calculation function with the parameters prev, cur, and i");
-  println("   prev and cur start with 0; i is the loop variable from 0 to n");
-  println("     example: 'return cur + i;' computes the sum of 1 to n"); 
-  println("     example: 'if (i == 0) { return 1; } else { return cur * i; }' computes the factorial of i"); 
-  println("     example: 'if (i <= 2) { return 1; } else { return prev + cur; }' computes the nth Fibonacci number");
-  println("i: define the number of iterations, i.e, the number n in the examples above");
-  println("r: Run the calculation loop often, and print the first and last result");
-  println("t: Run the calculation loop a couple of time, and print timing information for each run");
-  println("h: Print this help message");
-  println("");
-}
-
-function main() {
-  help();
-  
-  while (1 == 1) {
-    println("cmd>");
-    cmd = readln();
-    if (cmd == "x" || cmd == "") {
-      return;
-    }
-    if (cmd == "h") {
-      help();
-    }
-    if (cmd == "c") {
-      println("function>");
-      code = readln();
-      defineFunction("function calc(prev, cur, i) { " + code + "}");
-    }
-    if (cmd == "t") {
-      timing(iterations());
-    }
-    if (cmd == "r") {
-      run(iterations());
-    }
-    if (cmd == "i") {
-      println("n>");
-      n = readln();
-      defineFunction("function iterations() { return " + n + "; }");
-    }
-  }
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Call.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-42
-42
-42
-42
-42
-42
-42
-42
--- a/graal/com.oracle.truffle.sl.test/tests/Call.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-function ret(a) { return a; } 
-function dub(a) { return a * 2; } 
-function inc(a) { return a + 1; } 
-function dec(a) { return a - 1; } 
-function call(f, v) { return f(v); }
- 
-function main() {  
-  println(ret(42));
-  println(dub(21));
-  println(inc(41));
-  println(dec(43));
-  println(call(ret, 42));
-  println(call(dub, 21));
-  println(call(inc, 41));
-  println(call(dec, 43));
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Comparison.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-<
-true
-false
-false
-true
-false
-true
-false
-false
-<=
-true
-false
-true
-true
-false
-true
-false
-true
->
-false
-true
-false
-false
-true
-false
-true
-false
->=
-false
-true
-true
-false
-true
-false
-true
-true
-==
-false
-false
-true
-false
-false
-false
-false
-true
-!=
-true
-true
-false
-true
-true
-true
-true
-false
--- a/graal/com.oracle.truffle.sl.test/tests/Comparison.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-function main() {  
-  println("<");
-  println(4 < 20);  
-  println(40 < 2);  
-  println(4 < 4);  
-  println(4 < 200000000000000000000000000);  
-  println(40000000000000000000000000 < 20);  
-  println(40000000000000000000000000 < 200000000000000000000000000);  
-  println(400000000000000000000000000 < 20000000000000000000000000);  
-  println(40000000000000000000000000 < 40000000000000000000000000);  
-
-  println("<=");
-  println(4 <= 20);  
-  println(40 <= 2);  
-  println(4 <= 4);  
-  println(4 <= 200000000000000000000000000);  
-  println(40000000000000000000000000 <= 20);  
-  println(40000000000000000000000000 <= 200000000000000000000000000);  
-  println(400000000000000000000000000 <= 20000000000000000000000000);  
-  println(40000000000000000000000000 <= 40000000000000000000000000);  
-
-  println(">");
-  println(4 > 20);  
-  println(40 > 2);  
-  println(4 > 4);  
-  println(4 > 200000000000000000000000000);  
-  println(40000000000000000000000000 > 20);  
-  println(40000000000000000000000000 > 200000000000000000000000000);  
-  println(400000000000000000000000000 > 20000000000000000000000000);  
-  println(40000000000000000000000000 > 40000000000000000000000000);  
-
-  println(">=");
-  println(4 >= 20);  
-  println(40 >= 2);  
-  println(4 >= 4);  
-  println(4 >= 200000000000000000000000000);  
-  println(40000000000000000000000000 >= 20);  
-  println(40000000000000000000000000 >= 200000000000000000000000000);  
-  println(400000000000000000000000000 >= 20000000000000000000000000);  
-  println(40000000000000000000000000 >= 40000000000000000000000000);  
-
-  println("==");
-  println(4 == 20);  
-  println(40 == 2);  
-  println(4 == 4);  
-  println(4 == 200000000000000000000000000);  
-  println(40000000000000000000000000 == 20);  
-  println(40000000000000000000000000 == 200000000000000000000000000);  
-  println(400000000000000000000000000 == 20000000000000000000000000);  
-  println(40000000000000000000000000 == 40000000000000000000000000);  
-
-  println("!=");
-  println(4 != 20);  
-  println(40 != 2);  
-  println(4 != 4);  
-  println(4 != 200000000000000000000000000);  
-  println(40000000000000000000000000 != 20);  
-  println(40000000000000000000000000 != 200000000000000000000000000);  
-  println(400000000000000000000000000 != 20000000000000000000000000);  
-  println(40000000000000000000000000 != 40000000000000000000000000);  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/ControlFlow.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1
--- a/graal/com.oracle.truffle.sl.test/tests/ControlFlow.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-function foo() {}
-function bar() {}
-
-function main() {  
-  foo();
-  if (1 < 2) {
-    bar();
-    return 1;
-  }
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/DefineFunction.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-42
-38
--- a/graal/com.oracle.truffle.sl.test/tests/DefineFunction.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-function foo() {
-  println(test(40, 2));
-}
-
-function main() {
-  defineFunction("function test(a, b) { return a + b; }");
-  foo();
-
-  defineFunction("function test(a, b) { return a - b; }");
-  foo();
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Div.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-2
-0
-1000000000000
-1
--- a/graal/com.oracle.truffle.sl.test/tests/Div.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-function main() {  
-  println(4 / 2);  
-  println(4 / 4000000000000);  
-  println(3000000000000 / 3);  
-  println(3000000000000 / 3000000000000);  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Fibonacci.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-1: 1
-2: 1
-3: 2
-4: 3
-5: 5
-6: 8
-7: 13
-8: 21
-9: 34
-10: 55
--- a/graal/com.oracle.truffle.sl.test/tests/Fibonacci.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-function fib(num) { 
-  if (num < 1) {return 0;}
-  n1 = 0;
-  n2 = 1;
-  i = 1;
-  while (i < num) {
-    next = n2 + n1;
-    n1 = n2;
-    n2 = next;
-    i = i + 1;
-  }
-  return n2;
-}
-
-function main() {  
-  i = 1;
-  while (i <= 10) {
-    println(i + ": " + fib(i));
-    i = i + 1;
-  }
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/FunctionLiteral.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-42
-38
--- a/graal/com.oracle.truffle.sl.test/tests/FunctionLiteral.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-function add(a, b) {
-  return a + b;
-}
-
-function sub(a, b) {
-  return a - b;
-}
-
-function foo(f) {
-  println(f(40, 2));
-}
-
-function main() {
-  foo(add);
-  foo(sub);
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-Initial stack trace:
-Frame: root doIt, a=0, hello=null
-Frame: root main, i=0
-After 123 assignment:
-Frame: root doIt, a=0, hello=123
-Frame: root main, i=0
-After hello assignment:
-Frame: root doIt, a=0, hello=world
-Frame: root main, i=0
-Initial stack trace:
-Frame: root doIt, a=1, hello=null
-Frame: root main, i=1
-After 123 assignment:
-Frame: root doIt, a=1, hello=123
-Frame: root main, i=1
-After hello assignment:
-Frame: root doIt, a=1, hello=world
-Frame: root main, i=1
-Initial stack trace:
-Frame: root doIt, a=2, hello=null
-Frame: root main, i=2
-After 123 assignment:
-Frame: root doIt, a=2, hello=123
-Frame: root main, i=2
-After hello assignment:
-Frame: root doIt, a=2, hello=world
-Frame: root main, i=2
-Initial stack trace:
-Frame: root doIt, a=3, hello=null
-Frame: root main, i=3
-After 123 assignment:
-Frame: root doIt, a=3, hello=123
-Frame: root main, i=3
-After hello assignment:
-Frame: root doIt, a=3, hello=world
-Frame: root main, i=3
-Initial stack trace:
-Frame: root doIt, a=4, hello=null
-Frame: root main, i=4
-After 123 assignment:
-Frame: root doIt, a=4, hello=123
-Frame: root main, i=4
-After hello assignment:
-Frame: root doIt, a=4, hello=world
-Frame: root main, i=4
-Initial stack trace:
-Frame: root doIt, a=5, hello=null
-Frame: root main, i=5
-After 123 assignment:
-Frame: root doIt, a=5, hello=123
-Frame: root main, i=5
-After hello assignment:
-Frame: root doIt, a=5, hello=world
-Frame: root main, i=5
-Initial stack trace:
-Frame: root doIt, a=6, hello=null
-Frame: root main, i=6
-After 123 assignment:
-Frame: root doIt, a=6, hello=123
-Frame: root main, i=6
-After hello assignment:
-Frame: root doIt, a=6, hello=world
-Frame: root main, i=6
-Initial stack trace:
-Frame: root doIt, a=7, hello=null
-Frame: root main, i=7
-After 123 assignment:
-Frame: root doIt, a=7, hello=123
-Frame: root main, i=7
-After hello assignment:
-Frame: root doIt, a=7, hello=world
-Frame: root main, i=7
-Initial stack trace:
-Frame: root doIt, a=8, hello=null
-Frame: root main, i=8
-After 123 assignment:
-Frame: root doIt, a=8, hello=123
-Frame: root main, i=8
-After hello assignment:
-Frame: root doIt, a=8, hello=world
-Frame: root main, i=8
-Initial stack trace:
-Frame: root doIt, a=9, hello=null
-Frame: root main, i=9
-After 123 assignment:
-Frame: root doIt, a=9, hello=123
-Frame: root main, i=9
-After hello assignment:
-Frame: root doIt, a=9, hello=world
-Frame: root main, i=9
\ No newline at end of file
--- a/graal/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-function doIt(a) {
-  println("Initial stack trace:");
-  println(stacktrace());
-  
-  hello = 123;
-  println("After 123 assignment:");
-  println(stacktrace());
-  
-  helloEqualsWorld();
-  println("After hello assignment:");
-  println(stacktrace());
-  
-//  readln();
-}
-
-function main() {
-  i = 0;
-  while (i < 10) {
-    doIt(i);
-    i = i + 1;
-  }
-}
--- a/graal/com.oracle.truffle.sl.test/tests/HelloWorld.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Hello World!
--- a/graal/com.oracle.truffle.sl.test/tests/HelloWorld.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  println("Hello World!");  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Inlining.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1260000
\ No newline at end of file
--- a/graal/com.oracle.truffle.sl.test/tests/Inlining.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-
-function a() {return 42;}
-function b() {return a();}
-function c() {return b();}
-function d() {return c();}
-function e() {return c();}
-function f() {return c();}
-function g() {return d() + e() + f();}
-
-function main() {
-    i = 0;
-    result = 0;
-    while (i < 10000) {
-        result = result + g();
-        i = i + 1;
-    }
-    return result;
-}
--- a/graal/com.oracle.truffle.sl.test/tests/Loop.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1000
--- a/graal/com.oracle.truffle.sl.test/tests/Loop.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-function main() {  
-  i = 0;  
-  while (i < 1000) {  
-    i = i + 1;  
-  }  
-  return i;  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/LoopCall.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1000
--- a/graal/com.oracle.truffle.sl.test/tests/LoopCall.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-function add(a, b) {
-  return a + b;
-}
-
-function loop(n) {
-  i = 0;
-  while (i < n) {  
-    i = add(i, 1);  
-  }
-  return i;
-}
-
-function main() {
-  i = 0;
-  while (i < 20) {
-    loop(1000);
-    i = i + 1;
-  }
-  println(loop(1000));  
-}
--- a/graal/com.oracle.truffle.sl.test/tests/LoopInvalidate.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1000
--- a/graal/com.oracle.truffle.sl.test/tests/LoopInvalidate.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-function add(a, b) {
-  return a + b;
-}
-
-function loop(n) {
-  i = 0;  
-  while (i < n) {  
-    i = add(i, 1);  
-  }  
-  return i;
-}  
-
-function main() {
-  i = 0;
-  while (i < 20) {
-    loop(1000);
-    i = i + 1;
-  }
-  add("a", "b");
-  println(loop(1000));  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1000
--- a/graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-function add(a, b) {
-  return a + b;
-}
-
-function loop(n) {
-  i = 0;
-  while (i < n) {
-    i = add(i, 1); 
-  }
-  return i;
-}
-
-function main() {
-  add("a", "b");
-
-  i = 0;
-  while (i < 20) {
-    loop(1000);
-    i = i + 1;
-  }
-  println(loop(1000));  
-}
--- a/graal/com.oracle.truffle.sl.test/tests/LoopPrint.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-1000
--- a/graal/com.oracle.truffle.sl.test/tests/LoopPrint.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-function loop(n) {
-  i = 0;  
-  while (i < n) {  
-    i = i + 1;  
-  }  
-  return i;
-}  
-
-function main() {
-  i = 0;
-  while (i < 20) {
-    loop(1000);
-    i = i + 1;
-  }
-  println(loop(1000));  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Mul.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-12
-12000000000000
-12000000000000
-12000000000000000000000000
--- a/graal/com.oracle.truffle.sl.test/tests/Mul.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-function main() {  
-  println(3 * 4);  
-  println(3 * 4000000000000);  
-  println(3000000000000 * 4);  
-  println(3000000000000 * 4000000000000);  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Null.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-null
-true
-false
-false
-true
-false
-true
--- a/graal/com.oracle.truffle.sl.test/tests/Null.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/* The easiest way to generate null: a function without a return statement implicitly returns null. */
-function null() {
-}
-
-function main() {  
-  println(null());  
-  println(null() == null());  
-  println(null() != null());  
-  println(null() == 42);  
-  println(null() != 42);  
-  println(null() == "42");  
-  println(null() != "42");  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Object.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-null
-42
-42
-why
-zzz
-zzz
--- a/graal/com.oracle.truffle.sl.test/tests/Object.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-function main() {  
-  obj1 = new();
-  println(obj1.x);
-  obj1.x = 42;
-  println(obj1.x);
-  
-  obj2 = new();
-  obj2.o = obj1;
-  println(obj2.o.x);
-  obj2.o.y = "why";
-  println(obj1.y);
-  
-  println(mkobj().z);
-  
-  obj3 = new();
-  obj3.fn = mkobj;
-  println(obj3.fn().z);
-
-  obj4 = new();
-  write(obj4, 1);
-  read(obj4);
-  write(obj4, 2);
-  read(obj4);
-  write(obj4, "three");
-  read(obj4);
-}
-
-function mkobj() {
-  newobj = new();
-  newobj.z = "zzz";
-  return newobj;
-}
-
-function read(obj) {
-  return obj.prop;
-}
-
-function write(obj, value) {
-  return obj.prop = value;
-}
--- a/graal/com.oracle.truffle.sl.test/tests/String.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-snull
-snull
-sbar
-sfoo
-nulls
-nulls
-bars
-foos
-2 < 4: true
-Type error at String.sl line 9 col 34: operation "<" not defined for Number 2, String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/String.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-function null() {
-}
-
-function foo() {
-  return "bar";
-}
-
-function f(a, b) {
-  return a + " < " + b + ": " + (a < b);
-}
-
-function main() {  
-  println("s" + null());  
-  println("s" + null);  
-  println("s" + foo());  
-  println("s" + foo);
-    
-  println(null() + "s");  
-  println(null() + "s");  
-  println(foo() + "s");  
-  println(foo + "s");
-
-  println(f(2, 4));
-  println(f(2, "4"));
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Sub.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
--1
--3999999999997
-2999999999996
--1000000000000
--- a/graal/com.oracle.truffle.sl.test/tests/Sub.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-function main() {  
-  println(3 - 4);  
-  println(3 - 4000000000000);  
-  println(3000000000000 - 4);  
-  println(3000000000000 - 4000000000000);  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/Sum.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-50005000
--- a/graal/com.oracle.truffle.sl.test/tests/Sum.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-function main() {  
-  i = 0;  
-  sum = 0;  
-  while (i <= 10000) {  
-    sum = sum + i;  
-    i = i + 1;  
-  }  
-  return sum;  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError01.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error at TypeError01.sl line 2 col 3: operation "-" not defined for Number 3, String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError01.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  3 - "4";  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error at TypeError02.sl line 2 col 3: operation "if" not defined for String "4"
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError02.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  if ("4") { }  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError03.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error at TypeError03.sl line 2 col 3: operation "&&" not defined for String "4", ANY
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError03.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  "4" && 4;  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error at TypeError04.sl line 2 col 3: operation "||" not defined for Boolean false, Number 4
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError04.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  (1 > 2) || 4;  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError05.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error at TypeError05.sl line 3 col 3: operation "invoke" not defined for Boolean true
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError05.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-function main() {
-  f = 1 < 2;
-  f();  
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError06.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error: operation "defineFunction" not defined for Number 3
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError06.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {
-  defineFunction(3);
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError07.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Type error: operation "defineFunction" not defined for NULL
--- a/graal/com.oracle.truffle.sl.test/tests/error/TypeError07.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {
-  defineFunction();
-}  
--- a/graal/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Undefined function: foo
--- a/graal/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function main() {  
-  foo();
-}  
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-100
-0
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
-87
-88
-89
-90
-91
-92
-93
-94
-95
-96
-97
-98
-99
-100
-100
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-function loop(count) {  
-  i = 0;  
-  while (i < count) {  
-    i = i + 1;  
-  }  
-  return i;  
-}
-
-function main() {
-  count = loop(100);
-}
--- a/graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.tools.debug;
-
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.debug.shell.*;
-import com.oracle.truffle.tools.debug.shell.client.*;
-import com.oracle.truffle.tools.debug.shell.server.*;
-
-/**
- * Instantiation of the "server handler" part of the "REPL*" debugger for the simple language.
- * <p>
- * These handlers implement debugging commands that require language-specific support.
- *
- * @see SimpleREPLClient
- */
-public abstract class SLREPLHandler extends REPLHandler {
-
-    protected SLREPLHandler(String op) {
-        super(op);
-    }
-
-    public static final SLREPLHandler INFO_HANDLER = new SLREPLHandler(REPLMessage.INFO) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final String topic = request.get(REPLMessage.TOPIC);
-
-            if (topic == null || topic.isEmpty()) {
-                final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
-                return finishReplyFailed(message, "No info topic specified");
-            }
-
-            switch (topic) {
-
-                case REPLMessage.LANGUAGE:
-                    return createLanguageInfoReply();
-
-                default:
-                    final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
-                    return finishReplyFailed(message, "No info about topic \"" + topic + "\"");
-            }
-        }
-    };
-
-    private static REPLMessage[] createLanguageInfoReply() {
-        final ArrayList<REPLMessage> langMessages = new ArrayList<>();
-
-        final REPLMessage msg1 = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
-        msg1.put(REPLMessage.TOPIC, REPLMessage.LANGUAGE);
-        msg1.put(REPLMessage.INFO_KEY, "Language");
-        msg1.put(REPLMessage.INFO_VALUE, "Simple");
-        msg1.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-        langMessages.add(msg1);
-
-        return langMessages.toArray(new REPLMessage[0]);
-    }
-
-    public static final SLREPLHandler LOAD_RUN_SOURCE_HANDLER = new SLREPLHandler(REPLMessage.LOAD_RUN) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            return loadHandler(request, serverContext, false);
-        }
-    };
-
-    public static final SLREPLHandler LOAD_STEP_SOURCE_HANDLER = new SLREPLHandler(REPLMessage.LOAD_STEP) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            return loadHandler(request, serverContext, true);
-        }
-    };
-
-    /**
-     * Runs a source, optionally stepping into a specified tag.
-     */
-    private static REPLMessage[] loadHandler(REPLMessage request, REPLServerContext serverContext, boolean stepInto) {
-        final REPLMessage reply = new REPLMessage(REPLMessage.OP, REPLMessage.LOAD_RUN);
-        final String fileName = request.get(REPLMessage.SOURCE_NAME);
-        try {
-            final Source source = Source.fromFileName(fileName, true);
-            if (source == null) {
-                return finishReplyFailed(reply, "can't find file \"" + fileName + "\"");
-            }
-            serverContext.getDebugEngine().run(source, stepInto);
-            reply.put(REPLMessage.FILE_PATH, source.getPath());
-            return finishReplySucceeded(reply, source.getName() + "  exited");
-        } catch (QuitException ex) {
-            throw ex;
-        } catch (KillException ex) {
-            return finishReplySucceeded(reply, fileName + " killed");
-        } catch (Exception ex) {
-            return finishReplyFailed(reply, "error loading file \"" + fileName + "\": " + ex.getMessage());
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.tools.debug;
-
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.tools.debug.engine.*;
-import com.oracle.truffle.tools.debug.shell.*;
-import com.oracle.truffle.tools.debug.shell.client.*;
-import com.oracle.truffle.tools.debug.shell.server.*;
-
-/**
- * Instantiation of the "server" side of the "REPL*" debugger for the Simple language.
- * <p>
- * The SL parser is not equipped to parse program fragments, so any debugging functions that depend
- * on this are not supported, for example {@link DebugEngine#eval(Source, Node, MaterializedFrame)}
- * and {@link Breakpoint#setCondition(String)}.
- *
- * @see SimpleREPLClient
- */
-public final class SLREPLServer implements REPLServer {
-
-    // TODO (mlvdv) remove when there's a better way to express this dependency
-    @SuppressWarnings("unused") private static final Class<SLLanguage> DYNAMIC_DEPENDENCY = com.oracle.truffle.sl.SLLanguage.class;
-
-    public static void main(String[] args) {
-        // Cheating for the prototype: start from SL, rather than from the client.
-        final SLREPLServer server = new SLREPLServer();
-        final SimpleREPLClient client = new SimpleREPLClient(server.language.getShortName(), server);
-
-        // Cheating for the prototype: allow server access to client for recursive debugging
-        server.setClient(client);
-
-        try {
-            client.start();
-        } catch (QuitException ex) {
-        }
-    }
-
-    private final Language language;
-    private final DebugEngine slDebugEngine;
-    private final String statusPrefix;
-    private final Map<String, REPLHandler> handlerMap = new HashMap<>();
-    private SLServerContext currentServerContext;
-    private SimpleREPLClient replClient = null;
-
-    private void add(REPLHandler fileHandler) {
-        handlerMap.put(fileHandler.getOp(), fileHandler);
-    }
-
-    public SLREPLServer() {
-        add(REPLHandler.BACKTRACE_HANDLER);
-        add(REPLHandler.BREAK_AT_LINE_HANDLER);
-        add(REPLHandler.BREAK_AT_LINE_ONCE_HANDLER);
-        add(REPLHandler.BREAK_AT_THROW_HANDLER);
-        add(REPLHandler.BREAK_AT_THROW_ONCE_HANDLER);
-        add(REPLHandler.BREAKPOINT_INFO_HANDLER);
-        add(REPLHandler.CLEAR_BREAK_HANDLER);
-        add(REPLHandler.CONTINUE_HANDLER);
-        add(REPLHandler.DELETE_HANDLER);
-        add(REPLHandler.DISABLE_BREAK_HANDLER);
-        add(REPLHandler.ENABLE_BREAK_HANDLER);
-        add(REPLHandler.FILE_HANDLER);
-        add(REPLHandler.FRAME_HANDLER);
-        add(SLREPLHandler.INFO_HANDLER);
-        add(REPLHandler.KILL_HANDLER);
-        add(SLREPLHandler.LOAD_RUN_SOURCE_HANDLER);
-        add(SLREPLHandler.LOAD_STEP_SOURCE_HANDLER);
-        add(REPLHandler.QUIT_HANDLER);
-        add(REPLHandler.STEP_INTO_HANDLER);
-        add(REPLHandler.STEP_OUT_HANDLER);
-        add(REPLHandler.STEP_OVER_HANDLER);
-        add(REPLHandler.TRUFFLE_HANDLER);
-        add(REPLHandler.TRUFFLE_NODE_HANDLER);
-
-        TruffleVM vm = TruffleVM.newVM().build();
-        this.language = vm.getLanguages().get("application/x-sl");
-        assert language != null;
-
-        final SLREPLDebugClient slDebugClient = new SLREPLDebugClient(language);
-        this.slDebugEngine = DebugEngine.create(slDebugClient, language);
-
-        this.statusPrefix = language.getShortName() + " REPL:";
-    }
-
-    private void setClient(SimpleREPLClient replClient) {
-        this.replClient = replClient;
-    }
-
-    public REPLMessage start() {
-
-        this.currentServerContext = new SLServerContext(null, null, null);
-
-        // SL doesn't load modules (like other languages), so we just return a success
-        final REPLMessage reply = new REPLMessage();
-        reply.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-        reply.put(REPLMessage.DISPLAY_MSG, language.getShortName() + " started");
-        return reply;
-    }
-
-    public REPLMessage[] receive(REPLMessage request) {
-        if (currentServerContext == null) {
-            final REPLMessage message = new REPLMessage();
-            message.put(REPLMessage.STATUS, REPLMessage.FAILED);
-            message.put(REPLMessage.DISPLAY_MSG, "server not started");
-            final REPLMessage[] reply = new REPLMessage[]{message};
-            return reply;
-        }
-        return currentServerContext.receive(request);
-    }
-
-    /**
-     * Execution context of a halted SL program.
-     */
-    public final class SLServerContext extends REPLServerContext {
-
-        private final SLServerContext predecessor;
-
-        public SLServerContext(SLServerContext predecessor, Node astNode, MaterializedFrame mFrame) {
-            super(predecessor == null ? 0 : predecessor.getLevel() + 1, astNode, mFrame);
-            this.predecessor = predecessor;
-        }
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request) {
-            final String command = request.get(REPLMessage.OP);
-            final REPLHandler handler = handlerMap.get(command);
-
-            if (handler == null) {
-                final REPLMessage message = new REPLMessage();
-                message.put(REPLMessage.OP, command);
-                message.put(REPLMessage.STATUS, REPLMessage.FAILED);
-                message.put(REPLMessage.DISPLAY_MSG, statusPrefix + " op \"" + command + "\" not supported");
-                final REPLMessage[] reply = new REPLMessage[]{message};
-                return reply;
-            }
-            return handler.receive(request, currentServerContext);
-        }
-
-        @Override
-        public Language getLanguage() {
-            return language;
-        }
-
-        @Override
-        public DebugEngine getDebugEngine() {
-            return slDebugEngine;
-        }
-
-    }
-
-    /**
-     * Specialize the standard SL debug context by notifying the REPL client when execution is
-     * halted, e.g. at a breakpoint.
-     * <p>
-     * Before notification, the server creates a new context at the halted location, in which
-     * subsequent evaluations take place until such time as the client says to "continue".
-     * <p>
-     * This implementation "cheats" the intended asynchronous architecture by calling back directly
-     * to the client with the notification.
-     */
-    private final class SLREPLDebugClient implements DebugClient {
-
-        private final Language language;
-
-        SLREPLDebugClient(Language language) {
-            this.language = language;
-        }
-
-        public void haltedAt(Node node, MaterializedFrame mFrame, List<String> warnings) {
-            // Create and push a new debug context where execution is halted
-            currentServerContext = new SLServerContext(currentServerContext, node, mFrame);
-
-            // Message the client that execution is halted and is in a new debugging context
-            final REPLMessage message = new REPLMessage();
-            message.put(REPLMessage.OP, REPLMessage.STOPPED);
-            final SourceSection src = node.getSourceSection();
-            final Source source = src.getSource();
-            message.put(REPLMessage.SOURCE_NAME, source.getName());
-            message.put(REPLMessage.FILE_PATH, source.getPath());
-            message.put(REPLMessage.LINE_NUMBER, Integer.toString(src.getStartLine()));
-            message.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-            message.put(REPLMessage.DEBUG_LEVEL, Integer.toString(currentServerContext.getLevel()));
-            if (!warnings.isEmpty()) {
-                final StringBuilder sb = new StringBuilder();
-                for (String warning : warnings) {
-                    sb.append(warning + "\n");
-                }
-                message.put(REPLMessage.WARNINGS, sb.toString());
-            }
-            try {
-                // Cheat with synchrony: call client directly about entering a nested debugging
-                // context.
-                replClient.halted(message);
-            } finally {
-                // Returns when "continue" is called in the new debugging context
-
-                // Pop the debug context, and return so that the old context will continue
-                currentServerContext = currentServerContext.predecessor;
-            }
-        }
-
-        public Language getLanguage() {
-            return language;
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl;
-
-/**
- * An implementation of an {@link AssertionError} also containing the guest language stack trace.
- */
-public class SLAssertionError extends AssertionError {
-
-    private static final long serialVersionUID = -9138475336963945873L;
-
-    public SLAssertionError(String message) {
-        super(message);
-        initCause(new AssertionError("Java stack trace"));
-    }
-
-    @Override
-    public synchronized Throwable fillInStackTrace() {
-        return SLException.fillInSLStackTrace(this);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * SL does not need a sophisticated error checking and reporting mechanism, so all unexpected
- * conditions just abort execution. This exception class is used when we abort from within the SL
- * implementation.
- */
-public class SLException extends RuntimeException {
-
-    private static final long serialVersionUID = -6799734410727348507L;
-
-    public SLException(String message) {
-        super(message);
-        initCause(new Throwable("Java stack trace"));
-    }
-
-    @Override
-    public synchronized Throwable fillInStackTrace() {
-        return fillInSLStackTrace(this);
-    }
-
-    /**
-     * Uses the Truffle API to iterate the stack frames and to create and set Java
-     * {@link StackTraceElement} elements based on the source sections of the call nodes on the
-     * stack.
-     */
-    static Throwable fillInSLStackTrace(Throwable t) {
-        final List<StackTraceElement> stackTrace = new ArrayList<>();
-        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
-            public Void visitFrame(FrameInstance frame) {
-                Node callNode = frame.getCallNode();
-                if (callNode == null) {
-                    return null;
-                }
-                RootNode root = callNode.getRootNode();
-
-                /*
-                 * There should be no RootNodes other than SLRootNodes on the stack. Just for the
-                 * case if this would change.
-                 */
-                String methodName = "$unknownFunction";
-                if (root instanceof SLRootNode) {
-                    methodName = ((SLRootNode) root).getName();
-                }
-
-                SourceSection sourceSection = callNode.getEncapsulatingSourceSection();
-                Source source = sourceSection != null ? sourceSection.getSource() : null;
-                String sourceName = source != null ? source.getName() : null;
-                int lineNumber;
-                try {
-                    lineNumber = sourceSection != null ? sourceSection.getLineLocation().getLineNumber() : -1;
-                } catch (UnsupportedOperationException e) {
-                    /*
-                     * SourceSection#getLineLocation() may throw an UnsupportedOperationException.
-                     */
-                    lineNumber = -1;
-                }
-                stackTrace.add(new StackTraceElement("SL", methodName, sourceName, lineNumber));
-                return null;
-            }
-        });
-        t.setStackTrace(stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
-        return t;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl;
-
-import java.io.*;
-import java.math.*;
-import java.net.*;
-import java.util.*;
-import java.util.Scanner;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.*;
-import com.oracle.truffle.api.vm.TruffleVM.Symbol;
-import com.oracle.truffle.sl.builtins.*;
-import com.oracle.truffle.sl.factory.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.call.*;
-import com.oracle.truffle.sl.nodes.controlflow.*;
-import com.oracle.truffle.sl.nodes.expression.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
-import com.oracle.truffle.sl.nodes.local.*;
-import com.oracle.truffle.sl.parser.*;
-import com.oracle.truffle.sl.runtime.*;
-import com.oracle.truffle.tools.*;
-
-/**
- * SL is a simple language to demonstrate and showcase features of Truffle. The implementation is as
- * simple and clean as possible in order to help understanding the ideas and concepts of Truffle.
- * The language has first class functions, but no object model.
- * <p>
- * SL is dynamically typed, i.e., there are no type names specified by the programmer. SL is
- * strongly typed, i.e., there is no automatic conversion between types. If an operation is not
- * available for the types encountered at run time, a type error is reported and execution is
- * stopped. For example, {@code 4 - "2"} results in a type error because subtraction is only defined
- * for numbers.
- *
- * <p>
- * <b>Types:</b>
- * <ul>
- * <li>Number: arbitrary precision integer numbers. The implementation uses the Java primitive type
- * {@code long} to represent numbers that fit into the 64 bit range, and {@link BigInteger} for
- * numbers that exceed the range. Using a primitive type such as {@code long} is crucial for
- * performance.
- * <li>Boolean: implemented as the Java primitive type {@code boolean}.
- * <li>String: implemented as the Java standard type {@link String}.
- * <li>Function: implementation type {@link SLFunction}.
- * <li>Null (with only one value {@code null}): implemented as the singleton
- * {@link SLNull#SINGLETON}.
- * </ul>
- * The class {@link SLTypes} lists these types for the Truffle DSL, i.e., for type-specialized
- * operations that are specified using Truffle DSL annotations.
- *
- * <p>
- * <b>Language concepts:</b>
- * <ul>
- * <li>Literals for {@link SLBigIntegerLiteralNode numbers} , {@link SLStringLiteralNode strings},
- * and {@link SLFunctionLiteralNode functions}.
- * <li>Basic arithmetic, logical, and comparison operations: {@link SLAddNode +}, {@link SLSubNode
- * -}, {@link SLMulNode *}, {@link SLDivNode /}, {@link SLLogicalAndNode logical and},
- * {@link SLLogicalOrNode logical or}, {@link SLEqualNode ==}, !=, {@link SLLessThanNode &lt;},
- * {@link SLLessOrEqualNode &le;}, &gt;, &ge;.
- * <li>Local variables: local variables must be defined (via a {@link SLWriteLocalVariableNode
- * write}) before they can be used (by a {@link SLReadLocalVariableNode read}). Local variables are
- * not visible outside of the block where they were first defined.
- * <li>Basic control flow statements: {@link SLBlockNode blocks}, {@link SLIfNode if},
- * {@link SLWhileNode while} with {@link SLBreakNode break} and {@link SLContinueNode continue},
- * {@link SLReturnNode return}.
- * <li>Function calls: {@link SLInvokeNode invocations} are efficiently implemented with
- * {@link SLDispatchNode polymorphic inline caches}.
- * </ul>
- *
- * <p>
- * <b>Syntax and parsing:</b><br>
- * The syntax is described as an attributed grammar. The {@link Parser} and {@link Scanner} are
- * automatically generated by the parser generator Coco/R (available from <a
- * href="http://ssw.jku.at/coco/">http://ssw.jku.at/coco/</a>). The grammar contains semantic
- * actions that build the AST for a method. To keep these semantic actions short, they are mostly
- * calls to the {@link SLNodeFactory} that performs the actual node creation. All functions found in
- * the SL source are added to the {@link SLFunctionRegistry}, which is accessible from the
- * {@link SLContext}.
- *
- * <p>
- * <b>Builtin functions:</b><br>
- * Library functions that are available to every SL source without prior definition are called
- * builtin functions. They are added to the {@link SLFunctionRegistry} when the {@link SLContext} is
- * created. There current builtin functions are
- * <ul>
- * <li>{@link SLReadlnBuiltin readln}: Read a String from the {@link SLContext#getInput() standard
- * input}.
- * <li>{@link SLPrintlnBuiltin println}: Write a value to the {@link SLContext#getOutput() standard
- * output}.
- * <li>{@link SLNanoTimeBuiltin nanoTime}: Returns the value of a high-resolution time, in
- * nanoseconds.
- * <li>{@link SLDefineFunctionBuiltin defineFunction}: Parses the functions provided as a String
- * argument and adds them to the function registry. Functions that are already defined are replaced
- * with the new version.
- * </ul>
- *
- * <p>
- * <b>Tools:</b><br>
- * The use of some of Truffle's support for developer tools (based on the Truffle Instrumentation
- * Framework) are demonstrated in this file, for example:
- * <ul>
- * <li>a {@linkplain NodeExecCounter counter for node executions}, tabulated by node type; and</li>
- * <li>a simple {@linkplain CoverageTracker code coverage engine}.</li>
- * </ul>
- * In each case, the tool is enabled if a corresponding local boolean variable in this file is set
- * to {@code true}. Results are printed at the end of the execution using each tool's
- * <em>default printer</em>.
- *
- */
-@TruffleLanguage.Registration(name = "SL", version = "0.5", mimeType = "application/x-sl")
-public class SLLanguage extends TruffleLanguage {
-    private static SLLanguage LAST;
-    private static List<NodeFactory<? extends SLBuiltinNode>> builtins = Collections.emptyList();
-    private static Visualizer visualizer = new SLDefaultVisualizer();
-    private static ASTProber registeredASTProber; // non-null if prober already registered
-    private final SLContext context;
-    private DebugSupportProvider debugSupport;
-
-    public SLLanguage(Env env) {
-        super(env);
-        context = SLContextFactory.create(new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true));
-        LAST = this;
-        for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
-            context.installBuiltin(builtin);
-        }
-    }
-
-    // TODO (mlvdv) command line options
-    /* Enables demonstration of per-type tabulation of node execution counts */
-    private static boolean nodeExecCounts = false;
-    /* Enables demonstration of per-line tabulation of STATEMENT node execution counts */
-    private static boolean statementCounts = false;
-    /* Enables demonstration of per-line tabulation of STATEMENT coverage */
-    private static boolean coverage = false;
-
-    /* Small tools that can be installed for demonstration */
-    private static NodeExecCounter nodeExecCounter = null;
-    private static NodeExecCounter statementExecCounter = null;
-    private static CoverageTracker coverageTracker = null;
-
-    /**
-     * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup.
-     */
-    public static void main(String[] args) throws IOException {
-        TruffleVM vm = TruffleVM.newVM().build();
-        assert vm.getLanguages().containsKey("application/x-sl");
-
-        setupToolDemos();
-
-        int repeats = 1;
-        if (args.length >= 2) {
-            repeats = Integer.parseInt(args[1]);
-        }
-
-        if (args.length == 0) {
-            vm.eval("application/x-sl", new InputStreamReader(System.in));
-        } else {
-            vm.eval(new File(args[0]).toURI());
-        }
-        Symbol main = vm.findGlobalSymbol("main");
-        if (main == null) {
-            throw new SLException("No function main() defined in SL source file.");
-        }
-        while (repeats-- > 0) {
-            main.invoke(null);
-        }
-        reportToolDemos();
-    }
-
-    /**
-     * Temporary method during API evolution, supports debugger integration.
-     */
-    public static void run(Source source) throws IOException {
-        TruffleVM vm = TruffleVM.newVM().build();
-        assert vm.getLanguages().containsKey("application/x-sl");
-        vm.eval(new File(source.getPath()).toURI());
-        Symbol main = vm.findGlobalSymbol("main");
-        if (main == null) {
-            throw new SLException("No function main() defined in SL source file.");
-        }
-        main.invoke(null);
-    }
-
-    /**
-     * Parse and run the specified SL source. Factored out in a separate method so that it can also
-     * be used by the unit test harness.
-     */
-    public static long run(TruffleVM context, URI source, PrintWriter logOutput, PrintWriter out, int repeats, List<NodeFactory<? extends SLBuiltinNode>> currentBuiltins) throws IOException {
-        builtins = currentBuiltins;
-
-        if (logOutput != null) {
-            logOutput.println("== running on " + Truffle.getRuntime().getName());
-            // logOutput.println("Source = " + source.getCode());
-        }
-
-        /* Parse the SL source file. */
-        Object result = context.eval(source);
-        if (result != null) {
-            out.println(result);
-        }
-
-        /* Lookup our main entry point, which is per definition always named "main". */
-        Symbol main = context.findGlobalSymbol("main");
-        if (main == null) {
-            throw new SLException("No function main() defined in SL source file.");
-        }
-
-        /* Change to true if you want to see the AST on the console. */
-        boolean printASTToLog = false;
-        /* Change to true if you want to see source attribution for the AST to the console */
-        boolean printSourceAttributionToLog = false;
-        /* Change to dump the AST to IGV over the network. */
-        boolean dumpASTToIGV = false;
-
-        printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
-        long totalRuntime = 0;
-        try {
-            for (int i = 0; i < repeats; i++) {
-                long start = System.nanoTime();
-                /* Call the main entry point, without any arguments. */
-                try {
-                    result = main.invoke(null);
-                    if (result != null) {
-                        out.println(result);
-                    }
-                } catch (UnsupportedSpecializationException ex) {
-                    out.println(formatTypeError(ex));
-                } catch (SLUndefinedFunctionException ex) {
-                    out.println(String.format("Undefined function: %s", ex.getFunctionName()));
-                }
-                long end = System.nanoTime();
-                totalRuntime += end - start;
-
-                if (logOutput != null && repeats > 1) {
-                    logOutput.println("== iteration " + (i + 1) + ": " + ((end - start) / 1000000) + " ms");
-                }
-            }
-
-        } finally {
-            printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
-        }
-        return totalRuntime;
-    }
-
-    /**
-     * When dumpASTToIGV is true: dumps the AST of all functions to the IGV visualizer, via a socket
-     * connection. IGV can be started with the mx command "mx igv".
-     * <p>
-     * When printASTToLog is true: prints the ASTs to the console.
-     */
-    private static void printScript(String groupName, SLContext context, PrintWriter logOutput, boolean printASTToLog, boolean printSourceAttributionToLog, boolean dumpASTToIGV) {
-        if (dumpASTToIGV) {
-            GraphPrintVisitor graphPrinter = new GraphPrintVisitor();
-            graphPrinter.beginGroup(groupName);
-            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
-                RootCallTarget callTarget = function.getCallTarget();
-                if (callTarget != null) {
-                    graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode());
-                }
-            }
-            graphPrinter.printToNetwork(true);
-        }
-        if (printASTToLog && logOutput != null) {
-            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
-                RootCallTarget callTarget = function.getCallTarget();
-                if (callTarget != null) {
-                    logOutput.println("=== " + function);
-                    NodeUtil.printTree(logOutput, callTarget.getRootNode());
-                }
-            }
-        }
-        if (printSourceAttributionToLog && logOutput != null) {
-            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
-                RootCallTarget callTarget = function.getCallTarget();
-                if (callTarget != null) {
-                    logOutput.println("=== " + function);
-                    NodeUtil.printSourceAttributionTree(logOutput, callTarget.getRootNode());
-                }
-            }
-        }
-    }
-
-    /**
-     * Provides a user-readable message for run-time type errors. SL is strongly typed, i.e., there
-     * are no automatic type conversions of values. Therefore, Truffle does the type checking for
-     * us: if no matching node specialization for the actual values is found, then we have a type
-     * error. Specialized nodes use the {@link UnsupportedSpecializationException} to report that no
-     * specialization was found. We therefore just have to convert the information encapsulated in
-     * this exception in a user-readable form.
-     */
-    private static String formatTypeError(UnsupportedSpecializationException ex) {
-        StringBuilder result = new StringBuilder();
-        result.append("Type error");
-        if (ex.getNode() != null && ex.getNode().getSourceSection() != null) {
-            SourceSection ss = ex.getNode().getSourceSection();
-            if (ss != null && !(ss instanceof NullSourceSection)) {
-                result.append(" at ").append(ss.getSource().getShortName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn());
-            }
-        }
-        result.append(": operation");
-        if (ex.getNode() != null) {
-            NodeInfo nodeInfo = SLContext.lookupNodeInfo(ex.getNode().getClass());
-            if (nodeInfo != null) {
-                result.append(" \"").append(nodeInfo.shortName()).append("\"");
-            }
-        }
-        result.append(" not defined for");
-
-        String sep = " ";
-        for (int i = 0; i < ex.getSuppliedValues().length; i++) {
-            Object value = ex.getSuppliedValues()[i];
-            Node node = ex.getSuppliedNodes()[i];
-            if (node != null) {
-                result.append(sep);
-                sep = ", ";
-
-                if (value instanceof Long || value instanceof BigInteger) {
-                    result.append("Number ").append(value);
-                } else if (value instanceof Boolean) {
-                    result.append("Boolean ").append(value);
-                } else if (value instanceof String) {
-                    result.append("String \"").append(value).append("\"");
-                } else if (value instanceof SLFunction) {
-                    result.append("Function ").append(value);
-                } else if (value == SLNull.SINGLETON) {
-                    result.append("NULL");
-                } else if (value == null) {
-                    // value is not evaluated because of short circuit evaluation
-                    result.append("ANY");
-                } else {
-                    result.append(value);
-                }
-            }
-        }
-        return result.toString();
-    }
-
-    @Override
-    protected Object eval(Source code) throws IOException {
-        try {
-            context.evalSource(code);
-        } catch (Exception e) {
-            throw new IOException(e);
-        }
-        return null;
-    }
-
-    @Override
-    protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
-        for (SLFunction f : context.getFunctionRegistry().getFunctions()) {
-            if (globalName.equals(f.getName())) {
-                return f;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    protected Object getLanguageGlobal() {
-        return context;
-    }
-
-    @Override
-    protected boolean isObjectOfLanguage(Object object) {
-        return object instanceof SLFunction;
-    }
-
-    @Override
-    protected ToolSupportProvider getToolSupport() {
-        return getDebugSupport();
-    }
-
-    @Override
-    protected DebugSupportProvider getDebugSupport() {
-        if (debugSupport == null) {
-            debugSupport = new SLDebugProvider();
-        }
-        return debugSupport;
-    }
-
-    // TODO (mlvdv) remove the static hack when we no longer have the static demo variables
-    private static void setupToolDemos() {
-        if (statementCounts || coverage) {
-            if (registeredASTProber == null) {
-                final ASTProber newProber = new SLStandardASTProber();
-                // This should be registered on the TruffleVM
-                Probe.registerASTProber(newProber);
-                registeredASTProber = newProber;
-            }
-        }
-        if (nodeExecCounts) {
-            nodeExecCounter = new NodeExecCounter();
-            nodeExecCounter.install();
-        }
-
-        if (statementCounts) {
-            statementExecCounter = new NodeExecCounter(StandardSyntaxTag.STATEMENT);
-            statementExecCounter.install();
-        }
-
-        if (coverage) {
-            coverageTracker = new CoverageTracker();
-            coverageTracker.install();
-        }
-    }
-
-    private static void reportToolDemos() {
-        if (nodeExecCounter != null) {
-            nodeExecCounter.print(System.out);
-            nodeExecCounter.dispose();
-        }
-        if (statementExecCounter != null) {
-            statementExecCounter.print(System.out);
-            statementExecCounter.dispose();
-        }
-        if (coverageTracker != null) {
-            coverageTracker.print(System.out);
-            coverageTracker.dispose();
-        }
-    }
-
-    private final class SLDebugProvider implements DebugSupportProvider {
-
-        public SLDebugProvider() {
-            if (registeredASTProber == null) {
-                registeredASTProber = new SLStandardASTProber();
-                // This should be registered on the TruffleVM
-                Probe.registerASTProber(registeredASTProber);
-            }
-        }
-
-        public Visualizer getVisualizer() {
-            if (visualizer == null) {
-                visualizer = new SLDefaultVisualizer();
-            }
-            return visualizer;
-        }
-
-        public void enableASTProbing(ASTProber prober) {
-            if (prober != null) {
-                // This should be registered on the TruffleVM
-                Probe.registerASTProber(prober);
-            }
-        }
-
-        public void run(Source source) throws DebugSupportException {
-            // TODO (mlvdv) fix to run properly in the current VM
-            try {
-                SLLanguage.run(source);
-            } catch (Exception e) {
-                throw new DebugSupportException(e);
-            }
-        }
-
-        public Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException {
-            throw new DebugSupportException("evalInContext not supported in this language");
-        }
-
-        public AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException {
-            throw new DebugSupportException("createAdvancedInstrumentRootFactory not supported in this language");
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Asserts a given value to be <code>false</code> and throws an {@link AssertionError} if the value
- * was <code>true</code>.
- */
-@NodeInfo(shortName = "assertFalse")
-public abstract class SLAssertFalseBuiltin extends SLBuiltinNode {
-
-    public SLAssertFalseBuiltin() {
-        super(new NullSourceSection("SL builtin", "assertFalse"));
-    }
-
-    @Specialization
-    public boolean doAssert(boolean value, String message) {
-        if (value) {
-            CompilerDirectives.transferToInterpreter();
-            throw new SLAssertionError(message == null ? "" : message);
-        }
-        return value;
-    }
-
-    @Specialization
-    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
-        return doAssert(value, null);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Asserts a given value to be <code>true</code> and throws an {@link AssertionError} if the value
- * was <code>false</code>.
- */
-@NodeInfo(shortName = "assertTrue")
-public abstract class SLAssertTrueBuiltin extends SLBuiltinNode {
-
-    public SLAssertTrueBuiltin() {
-        super(new NullSourceSection("SL builtin", "assertTrue"));
-    }
-
-    @Specialization
-    public boolean doAssert(boolean value, String message) {
-        if (!value) {
-            CompilerDirectives.transferToInterpreter();
-            throw new SLAssertionError(message == null ? "" : message);
-        }
-        return value;
-    }
-
-    @Specialization
-    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
-        return doAssert(value, null);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Base class for all builtin functions. It contains the Truffle DSL annotation {@link NodeChild}
- * that defines the function arguments.<br>
- * Builtin functions need access to the {@link SLContext}. Instead of defining a Java field manually
- * and setting it in a constructor, we use the Truffle DSL annotation {@link NodeField} that
- * generates the field and constructor automatically.
- * <p>
- * The builtin functions are registered in {@link SLContext#installBuiltins}. Every builtin node
- * subclass is instantiated there, wrapped into a function, and added to the
- * {@link SLFunctionRegistry}. This ensures that builtin functions can be called like user-defined
- * functions; there is no special function lookup or call node for builtin functions.
- */
-@NodeChild(value = "arguments", type = SLExpressionNode[].class)
-@NodeField(name = "context", type = SLContext.class)
-@GenerateNodeFactory
-public abstract class SLBuiltinNode extends SLExpressionNode {
-
-    public SLBuiltinNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * Accessor for the {@link SLContext}. The implementation of this method is generated
-     * automatically based on the {@link NodeField} annotation on the class.
-     */
-    public abstract SLContext getContext();
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.parser.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Builtin function to define (or redefine) functions. The provided source code is parsed the same
- * way as the initial source of the script, so the same syntax applies.
- */
-@NodeInfo(shortName = "defineFunction")
-public abstract class SLDefineFunctionBuiltin extends SLBuiltinNode {
-
-    public SLDefineFunctionBuiltin() {
-        super(new NullSourceSection("SL builtin", "defineFunction"));
-    }
-
-    @Specialization
-    public String defineFunction(String code) {
-        doDefineFunction(getContext(), code);
-        return code;
-    }
-
-    @TruffleBoundary
-    private static void doDefineFunction(SLContext context, String code) {
-        Source source = Source.fromText(code, "[defineFunction]");
-        /* The same parsing code as for parsing the initial source. */
-        Parser.parseSL(context, source);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * This builtin sets the variable named "hello" in the caller frame to the string "world".
- */
-@NodeInfo(shortName = "helloEqualsWorld")
-public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode {
-
-    public SLHelloEqualsWorldBuiltin() {
-        super(new NullSourceSection("SL builtin", "helloEqualsWorld"));
-    }
-
-    @Specialization
-    @TruffleBoundary
-    public String change() {
-        FrameInstance frameInstance = Truffle.getRuntime().getCallerFrame();
-        Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false);
-        FrameSlot slot = frame.getFrameDescriptor().findOrAddFrameSlot("hello");
-        frame.setObject(slot, "world");
-        return "world";
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Builtin function that returns the value of a high-resolution time, in nanoseconds.
- */
-@NodeInfo(shortName = "nanoTime")
-public abstract class SLNanoTimeBuiltin extends SLBuiltinNode {
-
-    public SLNanoTimeBuiltin() {
-        super(new NullSourceSection("SL builtin", "nanoTime"));
-    }
-
-    @Specialization
-    public long nanoTime() {
-        return System.nanoTime();
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Built-in function to create a new object. Objects in SL are simply made up of name/value pairs.
- */
-@NodeInfo(shortName = "new")
-public abstract class SLNewObjectBuiltin extends SLBuiltinNode {
-
-    public SLNewObjectBuiltin() {
-        super(new NullSourceSection("SL builtin", "new"));
-    }
-
-    @Specialization
-    public Object newObject() {
-        return getContext().createObject();
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import java.io.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Builtin function to write a value to the {@link SLContext#getOutput() standard output}. The
- * different specialization leverage the typed {@code println} methods available in Java, i.e.,
- * primitive values are printed without converting them to a {@link String} first.
- * <p>
- * Printing involves a lot of Java code, so we need to tell the optimizing system that it should not
- * unconditionally inline everything reachable from the println() method. This is done via the
- * {@link TruffleBoundary} annotations.
- */
-@NodeInfo(shortName = "println")
-public abstract class SLPrintlnBuiltin extends SLBuiltinNode {
-
-    public SLPrintlnBuiltin() {
-        super(new NullSourceSection("SL builtin", "println"));
-    }
-
-    @Specialization
-    public long println(long value) {
-        doPrint(getContext().getOutput(), value);
-        return value;
-    }
-
-    @TruffleBoundary
-    private static void doPrint(PrintWriter out, long value) {
-        out.println(value);
-    }
-
-    @Specialization
-    public boolean println(boolean value) {
-        doPrint(getContext().getOutput(), value);
-        return value;
-    }
-
-    @TruffleBoundary
-    private static void doPrint(PrintWriter out, boolean value) {
-        out.println(value);
-    }
-
-    @Specialization
-    public String println(String value) {
-        doPrint(getContext().getOutput(), value);
-        return value;
-    }
-
-    @TruffleBoundary
-    private static void doPrint(PrintWriter out, String value) {
-        out.println(value);
-    }
-
-    @Specialization
-    public Object println(Object value) {
-        doPrint(getContext().getOutput(), value);
-        return value;
-    }
-
-    @TruffleBoundary
-    private static void doPrint(PrintWriter out, Object value) {
-        out.println(value);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import java.io.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Builtin function that reads a String from the {@link SLContext#getInput() standard input}.
- */
-@NodeInfo(shortName = "readln")
-public abstract class SLReadlnBuiltin extends SLBuiltinNode {
-
-    public SLReadlnBuiltin() {
-        super(new NullSourceSection("SL builtin", "readln"));
-    }
-
-    @Specialization
-    public String readln() {
-        String result = doRead(getContext().getInput());
-        if (result == null) {
-            /*
-             * We do not have a sophisticated end of file handling, so returning an empty string is
-             * a reasonable alternative. Note that the Java null value should never be used, since
-             * it can interfere with the specialization logic in generated source code.
-             */
-            result = "";
-        }
-        return result;
-    }
-
-    @TruffleBoundary
-    private static String doRead(BufferedReader in) {
-        try {
-            return in.readLine();
-        } catch (IOException ex) {
-            throw new SLException(ex.getMessage());
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.builtins;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Returns a string representation of the current stack. This includes the {@link CallTarget}s and
- * the contents of the {@link Frame}. Note that this is implemented as a slow path by passing
- * {@code true} to {@link FrameInstance#getFrame(FrameAccess, boolean)}.
- */
-@NodeInfo(shortName = "stacktrace")
-public abstract class SLStackTraceBuiltin extends SLBuiltinNode {
-
-    public SLStackTraceBuiltin() {
-        super(new NullSourceSection("SL builtin", "stacktrace"));
-    }
-
-    @Specialization
-    public String trace() {
-        return createStackTrace();
-    }
-
-    @TruffleBoundary
-    private static String createStackTrace() {
-        final StringBuilder str = new StringBuilder();
-
-        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Integer>() {
-            @Override
-            public Integer visitFrame(FrameInstance frameInstance) {
-                CallTarget callTarget = frameInstance.getCallTarget();
-                Frame frame = frameInstance.getFrame(FrameAccess.READ_ONLY, true);
-                RootNode rn = ((RootCallTarget) callTarget).getRootNode();
-                if (rn.getClass().getName().contains("SLFunctionForeignAccess")) {
-                    return 1;
-                }
-                if (str.length() > 0) {
-                    str.append(System.getProperty("line.separator"));
-                }
-                str.append("Frame: ").append(rn.toString());
-                FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-                for (FrameSlot s : frameDescriptor.getSlots()) {
-                    str.append(", ").append(s.getIdentifier()).append("=").append(frame.getValue(s));
-                }
-                return null;
-            }
-        });
-        return str.toString();
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.factory;
-
-import java.io.*;
-
-import com.oracle.truffle.sl.runtime.*;
-
-public final class SLContextFactory {
-
-    private SLContextFactory() {
-    }
-
-    public static SLContext create(BufferedReader input, PrintWriter output) {
-        return new SLContext(input, output);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Utility base class for operations that take two arguments (per convention called "left" and
- * "right"). For concrete subclasses of this class, the Truffle DSL creates two child fields, and
- * the necessary constructors and logic to set them.
- */
-@NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")})
-public abstract class SLBinaryNode extends SLExpressionNode {
-
-    public SLBinaryNode(SourceSection src) {
-        super(src);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Base class for all SL nodes that produce a value and therefore benefit from type specialization.
- * The annotation {@link TypeSystemReference} specifies the SL types. Specifying it here defines the
- * type system for all subclasses.
- */
-@TypeSystemReference(SLTypes.class)
-@NodeInfo(description = "The abstract base node for all expressions")
-public abstract class SLExpressionNode extends SLStatementNode {
-
-    public SLExpressionNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * The execute method when no specialization is possible. This is the most general case,
-     * therefore it must be provided by all subclasses.
-     */
-    public abstract Object executeGeneric(VirtualFrame frame);
-
-    /**
-     * When we use an expression at places where a {@link SLStatementNode statement} is already
-     * sufficient, the return value is just discarded.
-     */
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        executeGeneric(frame);
-    }
-
-    /*
-     * Execute methods for specialized types. They all follow the same pattern: they call the
-     * generic execution method and then expect a result of their return type. Type-specialized
-     * subclasses overwrite the appropriate methods.
-     */
-
-    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
-        return SLTypesGen.expectLong(executeGeneric(frame));
-    }
-
-    public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException {
-        return SLTypesGen.expectSLFunction(executeGeneric(frame));
-    }
-
-    public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
-        return SLTypesGen.expectBoolean(executeGeneric(frame));
-    }
-
-    @Override
-    public boolean isInstrumentable() {
-        return true;
-    }
-
-    @Override
-    public WrapperNode createWrapperNode() {
-        return new SLExpressionWrapperNode(this);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.builtins.*;
-import com.oracle.truffle.sl.nodes.controlflow.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The root of all SL execution trees. It is a Truffle requirement that the tree root extends the
- * class {@link RootNode}. This class is used for both builtin and user-defined functions. For
- * builtin functions, the {@link #bodyNode} is a subclass of {@link SLBuiltinNode}. For user-defined
- * functions, the {@link #bodyNode} is a {@link SLFunctionBodyNode}.
- */
-@NodeInfo(language = "Simple Language", description = "The root of all Simple Language execution trees")
-public final class SLRootNode extends RootNode {
-
-    /** The function body that is executed, and specialized during execution. */
-    @Child private SLExpressionNode bodyNode;
-
-    /** The name of the function, for printing purposes only. */
-    private final String name;
-
-    /** The Simple execution context for this tree. **/
-    private final SLContext context;
-
-    @CompilationFinal private boolean isCloningAllowed;
-
-    public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) {
-        super(null, frameDescriptor);
-        this.bodyNode = bodyNode;
-        this.name = name;
-        this.context = context;
-    }
-
-    @Override
-    public Object execute(VirtualFrame frame) {
-        return bodyNode.executeGeneric(frame);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setCloningAllowed(boolean isCloningAllowed) {
-        this.isCloningAllowed = isCloningAllowed;
-    }
-
-    public SLExpressionNode getBodyNode() {
-        return bodyNode;
-    }
-
-    @Override
-    public boolean isCloningAllowed() {
-        return isCloningAllowed;
-    }
-
-    @Override
-    public void applyInstrumentation() {
-        Probe.applyASTProbers(bodyNode);
-    }
-
-    @Override
-    public String toString() {
-        return "root " + name;
-    }
-
-    public SLContext getSLContext() {
-        return this.context;
-    }
-
-    @Override
-    public ExecutionContext getExecutionContext() {
-        return this.context;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import java.io.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
-
-/**
- * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
- * statements, i.e., without returning a value. The {@link VirtualFrame} provides access to the
- * local variables.
- */
-@NodeInfo(language = "Simple Language", description = "The abstract base node for all statements")
-public abstract class SLStatementNode extends Node {
-
-    public SLStatementNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * Execute this node as as statement, where no return value is necessary.
-     */
-    public abstract void executeVoid(VirtualFrame frame);
-
-    public SLStatementNode getNonWrapperNode() {
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return formatSourceSection(this);
-    }
-
-    /**
-     * Formats a source section of a node in human readable form. If no source section could be
-     * found it looks up the parent hierarchy until it finds a source section. Nodes where this was
-     * required append a <code>'~'</code> at the end.
-     *
-     * @param node the node to format.
-     * @return a formatted source section string
-     */
-    public static String formatSourceSection(Node node) {
-        if (node == null) {
-            return "<unknown>";
-        }
-        SourceSection section = node.getSourceSection();
-        boolean estimated = false;
-        if (section == null) {
-            section = node.getEncapsulatingSourceSection();
-            estimated = true;
-        }
-
-        if (section == null || section.getSource() == null) {
-            return "<unknown source>";
-        } else {
-            String sourceName = new File(section.getSource().getName()).getName();
-            int startLine = section.getStartLine();
-            return String.format("%s:%d%s", sourceName, startLine, estimated ? "~" : "");
-        }
-    }
-
-    @Override
-    public boolean isInstrumentable() {
-        return true;
-    }
-
-    @Override
-    public WrapperNode createWrapperNode() {
-        return new SLStatementWrapperNode(this);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.dsl.internal.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The type system of SL, as explained in {@link SLLanguage}. Based on the {@link TypeSystem}
- * annotation, the Truffle DSL generates the subclass {@link SLTypesGen} with type test and type
- * conversion methods for all types. In this class, we only cover types where the automatically
- * generated ones would not be sufficient.
- */
-@TypeSystem({long.class, BigInteger.class, boolean.class, String.class, SLFunction.class, SLNull.class})
-@DSLOptions(useNewLayout = true)
-public abstract class SLTypes {
-
-    /**
-     * Example of a manually specified type check that replaces the automatically generated type
-     * check that the Truffle DSL would generate. For {@link SLNull}, we do not need an
-     * {@code instanceof} check, because we know that there is only a {@link SLNull#SINGLETON
-     * singleton} instance.
-     */
-    @TypeCheck(SLNull.class)
-    public static boolean isSLNull(Object value) {
-        return value == SLNull.SINGLETON;
-    }
-
-    /**
-     * Example of a manually specified type cast that replaces the automatically generated type cast
-     * that the Truffle DSL would generate. For {@link SLNull}, we do not need an actual cast,
-     * because we know that there is only a {@link SLNull#SINGLETON singleton} instance.
-     */
-    @TypeCast(SLNull.class)
-    public static SLNull asSLNull(Object value) {
-        assert isSLNull(value);
-        return SLNull.SINGLETON;
-    }
-
-    /**
-     * Informs the Truffle DSL that a primitive {@code long} value can be used in all
-     * specializations where a {@link BigInteger} is expected. This models the semantic of SL: It
-     * only has an arbitrary precision Number type (implemented as {@link BigInteger}, and
-     * {@code long} is only used as a performance optimization to avoid the costly
-     * {@link BigInteger} arithmetic for values that fit into a 64-bit primitive value.
-     */
-    @ImplicitCast
-    public static BigInteger castBigInteger(long value) {
-        return BigInteger.valueOf(value);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.access;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.sl.runtime.*;
-
-public abstract class SLReadPropertyCacheNode extends Node {
-
-    protected static final int CACHE_LIMIT = 3;
-
-    protected final String propertyName;
-
-    public SLReadPropertyCacheNode(String propertyName) {
-        this.propertyName = propertyName;
-    }
-
-    public static SLReadPropertyCacheNode create(String propertyName) {
-        return SLReadPropertyCacheNodeGen.create(propertyName);
-    }
-
-    public abstract Object executeObject(DynamicObject receiver);
-
-    public abstract long executeLong(DynamicObject receiver) throws UnexpectedResultException;
-
-    /*
-     * We use a separate long specialization to avoid boxing for long.
-     */
-    @Specialization(limit = "CACHE_LIMIT", guards = {"longLocation != null", "shape.check(receiver)"}, assumptions = "shape.getValidAssumption()")
-    @SuppressWarnings("unused")
-    protected long doCachedLong(DynamicObject receiver, //
-                    @Cached("receiver.getShape()") Shape shape, //
-                    @Cached("getLongLocation(shape)") LongLocation longLocation) {
-        return longLocation.getLong(receiver, true);
-    }
-
-    protected LongLocation getLongLocation(Shape shape) {
-        Property property = shape.getProperty(propertyName);
-        if (property != null && property.getLocation() instanceof LongLocation) {
-            return (LongLocation) property.getLocation();
-        }
-        return null;
-    }
-
-    /*
-     * As soon as we have seen an object read, we cannot avoid boxing long anymore therefore we can
-     * contain all long cache entries.
-     */
-    @Specialization(limit = "CACHE_LIMIT", contains = "doCachedLong", guards = "shape.check(receiver)", assumptions = "shape.getValidAssumption()")
-    protected static Object doCachedObject(DynamicObject receiver, //
-                    @Cached("receiver.getShape()") Shape shape, //
-                    @Cached("shape.getProperty(propertyName)") Property property) {
-        if (property == null) {
-            return SLNull.SINGLETON;
-        } else {
-            return property.get(receiver, shape);
-        }
-    }
-
-    /*
-     * The generic case is used if the number of shapes accessed overflows the limit.
-     */
-    @Specialization(contains = "doCachedObject")
-    @TruffleBoundary
-    protected Object doGeneric(DynamicObject receiver, @Cached("new()") LRUPropertyLookup lruCache) {
-        if (!lruCache.shape.check(receiver)) {
-            Shape receiverShape = receiver.getShape();
-            lruCache.shape = receiverShape;
-            lruCache.property = receiverShape.getProperty(propertyName);
-        }
-        if (lruCache.property != null) {
-            return lruCache.property.get(receiver, true);
-        } else {
-            return SLNull.SINGLETON;
-        }
-    }
-
-    protected static class LRUPropertyLookup {
-
-        private Shape shape;
-        private Property property;
-
-        public LRUPropertyLookup() {
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.access;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The node for accessing a property of an object. When executed, this node first evaluates the
- * object expression on the left side of the dot operator and then reads the named property.
- */
-@NodeInfo(shortName = ".")
-public final class SLReadPropertyNode extends SLExpressionNode {
-
-    public static SLReadPropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
-        return new SLReadPropertyNode(src, receiverNode, propertyName);
-    }
-
-    @Child private SLExpressionNode receiverNode;
-    @Child private SLReadPropertyCacheNode cacheNode;
-    private final ConditionProfile receiverTypeCondition = ConditionProfile.createBinaryProfile();
-
-    private SLReadPropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
-        super(src);
-        this.receiverNode = receiverNode;
-        this.cacheNode = SLReadPropertyCacheNodeGen.create(propertyName);
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        Object object = receiverNode.executeGeneric(frame);
-        if (receiverTypeCondition.profile(SLContext.isSLObject(object))) {
-            return cacheNode.executeObject(SLContext.castSLObject(object));
-        } else {
-            throw new SLException("unexpected receiver type");
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.access;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.object.*;
-
-public abstract class SLWritePropertyCacheNode extends Node {
-
-    protected final String propertyName;
-
-    public SLWritePropertyCacheNode(String propertyName) {
-        this.propertyName = propertyName;
-    }
-
-    public abstract void executeObject(DynamicObject receiver, Object value);
-
-    @Specialization(guards = "location.isValid(receiver, value)", assumptions = "location.getAssumptions()")
-    public void writeCached(DynamicObject receiver, Object value, //
-                    @Cached("createCachedWrite(receiver, value)") CachedWriteLocation location) {
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
-            executeObject(receiver, value);
-        }
-    }
-
-    @Specialization(contains = "writeCached")
-    @TruffleBoundary
-    public void writeGeneric(DynamicObject receiver, Object value, //
-                    @Cached("new(createCachedWrite(receiver, value))") LRUCachedWriteLocation lru) {
-        CachedWriteLocation location = lru.location;
-        if (!location.isValid(receiver, value) || !location.areAssumptionsValid()) {
-            location = createCachedWrite(receiver, value);
-            lru.location = location;
-        }
-        if (location.writeUnchecked(receiver, value)) {
-            // write successful
-        } else {
-            executeObject(receiver, value);
-        }
-    }
-
-    protected CachedWriteLocation createCachedWrite(DynamicObject receiver, Object value) {
-        while (receiver.updateShape()) {
-            // multiple shape updates might be needed.
-        }
-
-        Shape oldShape = receiver.getShape();
-        Shape newShape;
-        Property property = oldShape.getProperty(propertyName);
-
-        if (property != null && property.getLocation().canSet(receiver, value)) {
-            newShape = oldShape;
-        } else {
-            receiver.define(propertyName, value, 0);
-            newShape = receiver.getShape();
-            property = newShape.getProperty(propertyName);
-        }
-
-        if (!oldShape.check(receiver)) {
-            return createCachedWrite(receiver, value);
-        }
-
-        return new CachedWriteLocation(oldShape, newShape, property.getLocation());
-
-    }
-
-    protected static final class CachedWriteLocation {
-
-        private final Shape oldShape;
-        private final Shape newShape;
-        private final Location location;
-        private final Assumption validLocation = Truffle.getRuntime().createAssumption();
-
-        public CachedWriteLocation(Shape oldShape, Shape newShape, Location location) {
-            this.oldShape = oldShape;
-            this.newShape = newShape;
-            this.location = location;
-        }
-
-        public boolean areAssumptionsValid() {
-            return validLocation.isValid() && oldShape.getValidAssumption().isValid() && newShape.getValidAssumption().isValid();
-        }
-
-        public Assumption[] getAssumptions() {
-            return new Assumption[]{oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation};
-        }
-
-        public boolean isValid(DynamicObject receiver, Object value) {
-            return oldShape.check(receiver) && location.canSet(receiver, value);
-        }
-
-        public boolean writeUnchecked(DynamicObject receiver, Object value) {
-            try {
-                if (oldShape == newShape) {
-                    location.set(receiver, value, oldShape);
-                } else {
-                    location.set(receiver, value, oldShape, newShape);
-                }
-                return true;
-            } catch (IncompatibleLocationException | FinalLocationException e) {
-                validLocation.invalidate();
-                return false;
-            }
-        }
-    }
-
-    protected static final class LRUCachedWriteLocation {
-
-        private CachedWriteLocation location;
-
-        public LRUCachedWriteLocation(CachedWriteLocation location) {
-            this.location = location;
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.access;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The node for setting a property of an object. When executed, this node first evaluates the value
- * expression on the right hand side of the equals operator, followed by the object expression on
- * the left side of the dot operator, and then sets the named property of this object to the new
- * value if the property already exists or adds a new property. Finally, it returns the new value.
- */
-@NodeInfo(shortName = ".=")
-public final class SLWritePropertyNode extends SLExpressionNode {
-
-    public static SLWritePropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
-        return new SLWritePropertyNode(src, receiverNode, propertyName, valueNode);
-    }
-
-    @Child protected SLExpressionNode receiverNode;
-    protected final String propertyName;
-    @Child protected SLExpressionNode valueNode;
-    @Child protected SLWritePropertyCacheNode cacheNode;
-    private final ConditionProfile receiverTypeCondition = ConditionProfile.createBinaryProfile();
-
-    private SLWritePropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
-        super(src);
-        this.receiverNode = receiverNode;
-        this.propertyName = propertyName;
-        this.valueNode = valueNode;
-        this.cacheNode = SLWritePropertyCacheNodeGen.create(propertyName);
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        Object value = valueNode.executeGeneric(frame);
-        Object object = receiverNode.executeGeneric(frame);
-        if (receiverTypeCondition.profile(SLContext.isSLObject(object))) {
-            cacheNode.executeObject(SLContext.castSLObject(object), value);
-        } else {
-            throw new SLException("unexpected receiver type");
-        }
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDispatchNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.call;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-public abstract class SLDispatchNode extends Node {
-
-    protected static final int INLINE_CACHE_SIZE = 2;
-
-    public abstract Object executeDispatch(VirtualFrame frame, SLFunction function, Object[] arguments);
-
-    @Specialization(guards = "function.getCallTarget() == null")
-    protected Object doUndefinedFunction(SLFunction function, @SuppressWarnings("unused") Object[] arguments) {
-        throw new SLUndefinedFunctionException(function.getName());
-    }
-
-    /**
-     * Inline cached specialization of the dispatch.
-     *
-     * <p>
-     * Since SL is a quite simple language, the benefit of the inline cache is quite small: after
-     * checking that the actual function to be executed is the same as the cachedFuntion, we can
-     * safely execute the cached call target. You can reasonably argue that caching the call target
-     * is overkill, since we could just retrieve it via {@code function.getCallTarget()}. However,
-     * in a more complex language the lookup of the call target is usually much more complicated
-     * than in SL. In addition, caching the call target allows method inlining.
-     * </p>
-     *
-     * <p>
-     * {@code limit = "INLINE_CACHE_SIZE"} Specifies the limit number of inline cache specialization
-     * instantiations.
-     * </p>
-     * <p>
-     * {@code guards = "function == cachedFunction"} The inline cache check. Note that
-     * cachedFunction is a final field so that the compiler can optimize the check.
-     * </p>
-     * <p>
-     * {@code assumptions = "cachedFunction.getCallTargetStable()"} Support for function
-     * redefinition: When a function is redefined, the call target maintained by the SLFunction
-     * object is change. To avoid a check for that, we use an Assumption that is invalidated by the
-     * SLFunction when the change is performed. Since checking an assumption is a no-op in compiled
-     * code, the assumption check performed by the DSL does not add any overhead during optimized
-     * execution.
-     * </p>
-     *
-     * @see Cached
-     * @see Specialization
-     *
-     * @param function the dynamically provided function
-     * @param cachedFunction the cached function of the specialization instance
-     * @param callNode the {@link DirectCallNode} specifically created for the {@link CallTarget} in
-     *            cachedFunction.
-     */
-    @Specialization(limit = "INLINE_CACHE_SIZE", guards = "function == cachedFunction", assumptions = "cachedFunction.getCallTargetStable()")
-    protected static Object doDirect(VirtualFrame frame, SLFunction function, Object[] arguments, //
-                    @Cached("function") SLFunction cachedFunction, //
-                    @Cached("create(cachedFunction.getCallTarget())") DirectCallNode callNode) {
-        /* Inline cache hit, we are safe to execute the cached call target. */
-        return callNode.call(frame, arguments);
-    }
-
-    /**
-     * Slow-path code for a call, used when the polymorphic inline cache exceeded its maximum size
-     * specified in <code>INLINE_CACHE_SIZE</code>. Such calls are not optimized any further, e.g.,
-     * no method inlining is performed.
-     */
-    @Specialization(contains = "doDirect")
-    protected static Object doIndirect(VirtualFrame frame, SLFunction function, Object[] arguments, //
-                    @Cached("create()") IndirectCallNode callNode) {
-        /*
-         * SL has a quite simple call lookup: just ask the function for the current call target, and
-         * call it.
-         */
-        return callNode.call(frame, function.getCallTarget(), arguments);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.call;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The node for function invocation in SL. Since SL has first class functions, the
- * {@link SLFunction target function} can be computed by an {@link #functionNode arbitrary
- * expression}. This node is responsible for evaluating this expression, as well as evaluating the
- * {@link #argumentNodes arguments}. The actual dispatch is then delegated to a chain of
- * {@link SLDispatchNode} that form a polymorphic inline cache.
- */
-@NodeInfo(shortName = "invoke")
-public final class SLInvokeNode extends SLExpressionNode {
-
-    public static SLInvokeNode create(SourceSection src, SLExpressionNode function, SLExpressionNode[] arguments) {
-        return new SLInvokeNode(src, function, arguments);
-    }
-
-    @Child private SLExpressionNode functionNode;
-    @Children private final SLExpressionNode[] argumentNodes;
-    @Child private SLDispatchNode dispatchNode;
-
-    private SLInvokeNode(SourceSection src, SLExpressionNode functionNode, SLExpressionNode[] argumentNodes) {
-        super(src);
-        this.functionNode = functionNode;
-        this.argumentNodes = argumentNodes;
-        this.dispatchNode = SLDispatchNodeGen.create();
-    }
-
-    @Override
-    @ExplodeLoop
-    public Object executeGeneric(VirtualFrame frame) {
-        SLFunction function = evaluateFunction(frame);
-
-        /*
-         * The number of arguments is constant for one invoke node. During compilation, the loop is
-         * unrolled and the execute methods of all arguments are inlined. This is triggered by the
-         * ExplodeLoop annotation on the method. The compiler assertion below illustrates that the
-         * array length is really constant.
-         */
-        CompilerAsserts.compilationConstant(argumentNodes.length);
-
-        Object[] argumentValues = new Object[argumentNodes.length];
-        for (int i = 0; i < argumentNodes.length; i++) {
-            argumentValues[i] = argumentNodes[i].executeGeneric(frame);
-        }
-
-        return dispatchNode.executeDispatch(frame, function, argumentValues);
-    }
-
-    private SLFunction evaluateFunction(VirtualFrame frame) {
-        try {
-            /*
-             * The function node must evaluate to a SLFunction value, so we call
-             * function-specialized method.
-             */
-            return functionNode.executeFunction(frame);
-        } catch (UnexpectedResultException ex) {
-            /*
-             * The function node evaluated to a non-function result. This is a type error in the SL
-             * program. We report it with the same exception that Truffle DSL generated nodes use to
-             * report type errors.
-             */
-            throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult());
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUndefinedFunctionException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.call;
-
-public class SLUndefinedFunctionException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    private final String functionName;
-
-    public SLUndefinedFunctionException(String functionName) {
-        this.functionName = functionName;
-    }
-
-    public String getFunctionName() {
-        return functionName;
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * A statement node that just executes a list of other statements.
- */
-@NodeInfo(shortName = "block", description = "The node implementing a source code block")
-public final class SLBlockNode extends SLStatementNode {
-
-    /**
-     * The array of child nodes. The annotation {@link com.oracle.truffle.api.nodes.Node.Children
-     * Children} informs Truffle that the field contains multiple children. It is a Truffle
-     * requirement that the field is {@code final} and an array of nodes.
-     */
-    @Children private final SLStatementNode[] bodyNodes;
-
-    public SLBlockNode(SourceSection src, SLStatementNode... bodyNodes) {
-        super(src);
-        this.bodyNodes = bodyNodes;
-    }
-
-    /**
-     * Execute all child statements. The annotation {@link ExplodeLoop} triggers full unrolling of
-     * the loop during compilation. This allows the {@link SLStatementNode#executeVoid} method of
-     * all children to be inlined.
-     */
-    @Override
-    @ExplodeLoop
-    public void executeVoid(VirtualFrame frame) {
-        /*
-         * This assertion illustrates that the array length is really a constant during compilation.
-         */
-        CompilerAsserts.compilationConstant(bodyNodes.length);
-
-        for (SLStatementNode statement : bodyNodes) {
-            statement.executeVoid(frame);
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Exception thrown by the {@link SLBreakNode break statement} and caught by the {@link SLWhileNode
- * loop statement}. Since the exception is stateless, i.e., has no instance fields, we can use a
- * {@link #SINGLETON} to avoid memory allocation during interpretation.
- */
-public final class SLBreakException extends ControlFlowException {
-
-    public static final SLBreakException SINGLETON = new SLBreakException();
-
-    private static final long serialVersionUID = -91013036379258890L;
-
-    /* Prevent instantiation from outside. */
-    private SLBreakException() {
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Implementation of the SL break statement. We need to unwind an unknown number of interpreter
- * frames that are between this {@link SLBreakNode} and the {@link SLWhileNode} of the loop we are
- * breaking out. This is done by throwing an {@link SLBreakException exception} that is caught by
- * the {@link SLWhileNode#executeVoid loop node}.
- */
-@NodeInfo(shortName = "break", description = "The node implementing a break statement")
-public final class SLBreakNode extends SLStatementNode {
-
-    public SLBreakNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        throw SLBreakException.SINGLETON;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Exception thrown by the {@link SLContinueNode continue statement} and caught by the
- * {@link SLWhileNode loop statement}. Since the exception is stateless, i.e., has no instance
- * fields, we can use a {@link #SINGLETON} to avoid memory allocation during interpretation.
- */
-public final class SLContinueException extends ControlFlowException {
-
-    public static final SLContinueException SINGLETON = new SLContinueException();
-
-    private static final long serialVersionUID = 5329687983726237188L;
-
-    /* Prevent instantiation from outside. */
-    private SLContinueException() {
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Implementation of the SL continue statement. We need to unwind an unknown number of interpreter
- * frames that are between this {@link SLContinueNode} and the {@link SLWhileNode} of the loop we
- * are continuing. This is done by throwing an {@link SLContinueException exception} that is caught
- * by the {@link SLWhileNode#executeVoid loop node}.
- */
-@NodeInfo(shortName = "continue", description = "The node implementing a continue statement")
-public final class SLContinueNode extends SLStatementNode {
-
-    public SLContinueNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        throw SLContinueException.SINGLETON;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The body of a user-defined SL function. This is the node referenced by a {@link SLRootNode} for
- * user-defined functions. It handles the return value of a function: the {@link SLReturnNode return
- * statement} throws an {@link SLReturnException exception} with the return value. This node catches
- * the exception. If the method ends without an explicit {@code return}, return the
- * {@link SLNull#SINGLETON default null value}.
- */
-@NodeInfo(shortName = "body")
-public final class SLFunctionBodyNode extends SLExpressionNode {
-
-    /** The body of the function. */
-    @Child private SLStatementNode bodyNode;
-
-    /**
-     * Profiling information, collected by the interpreter, capturing whether the function had an
-     * {@link SLReturnNode explicit return statement}. This allows the compiler to generate better
-     * code.
-     */
-    private final BranchProfile exceptionTaken = BranchProfile.create();
-    private final BranchProfile nullTaken = BranchProfile.create();
-
-    public SLFunctionBodyNode(SourceSection src, SLStatementNode bodyNode) {
-        super(src);
-        this.bodyNode = bodyNode;
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        try {
-            /* Execute the function body. */
-            bodyNode.executeVoid(frame);
-
-        } catch (SLReturnException ex) {
-            /*
-             * In the interpreter, record profiling information that the function has an explicit
-             * return.
-             */
-            exceptionTaken.enter();
-            /* The exception transports the actual return value. */
-            return ex.getResult();
-        }
-
-        /*
-         * In the interpreter, record profiling information that the function ends without an
-         * explicit return.
-         */
-        nullTaken.enter();
-        /* Return the default null value. */
-        return SLNull.SINGLETON;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.nodes.*;
-
-@NodeInfo(shortName = "if", description = "The node implementing a condional statement")
-public final class SLIfNode extends SLStatementNode {
-
-    /**
-     * The condition of the {@code if}. This in a {@link SLExpressionNode} because we require a
-     * result value. We do not have a node type that can only return a {@code boolean} value, so
-     * {@link #evaluateCondition executing the condition} can lead to a type error.
-     */
-    @Child private SLExpressionNode conditionNode;
-
-    /** Statement (or {@link SLBlockNode block}) executed when the condition is true. */
-    @Child private SLStatementNode thenPartNode;
-
-    /** Statement (or {@link SLBlockNode block}) executed when the condition is false. */
-    @Child private SLStatementNode elsePartNode;
-
-    /**
-     * Profiling information, collected by the interpreter, capturing the profiling information of
-     * the condition. This allows the compiler to generate better code for conditions that are
-     * always true or always false. Additionally the {@link CountingConditionProfile} implementation
-     * (as opposed to {@link BinaryConditionProfile} implementation) transmits the probability of
-     * the condition to be true to the compiler.
-     */
-    private final ConditionProfile condition = ConditionProfile.createCountingProfile();
-
-    public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
-        super(src);
-        this.conditionNode = conditionNode;
-        this.thenPartNode = thenPartNode;
-        this.elsePartNode = elsePartNode;
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        /*
-         * In the interpreter, record profiling information that the condition was executed and with
-         * which outcome.
-         */
-        if (condition.profile(evaluateCondition(frame))) {
-            /* Execute the then-branch. */
-            thenPartNode.executeVoid(frame);
-        } else {
-            /* Execute the else-branch (which is optional according to the SL syntax). */
-            if (elsePartNode != null) {
-                elsePartNode.executeVoid(frame);
-            }
-        }
-    }
-
-    private boolean evaluateCondition(VirtualFrame frame) {
-        try {
-            /*
-             * The condition must evaluate to a boolean value, so we call the boolean-specialized
-             * execute method.
-             */
-            return conditionNode.executeBoolean(frame);
-        } catch (UnexpectedResultException ex) {
-            /*
-             * The condition evaluated to a non-boolean result. This is a type error in the SL
-             * program. We report it with the same exception that Truffle DSL generated nodes use to
-             * report type errors.
-             */
-            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.nodes.*;
-
-public final class SLRepeatingNode extends Node implements RepeatingNode {
-
-    /**
-     * The condition of the loop. This in a {@link SLExpressionNode} because we require a result
-     * value. We do not have a node type that can only return a {@code boolean} value, so
-     * {@link #evaluateCondition executing the condition} can lead to a type error.
-     */
-    @Child private SLExpressionNode conditionNode;
-
-    /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */
-    @Child private SLStatementNode bodyNode;
-
-    /**
-     * Profiling information, collected by the interpreter, capturing whether a {@code continue}
-     * statement was used in this loop. This allows the compiler to generate better code for loops
-     * without a {@code continue}.
-     */
-    private final BranchProfile continueTaken = BranchProfile.create();
-    private final BranchProfile breakTaken = BranchProfile.create();
-
-    public SLRepeatingNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
-        super(src);
-        this.conditionNode = conditionNode;
-        this.bodyNode = bodyNode;
-    }
-
-    public boolean executeRepeating(VirtualFrame frame) {
-        if (evaluateCondition(frame)) {
-            try {
-                /* Execute the loop body. */
-                bodyNode.executeVoid(frame);
-            } catch (SLContinueException ex) {
-                /* In the interpreter, record profiling information that the loop uses continue. */
-                continueTaken.enter();
-                /* Fall through to next loop iteration. */
-            } catch (SLBreakException ex) {
-                /* In the interpreter, record profiling information that the loop uses break. */
-                breakTaken.enter();
-                /* Done executing this loop, exit method to execute statement following the loop. */
-                return false;
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private boolean evaluateCondition(VirtualFrame frame) {
-        try {
-            /*
-             * The condition must evaluate to a boolean value, so we call the boolean-specialized
-             * execute method.
-             */
-            return (conditionNode.executeBoolean(frame));
-        } catch (UnexpectedResultException ex) {
-            /*
-             * The condition evaluated to a non-boolean result. This is a type error in the SL
-             * program. We report it with the same exception that Truffle DSL generated nodes use to
-             * report type errors.
-             */
-            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
-        }
-    }
-
-    @Override
-    public String toString() {
-        return SLStatementNode.formatSourceSection(this);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * Exception thrown by the {@link SLReturnNode return statement} and caught by the
- * {@link SLFunctionBodyNode function body}. The exception transports the return value in its
- * {@link #result} field.
- */
-public final class SLReturnException extends ControlFlowException {
-
-    private static final long serialVersionUID = 4073191346281369231L;
-
-    private final Object result;
-
-    public SLReturnException(Object result) {
-        this.result = result;
-    }
-
-    public Object getResult() {
-        return result;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Implementation of the SL return statement. We need to unwind an unknown number of interpreter
- * frames that are between this {@link SLReturnNode} and the {@link SLFunctionBodyNode} of the
- * method we are exiting. This is done by throwing an {@link SLReturnException exception} that is
- * caught by the {@link SLFunctionBodyNode#executeGeneric function body}. The exception transports
- * the return value.
- */
-@NodeInfo(shortName = "return", description = "The node implementing a return statement")
-public final class SLReturnNode extends SLStatementNode {
-
-    @Child private SLExpressionNode valueNode;
-
-    public SLReturnNode(SourceSection src, SLExpressionNode valueNode) {
-        super(src);
-        this.valueNode = valueNode;
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        Object result;
-        if (valueNode != null) {
-            result = valueNode.executeGeneric(frame);
-        } else {
-            /* Return statement that was not followed by an expression, so return the SL null value. */
-            result = SLNull.SINGLETON;
-        }
-        throw new SLReturnException(result);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.controlflow;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-@NodeInfo(shortName = "while", description = "The node implementing a while loop")
-public final class SLWhileNode extends SLStatementNode {
-
-    @Child private LoopNode loopNode;
-
-    public SLWhileNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
-        super(src);
-        this.loopNode = Truffle.getRuntime().createLoopNode(new SLRepeatingNode(src, conditionNode, bodyNode));
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        loopNode.executeLoop(frame);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * SL node that performs the "+" operation, which performs addition on arbitrary precision numbers,
- * as well as String concatenation if one of the operands is a String.
- * <p>
- * Type specialization on the input values is essential for the performance. This is achieved via
- * node rewriting: specialized subclasses handle just a single type, so that the generic node that
- * can handle all types is used only in cases where different types were encountered. The subclasses
- * are automatically generated by the Truffle DSL. In addition, a {@link SLAddNodeGen factory class}
- * is generated that provides, e.g., {@link SLAddNodeGen#create node creation}.
- */
-@NodeInfo(shortName = "+")
-public abstract class SLAddNode extends SLBinaryNode {
-
-    public SLAddNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * Specialization for primitive {@code long} values. This is the fast path of the
-     * arbitrary-precision arithmetic. We need to check for overflows of the addition, and switch to
-     * the {@link #add(BigInteger, BigInteger) slow path}. Therefore, we use an
-     * {@link ExactMath#addExact(long, long) addition method that throws an exception on overflow}.
-     * The {@code rewriteOn} attribute on the {@link Specialization} annotation automatically
-     * triggers the node rewriting on the exception.
-     * <p>
-     * In compiled code, {@link ExactMath#addExact(long, long) addExact} is compiled to efficient
-     * machine code that uses the processor's overflow flag. Therefore, this method is compiled to
-     * only two machine code instructions on the fast path.
-     * <p>
-     * This specialization is automatically selected by the Truffle DSL if both the left and right
-     * operand are {@code long} values.
-     */
-    @Specialization(rewriteOn = ArithmeticException.class)
-    protected long add(long left, long right) {
-        return ExactMath.addExact(left, right);
-    }
-
-    /**
-     * This is the slow path of the arbitrary-precision arithmetic. The {@link BigInteger} type of
-     * Java is doing everything we need.
-     * <p>
-     * This specialization is automatically selected by the Truffle DSL if both the left and right
-     * operand are {@link BigInteger} values. Because the type system defines an
-     * {@link ImplicitCast implicit conversion} from {@code long} to {@link BigInteger} in
-     * {@link SLTypes#castBigInteger(long)}, this specialization is also taken if the left or the
-     * right operand is a {@code long} value. Because the {@link #add(long, long) long}
-     * specialization} has the {@code rewriteOn} attribute, this specialization is also taken if
-     * both input values are {@code long} values but the primitive addition overflows.
-     */
-    @Specialization
-    @TruffleBoundary
-    protected BigInteger add(BigInteger left, BigInteger right) {
-        return left.add(right);
-    }
-
-    /**
-     * Specialization for String concatenation. The SL specification says that String concatenation
-     * works if either the left or the right operand is a String. The non-string operand is
-     * converted then automatically converted to a String.
-     * <p>
-     * To implement these semantics, we tell the Truffle DSL to use a custom guard. The guard
-     * function is defined in {@link #isString this class}, but could also be in any superclass.
-     */
-    @Specialization(guards = "isString(left, right)")
-    @TruffleBoundary
-    protected String add(Object left, Object right) {
-        return left.toString() + right.toString();
-    }
-
-    /**
-     * Guard for String concatenation: returns true if either the left or the right operand is a
-     * {@link String}.
-     */
-    protected boolean isString(Object a, Object b) {
-        return a instanceof String || b instanceof String;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Constant literal for a arbitrary-precision number that exceeds the range of
- * {@link SLLongLiteralNode}.
- */
-@NodeInfo(shortName = "const")
-public final class SLBigIntegerLiteralNode extends SLExpressionNode {
-
-    private final BigInteger value;
-
-    public SLBigIntegerLiteralNode(SourceSection src, BigInteger value) {
-        super(src);
-        this.value = value;
-    }
-
-    @Override
-    public BigInteger executeGeneric(VirtualFrame frame) {
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the extensively documented {@link SLAddNode}. Divisions by 0 throw the
- * same {@link ArithmeticException exception} as in Java, SL has no special handling for it to keep
- * the code simple.
- */
-@NodeInfo(shortName = "/")
-public abstract class SLDivNode extends SLBinaryNode {
-
-    public SLDivNode(SourceSection src) {
-        super(src);
-    }
-
-    @Specialization(rewriteOn = ArithmeticException.class)
-    protected long div(long left, long right) throws ArithmeticException {
-        long result = left / right;
-        /*
-         * The division overflows if left is Long.MIN_VALUE and right is -1.
-         */
-        if ((left & right & result) < 0) {
-            throw new ArithmeticException("long overflow");
-        }
-        return result;
-    }
-
-    @Specialization
-    protected BigInteger div(BigInteger left, BigInteger right) {
-        return left.divide(right);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * The {@code ==} operator of SL is defined on all types. Therefore, we need a
- * {@link #equal(Object, Object) generic implementation} that can handle all possible types. But
- * since {@code ==} can only return {@code true} when the type of the left and right operand are the
- * same, the specializations already cover all possible cases that can return {@code true} and the
- * generic case is trivial.
- * <p>
- * Note that we do not need the analogous {@code =!} operator, because we can just
- * {@link SLLogicalNotNode negate} the {@code ==} operator.
- */
-@NodeInfo(shortName = "==")
-public abstract class SLEqualNode extends SLBinaryNode {
-
-    public SLEqualNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    @Specialization
-    protected boolean equal(long left, long right) {
-        return left == right;
-    }
-
-    @Specialization
-    protected boolean equal(BigInteger left, BigInteger right) {
-        return left.equals(right);
-    }
-
-    @Specialization
-    protected boolean equal(boolean left, boolean right) {
-        return left == right;
-    }
-
-    @Specialization
-    protected boolean equal(String left, String right) {
-        return left.equals(right);
-    }
-
-    @Specialization
-    protected boolean equal(SLFunction left, SLFunction right) {
-        /*
-         * Our function registry maintains one canonical SLFunction object per function name, so we
-         * do not need equals().
-         */
-        return left == right;
-    }
-
-    @Specialization
-    protected boolean equal(SLNull left, SLNull right) {
-        /* There is only the singleton instance of SLNull, so we do not need equals(). */
-        return left == right;
-    }
-
-    /**
-     * The {@link Fallback} annotation informs the Truffle DSL that this method should be executed
-     * when no {@link Specialization specialized method} matches. The operand types must be
-     * {@link Object}.
-     */
-    @Fallback
-    protected boolean equal(Object left, Object right) {
-        /*
-         * We covered all the cases that can return true in specializations. If we compare two
-         * values with different types, no specialization matches and we end up here.
-         */
-        assert !left.equals(right);
-        return false;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Constant literal for a {@link SLFunction function} value, created when a function name occurs as
- * a literal in SL source code. Note that function redefinition can change the {@link CallTarget
- * call target} that is executed when calling the function, but the {@link SLFunction} for a name
- * never changes. This is guaranteed by the {@link SLFunctionRegistry}.
- */
-@NodeInfo(shortName = "func")
-public final class SLFunctionLiteralNode extends SLExpressionNode {
-
-    private final SLFunction value;
-
-    public SLFunctionLiteralNode(SourceSection src, SLFunction value) {
-        super(src);
-        this.value = value;
-    }
-
-    @Override
-    public SLFunction executeGeneric(VirtualFrame frame) {
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the {@link SLLessThanNode}.
- */
-@NodeInfo(shortName = "<=")
-public abstract class SLLessOrEqualNode extends SLBinaryNode {
-
-    public SLLessOrEqualNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    @Specialization
-    protected boolean lessOrEqual(long left, long right) {
-        return left <= right;
-    }
-
-    @Specialization
-    protected boolean lessOrEqual(BigInteger left, BigInteger right) {
-        return left.compareTo(right) <= 0;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the extensively documented {@link SLAddNode}. The only difference: the
- * specialized methods return {@code boolean} instead of the input types.
- */
-@NodeInfo(shortName = "<")
-public abstract class SLLessThanNode extends SLBinaryNode {
-
-    public SLLessThanNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    @Specialization
-    protected boolean lessThan(long left, long right) {
-        return left < right;
-    }
-
-    @Specialization
-    protected boolean lessThan(BigInteger left, BigInteger right) {
-        return left.compareTo(right) < 0;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class declares specializations similar to the extensively documented {@link SLAddNode}. It
- * uses one additional feature of the Truffle DSL: {@link ShortCircuit}.
- * <p>
- * Logical operations in SL use short circuit evaluation: if the evaluation of the left operand
- * already decides the result of the operation, the right operand must not be executed. This is
- * expressed in the Truffle DSL via a method annotated with {@link ShortCircuit}, which returns
- * whether a child needs to be executed based on the result of already executed children.
- */
-@NodeInfo(shortName = "&&")
-@SuppressWarnings("unused")
-public abstract class SLLogicalAndNode extends SLBinaryNode {
-
-    public SLLogicalAndNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    /**
-     * This method is called after the left child was evaluated, but before the right child is
-     * evaluated. The right child is only evaluated when the return value is {code true}.
-     */
-    @ShortCircuit("rightNode")
-    protected boolean needsRightNode(boolean left) {
-        return left;
-    }
-
-    /**
-     * Similar to {@link #needsRightNode(boolean)}, but for generic cases where the type of the left
-     * child is not known.
-     */
-    @ShortCircuit("rightNode")
-    protected boolean needsRightNode(Object left) {
-        return left instanceof Boolean && needsRightNode(((Boolean) left).booleanValue());
-    }
-
-    @Specialization
-    protected boolean doBoolean(boolean left, boolean hasRight, boolean right) {
-        return left && right;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Example of a simple unary node that uses type specialization. See {@link SLAddNode} for
- * information on specializations.
- */
-@NodeChild("valueNode")
-@NodeInfo(shortName = "!")
-public abstract class SLLogicalNotNode extends SLExpressionNode {
-
-    public SLLogicalNotNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    @Specialization
-    protected boolean doBoolean(boolean value) {
-        return !value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the {@link SLLogicalAndNode}.
- */
-@NodeInfo(shortName = "||")
-@SuppressWarnings("unused")
-public abstract class SLLogicalOrNode extends SLBinaryNode {
-
-    public SLLogicalOrNode(SourceSection src) {
-        super(src);
-    }
-
-    @Override
-    public abstract boolean executeBoolean(VirtualFrame frame);
-
-    @ShortCircuit("rightNode")
-    protected boolean needsRightNode(boolean left) {
-        return !left;
-    }
-
-    @ShortCircuit("rightNode")
-    protected boolean needsRightNode(Object left) {
-        return left instanceof Boolean && needsRightNode(((Boolean) left).booleanValue());
-    }
-
-    @Specialization
-    protected boolean doBoolean(boolean left, boolean hasRight, boolean right) {
-        return left || right;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Constant literal for a primitive {@code long} value. The unboxed value can be returned when the
- * parent expects a long value and calls {@link SLLongLiteralNode#executeLong}. In the generic case,
- * the primitive value is automatically boxed by Java.
- */
-@NodeInfo(shortName = "const")
-public final class SLLongLiteralNode extends SLExpressionNode {
-
-    private final long value;
-
-    public SLLongLiteralNode(SourceSection src, long value) {
-        super(src);
-        this.value = value;
-    }
-
-    @Override
-    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
-        return value;
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the extensively documented {@link SLAddNode}.
- */
-@NodeInfo(shortName = "*")
-public abstract class SLMulNode extends SLBinaryNode {
-
-    public SLMulNode(SourceSection src) {
-        super(src);
-    }
-
-    @Specialization(rewriteOn = ArithmeticException.class)
-    protected long mul(long left, long right) {
-        return ExactMath.multiplyExact(left, right);
-    }
-
-    @Specialization
-    @TruffleBoundary
-    protected BigInteger mul(BigInteger left, BigInteger right) {
-        return left.multiply(right);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * A {@link SLExpressionNode} that represents a parenthesized expression; it simply returns the
- * value of the enclosed (child) expression. It is represented separately in the AST for the purpose
- * of correct source attribution; this preserves the lexical relationship between the two
- * parentheses and allows a tool to describe the expression as distinct from its contents.
- */
-@NodeInfo(description = "A parenthesized expression")
-public class SLParenExpressionNode extends SLExpressionNode {
-
-    private final SLExpressionNode expression;
-
-    public SLParenExpressionNode(SourceSection src, SLExpressionNode expression) {
-        super(src);
-        this.expression = insert(expression);
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        return expression.executeGeneric(frame);
-    }
-
-    @Override
-    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
-        return expression.executeLong(frame);
-    }
-
-    @Override
-    public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
-        return expression.executeBoolean(frame);
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Constant literal for a String value.
- */
-@NodeInfo(shortName = "const")
-public final class SLStringLiteralNode extends SLExpressionNode {
-
-    private final String value;
-
-    public SLStringLiteralNode(SourceSection src, String value) {
-        super(src);
-        this.value = value;
-    }
-
-    @Override
-    public String executeGeneric(VirtualFrame frame) {
-        return value;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression;
-
-import java.math.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * This class is similar to the extensively documented {@link SLAddNode}.
- */
-@NodeInfo(shortName = "-")
-public abstract class SLSubNode extends SLBinaryNode {
-
-    public SLSubNode(SourceSection src) {
-        super(src);
-    }
-
-    @Specialization(rewriteOn = ArithmeticException.class)
-    protected long sub(long left, long right) {
-        return ExactMath.subtractExact(left, right);
-    }
-
-    @Specialization
-    protected BigInteger sub(BigInteger left, BigInteger right) {
-        return left.subtract(right);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.expression.demo;
-
-import java.math.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.expression.*;
-
-/**
- * This is an example how the add operation would be implemented without specializations and without
- * the Truffle DSL. Do not write such code in your language! See {@link SLAddNode} how the add
- * operation is implemented correctly.
- */
-public class SLAddWithoutSpecializationNode extends SLExpressionNode {
-
-    @Child private SLExpressionNode leftNode;
-    @Child private SLExpressionNode rightNode;
-
-    public SLAddWithoutSpecializationNode(SLExpressionNode leftNode, SLExpressionNode rightNode) {
-        super(null);
-        this.leftNode = leftNode;
-        this.rightNode = rightNode;
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        /* Evaluate the child nodes. */
-        Object left = leftNode.executeGeneric(frame);
-        Object right = rightNode.executeGeneric(frame);
-
-        if (left instanceof Long && right instanceof Long) {
-            /* Fast path of the arbitrary-precision arithmetic. We need to check for overflows */
-            try {
-                return ExactMath.addExact((Long) left, (Long) right);
-            } catch (ArithmeticException ex) {
-                /* Fall through to BigInteger case. */
-            }
-        }
-
-        /* Implicit type conversions. */
-        if (left instanceof Long) {
-            left = BigInteger.valueOf((Long) left);
-        }
-        if (right instanceof Long) {
-            right = BigInteger.valueOf((Long) right);
-        }
-        if (left instanceof BigInteger && right instanceof BigInteger) {
-            /* Slow path of the arbitrary-precision arithmetic. */
-            return ((BigInteger) left).add((BigInteger) right);
-        }
-
-        /* String concatenation if either the left or the right operand is a String. */
-        if (left instanceof String || right instanceof String) {
-            return left.toString() + right.toString();
-        }
-
-        /* Type error. */
-        throw new UnsupportedSpecializationException(this, new Node[]{leftNode, rightNode}, new Object[]{left, right});
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.instrument;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
-
-/**
- * SLASTPrinter is used to print for SL's internal Truffle AST. This is used by
- * {@link SLDefaultVisualizer} to provide a means of displaying the internal Truffle AST
- */
-public final class SLASTPrinter extends DefaultASTPrinter {
-
-    public SLASTPrinter() {
-    }
-
-    @Override
-    protected void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
-        if (node == null) {
-            p.print("null");
-            return;
-        }
-
-        p.print(nodeName(node));
-
-        p.print("(");
-
-        if (node instanceof InstrumentationNode) {
-            p.print(instrumentInfo((InstrumentationNode) node));
-        }
-
-        p.print(sourceInfo(node));
-
-        p.print(NodeUtil.printSyntaxTags(node));
-
-        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
-
-        for (NodeFieldAccessor field : NodeClass.get(node.getClass()).getFields()) {
-            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
-                childFields.add(field);
-            } else if (field.getKind() == NodeFieldKind.DATA) {
-                // p.print(sep);
-                // sep = ", ";
-                //
-                // final String fieldName = field.getName();
-                // switch (fieldName) {
-                //
-                // }
-                // p.print(fieldName);
-                // p.print(" = ");
-                // p.print(field.loadValue(node));
-            }
-        }
-        p.print(")");
-
-        if (level <= maxDepth) {
-
-            if (childFields.size() != 0) {
-                p.print(" {");
-                for (NodeFieldAccessor field : childFields) {
-
-                    Object value = field.loadValue(node);
-                    if (value == null) {
-                        printNewLine(p, level);
-                        p.print(field.getName());
-                        p.print(" = null ");
-                    } else if (field.getKind() == NodeFieldKind.CHILD) {
-                        printChild(p, maxDepth, markNode, level, field, value);
-                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
-                        printChildren(p, maxDepth, markNode, level, field, value);
-                    } else {
-                        printNewLine(p, level);
-                        p.print(field.getName());
-                    }
-                }
-                printNewLine(p, level - 1);
-                p.print("}");
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.instrument;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * SLDefaultVisualizer provides methods to get the names of SL's internal Truffle AST nodes.
- *
- */
-public class SLDefaultVisualizer extends DefaultVisualizer {
-
-    private final SLASTPrinter astPrinter;
-
-    public SLDefaultVisualizer() {
-        this.astPrinter = new SLASTPrinter();
-    }
-
-    @Override
-    public ASTPrinter getASTPrinter() {
-        return astPrinter;
-    }
-
-    @Override
-    public String displayMethodName(Node node) {
-
-        if (node == null) {
-            return null;
-        }
-        RootNode root = node.getRootNode();
-        if (root instanceof SLRootNode) {
-            SLRootNode slRootNode = (SLRootNode) root;
-            return slRootNode.toString();
-
-        }
-        return "unknown";
-    }
-
-    @Override
-    public String displayCallTargetName(CallTarget callTarget) {
-        if (callTarget instanceof RootCallTarget) {
-            final RootCallTarget rootCallTarget = (RootCallTarget) callTarget;
-            SLRootNode slRootNode = (SLRootNode) rootCallTarget.getRootNode();
-            return slRootNode.toString();
-        }
-        return callTarget.toString();
-    }
-
-    @Override
-    public String displayValue(Object value, int trim) {
-        if (value == SLNull.SINGLETON) {
-            return "null";
-        }
-        return trim(value.toString(), trim);
-    }
-
-    @Override
-    public String displayIdentifier(FrameSlot slot) {
-
-        final Object id = slot.getIdentifier();
-        return id.toString();
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to
- * enable "instrumentation" of an {@link SLExpressionNode}. Tools wishing to interact with AST
- * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the
- * wrapper, and to which this wrapper routes execution events.
- */
-@NodeInfo(cost = NodeCost.NONE)
-public final class SLExpressionWrapperNode extends SLExpressionNode implements WrapperNode {
-    @Child private SLExpressionNode child;
-    @Child private ProbeNode probeNode;
-
-    /**
-     * Constructor.
-     *
-     * @param child The {@link SLExpressionNode} that this wrapper is wrapping
-     */
-    public SLExpressionWrapperNode(SLExpressionNode child) {
-        super(child.getSourceSection());
-        assert !(child instanceof SLExpressionWrapperNode);
-        this.child = child;
-    }
-
-    public String instrumentationInfo() {
-        return "Wrapper node for SL Expressions";
-    }
-
-    @Override
-    public boolean isInstrumentable() {
-        return false;
-    }
-
-    @Override
-    public SLExpressionNode getNonWrapperNode() {
-        return child;
-    }
-
-    public void insertProbe(ProbeNode newProbeNode) {
-        this.probeNode = newProbeNode;
-    }
-
-    public Probe getProbe() {
-        return probeNode.getProbe();
-    }
-
-    public Node getChild() {
-        return child;
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame vFrame) {
-
-        probeNode.enter(child, vFrame);
-        Object result;
-
-        try {
-            result = child.executeGeneric(vFrame);
-            probeNode.returnValue(child, vFrame, result);
-        } catch (Exception e) {
-            probeNode.returnExceptional(child, vFrame, e);
-            throw (e);
-        }
-        return result;
-    }
-
-    @Override
-    public long executeLong(VirtualFrame vFrame) throws UnexpectedResultException {
-        return SLTypesGen.expectLong(executeGeneric(vFrame));
-    }
-
-    @Override
-    public boolean executeBoolean(VirtualFrame vFrame) throws UnexpectedResultException {
-        return SLTypesGen.expectBoolean(executeGeneric(vFrame));
-    }
-
-    @Override
-    public SLFunction executeFunction(VirtualFrame vFrame) throws UnexpectedResultException {
-        probeNode.enter(child, vFrame);
-        SLFunction result;
-
-        try {
-            result = child.executeFunction(vFrame);
-            probeNode.returnValue(child, vFrame, result);
-        } catch (Exception e) {
-            probeNode.returnExceptional(child, vFrame, e);
-            throw (e);
-        }
-        return result;
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.instrument;
-
-import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.controlflow.*;
-import com.oracle.truffle.sl.nodes.local.*;
-
-/**
- * A visitor which traverses a completely parsed Simple AST (presumed not yet executed) and enables
- * instrumentation at a few standard kinds of nodes.
- */
-public class SLStandardASTProber implements NodeVisitor, ASTProber {
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * Instruments and tags all relevant {@link SLStatementNode}s and {@link SLExpressionNode}s.
-     * Currently, only SLStatementNodes that are not SLExpressionNodes are tagged as statements.
-     */
-    public boolean visit(Node node) {
-
-        if (!(node instanceof InstrumentationNode) && node instanceof SLStatementNode && node.getParent() != null && node.getSourceSection() != null) {
-            // All SL nodes are instrumentable, but treat expressions specially
-
-            if (node instanceof SLExpressionNode) {
-                SLExpressionNode expressionNode = (SLExpressionNode) node;
-                Probe probe = expressionNode.probe();
-                if (node instanceof SLWriteLocalVariableNode) {
-                    probe.tagAs(STATEMENT, null);
-                    probe.tagAs(ASSIGNMENT, null);
-                }
-            } else {
-                SLStatementNode statementNode = (SLStatementNode) node;
-                Probe probe = statementNode.probe();
-                probe.tagAs(STATEMENT, null);
-                if (node instanceof SLWhileNode) {
-                    probe.tagAs(START_LOOP, null);
-                }
-            }
-        }
-        return true;
-    }
-
-    public void probeAST(Node node) {
-        node.accept(this);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.instrument;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to
- * enable "instrumentation" of a {@link SLStatementNode}. Tools wishing to interact with AST
- * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the
- * wrapper, and to which this wrapper routes execution events.
- */
-@NodeInfo(cost = NodeCost.NONE)
-public final class SLStatementWrapperNode extends SLStatementNode implements WrapperNode {
-
-    @Child private SLStatementNode child;
-    @Child private ProbeNode probeNode;
-
-    public SLStatementWrapperNode(SLStatementNode child) {
-        super(child.getSourceSection());
-        assert !(child instanceof SLStatementWrapperNode);
-        this.child = child;
-    }
-
-    public String instrumentationInfo() {
-        return "Wrapper node for SL Statements";
-    }
-
-    @Override
-    public boolean isInstrumentable() {
-        return false;
-    }
-
-    @Override
-    public SLStatementNode getNonWrapperNode() {
-        return child;
-    }
-
-    public void insertProbe(ProbeNode newProbeNode) {
-        this.probeNode = newProbeNode;
-    }
-
-    public Probe getProbe() {
-        return probeNode.getProbe();
-    }
-
-    @Override
-    public Node getChild() {
-        return child;
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame vFrame) {
-        probeNode.enter(child, vFrame);
-
-        try {
-            child.executeVoid(vFrame);
-            probeNode.returnVoid(child, vFrame);
-        } catch (KillException e) {
-            throw (e);
-        } catch (Exception e) {
-            probeNode.returnExceptional(child, vFrame, e);
-            throw (e);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.local;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.parser.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Reads a function argument. Arguments are passed in as an object array.
- * <p>
- * Arguments are not type-specialized. To ensure that repeated accesses within a method are
- * specialized and can, e.g., be accessed without unboxing, all arguments are loaded into local
- * variables {@link SLNodeFactory#addFormalParameter in the method prologue}.
- */
-public class SLReadArgumentNode extends SLExpressionNode {
-
-    /** The argument number, i.e., the index into the array of arguments. */
-    private final int index;
-
-    /**
-     * Profiling information, collected by the interpreter, capturing whether the function was
-     * called with fewer actual arguments than formal arguments.
-     */
-    private final BranchProfile outOfBoundsTaken = BranchProfile.create();
-
-    public SLReadArgumentNode(SourceSection src, int index) {
-        super(src);
-        this.index = index;
-    }
-
-    @Override
-    public Object executeGeneric(VirtualFrame frame) {
-        Object[] args = frame.getArguments();
-        if (index < args.length) {
-            return args[index];
-        } else {
-            /* In the interpreter, record profiling information that the branch was used. */
-            outOfBoundsTaken.enter();
-            /* Use the default null value. */
-            return SLNull.SINGLETON;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.local;
-
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Node to read a local variable from a function's {@link VirtualFrame frame}. The Truffle frame API
- * allows to store primitive values of all Java primitive types, and Object values. This means that
- * all SL types that are objects are handled by the {@link #readObject} method. When a local
- * variable changes its type, the frame access method throws an {@link FrameSlotTypeException},
- * which causes not rewriting. The rewriting code is generated by the Truffle DSL.
- */
-@NodeField(name = "slot", type = FrameSlot.class)
-public abstract class SLReadLocalVariableNode extends SLExpressionNode {
-
-    public SLReadLocalVariableNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * Returns the descriptor of the accessed local variable. The implementation of this method is
-     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
-     */
-    protected abstract FrameSlot getSlot();
-
-    @Specialization(rewriteOn = FrameSlotTypeException.class)
-    protected long readLong(VirtualFrame frame) throws FrameSlotTypeException {
-        return frame.getLong(getSlot());
-    }
-
-    @Specialization(rewriteOn = FrameSlotTypeException.class)
-    protected boolean readBoolean(VirtualFrame frame) throws FrameSlotTypeException {
-        return frame.getBoolean(getSlot());
-    }
-
-    @Specialization(rewriteOn = FrameSlotTypeException.class)
-    protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException {
-        return frame.getObject(getSlot());
-    }
-
-    /**
-     * This is the generic case that always succeeds. Since we already have another specialization
-     * with the same signature above, we need to order them explicitly with the order attribute.
-     */
-    @Specialization(contains = {"readLong", "readBoolean", "readObject"})
-    protected Object read(VirtualFrame frame) {
-        return frame.getValue(getSlot());
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes.local;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Node to write a local variable to a function's {@link VirtualFrame frame}. The Truffle frame API
- * allows to store primitive values of all Java primitive types, and Object values.
- */
-@NodeChild("valueNode")
-@NodeField(name = "slot", type = FrameSlot.class)
-public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
-
-    public SLWriteLocalVariableNode(SourceSection src) {
-        super(src);
-    }
-
-    /**
-     * Returns the descriptor of the accessed local variable. The implementation of this method is
-     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
-     */
-    protected abstract FrameSlot getSlot();
-
-    /**
-     * Specialized method to write a primitive {@code long} value. This is only possible if the
-     * local variable also has currently the type {@code long}, therefore a Truffle DSL
-     * {@link #isLongKind(VirtualFrame) custom guard} is specified.
-     */
-    @Specialization(guards = "isLongKind(frame)")
-    protected long writeLong(VirtualFrame frame, long value) {
-        frame.setLong(getSlot(), value);
-        return value;
-    }
-
-    @Specialization(guards = "isBooleanKind(frame)")
-    protected boolean writeBoolean(VirtualFrame frame, boolean value) {
-        frame.setBoolean(getSlot(), value);
-        return value;
-    }
-
-    /**
-     * Generic write method that works for all possible types.
-     * <p>
-     * Why is this method annotated with {@link Specialization} and not {@link Fallback}? For a
-     * {@link Fallback} method, the Truffle DSL generated code would try all other specializations
-     * first before calling this method. We know that all these specializations would fail their
-     * guards, so there is no point in calling them. Since this method takes a value of type
-     * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the
-     * node will never be re-specialized.
-     */
-    @Specialization(contains = {"writeLong", "writeBoolean"})
-    protected Object write(VirtualFrame frame, Object value) {
-        if (getSlot().getKind() != FrameSlotKind.Object) {
-            /*
-             * The local variable has still a primitive type, we need to change it to Object. Since
-             * the variable type is important when the compiler optimizes a method, we also discard
-             * compiled code.
-             */
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            getSlot().setKind(FrameSlotKind.Object);
-        }
-        frame.setObject(getSlot(), value);
-        return value;
-    }
-
-    /**
-     * Guard function that the local variable has the type {@code long}.
-     */
-    @SuppressWarnings("unused")
-    protected boolean isLongKind(VirtualFrame frame) {
-        return isKind(FrameSlotKind.Long);
-    }
-
-    @SuppressWarnings("unused")
-    protected boolean isBooleanKind(VirtualFrame frame) {
-        return isKind(FrameSlotKind.Boolean);
-    }
-
-    private boolean isKind(FrameSlotKind kind) {
-        if (getSlot().getKind() == kind) {
-            /* Success: the frame slot has the expected kind. */
-            return true;
-        } else if (getSlot().getKind() == FrameSlotKind.Illegal) {
-            /*
-             * This is the first write to this local variable. We can set the type to the one we
-             * expect. Since the variable type is important when the compiler optimizes a method, we
-             * also discard compiled code.
-             */
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            getSlot().setKind(kind);
-            return true;
-        } else {
-            /*
-             * Failure: the frame slot has the wrong kind, the Truffle DSL generated code will
-             * choose a different specialization.
-             */
-            return false;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// The content of this file is automatically generated. DO NOT EDIT.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,207 +0,0 @@
-/*-------------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported from C# to Java by Wolfgang Ahorner
-with improvements by Pat Terry, Rhodes University
-
-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, 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.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than 
-Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
--->begin
-package com.oracle.truffle.sl.parser;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-// Checkstyle: stop
-// @formatter:off
-public class Parser {
--->constants
-    static final boolean _T = true;
-    static final boolean _x = false;
-    static final int minErrDist = 2;
-
-    public Token t; // last recognized token
-    public Token la; // lookahead token
-    int errDist = minErrDist;
-
-    public final Scanner scanner;
-    public final Errors errors;
-    private final SLNodeFactory factory;
-    -->declarations
-    public Parser(SLContext context, Source source) {
-        this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source);
-        errors = new Errors();
-    }
-
-    void SynErr(int n) {
-        if (errDist >= minErrDist)
-            errors.SynErr(la.line, la.col, n);
-        errDist = 0;
-    }
-
-    public void SemErr(String msg) {
-        if (errDist >= minErrDist)
-            errors.SemErr(t.line, t.col, msg);
-        errDist = 0;
-    }
-
-    void Get() {
-        for (;;) {
-            t = la;
-            la = scanner.Scan();
-            if (la.kind <= maxT) {
-                ++errDist;
-                break;
-            }
--->pragmas
-            la = t;
-        }
-    }
-
-    void Expect(int n) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-        }
-    }
-
-    boolean StartOf(int s) {
-        return set[s][la.kind];
-    }
-
-    void ExpectWeak(int n, int follow) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-            while (!StartOf(follow))
-                Get();
-        }
-    }
-
-    boolean WeakSeparator(int n, int syFol, int repFol) {
-        int kind = la.kind;
-        if (kind == n) {
-            Get();
-            return true;
-        } else if (StartOf(repFol))
-            return false;
-        else {
-            SynErr(n);
-            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
-                Get();
-                kind = la.kind;
-            }
-            return StartOf(syFol);
-        }
-    }
-
--->productions
-
-    public void Parse() {
-        la = new Token();
-        la.val = "";
-        Get();
--->parseRoot
-    }
-
-    private static final boolean[][] set = {
--->initialization
-    };
-
-    public static void parseSL(SLContext context, Source source) {
-        Parser parser = new Parser(context, source);
-        parser.Parse();
-        if (parser.errors.errors.size() > 0) {
-            StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
-            for (String error : parser.errors.errors) {
-                msg.append(error).append("\n");
-            }
-            throw new SLException(msg.toString());
-        }
-    }
-} // end Parser
-
-class Errors {
-
-    protected final List<String> errors = new ArrayList<>();
-    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-
-    protected void printMsg(int line, int column, String msg) {
-        StringBuffer b = new StringBuffer(errMsgFormat);
-        int pos = b.indexOf("{0}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, line);
-        }
-        pos = b.indexOf("{1}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, column);
-        }
-        pos = b.indexOf("{2}");
-        if (pos >= 0)
-            b.replace(pos, pos + 3, msg);
-        errors.add(b.toString());
-    }
-
-    public void SynErr(int line, int col, int n) {
-        String s;
-        switch (n) {-->errors
-            default:
-                s = "error " + n;
-                break;
-        }
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(String s) {
-        errors.add(s);
-    }
-
-    public void Warning(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void Warning(String s) {
-        errors.add(s);
-    }
-} // Errors
-
-class FatalError extends RuntimeException {
-
-    public static final long serialVersionUID = 1L;
-
-    public FatalError(String s) {
-        super(s);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,546 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// The content of this file is automatically generated. DO NOT EDIT.
-
-package com.oracle.truffle.sl.parser;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.runtime.*;
-
-// Checkstyle: stop
-// @formatter:off
-public class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _stringLiteral = 2;
-	public static final int _numericLiteral = 3;
-	public static final int maxT = 31;
-
-    static final boolean _T = true;
-    static final boolean _x = false;
-    static final int minErrDist = 2;
-
-    public Token t; // last recognized token
-    public Token la; // lookahead token
-    int errDist = minErrDist;
-
-    public final Scanner scanner;
-    public final Errors errors;
-    private final SLNodeFactory factory;
-
-    public Parser(SLContext context, Source source) {
-        this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source);
-        errors = new Errors();
-    }
-
-    void SynErr(int n) {
-        if (errDist >= minErrDist)
-            errors.SynErr(la.line, la.col, n);
-        errDist = 0;
-    }
-
-    public void SemErr(String msg) {
-        if (errDist >= minErrDist)
-            errors.SemErr(t.line, t.col, msg);
-        errDist = 0;
-    }
-
-    void Get() {
-        for (;;) {
-            t = la;
-            la = scanner.Scan();
-            if (la.kind <= maxT) {
-                ++errDist;
-                break;
-            }
-
-            la = t;
-        }
-    }
-
-    void Expect(int n) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-        }
-    }
-
-    boolean StartOf(int s) {
-        return set[s][la.kind];
-    }
-
-    void ExpectWeak(int n, int follow) {
-        if (la.kind == n)
-            Get();
-        else {
-            SynErr(n);
-            while (!StartOf(follow))
-                Get();
-        }
-    }
-
-    boolean WeakSeparator(int n, int syFol, int repFol) {
-        int kind = la.kind;
-        if (kind == n) {
-            Get();
-            return true;
-        } else if (StartOf(repFol))
-            return false;
-        else {
-            SynErr(n);
-            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
-                Get();
-                kind = la.kind;
-            }
-            return StartOf(syFol);
-        }
-    }
-
-	void SimpleLanguage() {
-		Function();
-		while (la.kind == 4) {
-			Function();
-		}
-	}
-
-	void Function() {
-		Expect(4);
-		Expect(1);
-		Token identifierToken = t;
-		Expect(5);
-		int bodyStartPos = t.charPos;
-		factory.startFunction(identifierToken, bodyStartPos);
-		if (la.kind == 1) {
-			Get();
-			factory.addFormalParameter(t);
-			while (la.kind == 6) {
-				Get();
-				Expect(1);
-				factory.addFormalParameter(t);
-			}
-		}
-		Expect(7);
-		SLStatementNode body = Block(false);
-		factory.finishFunction(body);
-	}
-
-	SLStatementNode  Block(boolean inLoop) {
-		SLStatementNode  result;
-		factory.startBlock();
-		List<SLStatementNode> body = new ArrayList<>();
-		Expect(8);
-		int start = t.charPos;
-		while (StartOf(1)) {
-			SLStatementNode s = Statement(inLoop);
-			body.add(s);
-		}
-		Expect(9);
-		int length = (t.charPos + t.val.length()) - start;
-		result = factory.finishBlock(body, start, length);
-		return result;
-	}
-
-	SLStatementNode  Statement(boolean inLoop) {
-		SLStatementNode  result;
-		result = null;
-		switch (la.kind) {
-		case 13: {
-			result = WhileStatement();
-			break;
-		}
-		case 10: {
-			Get();
-			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); }
-			Expect(11);
-			break;
-		}
-		case 12: {
-			Get();
-			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); }
-			Expect(11);
-			break;
-		}
-		case 14: {
-			result = IfStatement(inLoop);
-			break;
-		}
-		case 16: {
-			result = ReturnStatement();
-			break;
-		}
-		case 1: case 2: case 3: case 5: {
-			result = Expression();
-			Expect(11);
-			break;
-		}
-		default: SynErr(32); break;
-		}
-		return result;
-	}
-
-	SLStatementNode  WhileStatement() {
-		SLStatementNode  result;
-		Expect(13);
-		Token whileToken = t;
-		Expect(5);
-		SLExpressionNode condition = Expression();
-		Expect(7);
-		SLStatementNode body = Block(true);
-		result = factory.createWhile(whileToken, condition, body);
-		return result;
-	}
-
-	SLStatementNode  IfStatement(boolean inLoop) {
-		SLStatementNode  result;
-		Expect(14);
-		Token ifToken = t;
-		Expect(5);
-		SLExpressionNode condition = Expression();
-		Expect(7);
-		SLStatementNode thenPart = Block(inLoop);
-		SLStatementNode elsePart = null;
-		if (la.kind == 15) {
-			Get();
-			elsePart = Block(inLoop);
-		}
-		result = factory.createIf(ifToken, condition, thenPart, elsePart);
-		return result;
-	}
-
-	SLStatementNode  ReturnStatement() {
-		SLStatementNode  result;
-		Expect(16);
-		Token returnToken = t;
-		SLExpressionNode value = null;
-		if (StartOf(2)) {
-			value = Expression();
-		}
-		result = factory.createReturn(returnToken, value);
-		Expect(11);
-		return result;
-	}
-
-	SLExpressionNode  Expression() {
-		SLExpressionNode  result;
-		result = LogicTerm();
-		while (la.kind == 17) {
-			Get();
-			Token op = t;
-			SLExpressionNode right = LogicTerm();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	SLExpressionNode  LogicTerm() {
-		SLExpressionNode  result;
-		result = LogicFactor();
-		while (la.kind == 18) {
-			Get();
-			Token op = t;
-			SLExpressionNode right = LogicFactor();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	SLExpressionNode  LogicFactor() {
-		SLExpressionNode  result;
-		result = Arithmetic();
-		if (StartOf(3)) {
-			switch (la.kind) {
-			case 19: {
-				Get();
-				break;
-			}
-			case 20: {
-				Get();
-				break;
-			}
-			case 21: {
-				Get();
-				break;
-			}
-			case 22: {
-				Get();
-				break;
-			}
-			case 23: {
-				Get();
-				break;
-			}
-			case 24: {
-				Get();
-				break;
-			}
-			}
-			Token op = t;
-			SLExpressionNode right = Arithmetic();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	SLExpressionNode  Arithmetic() {
-		SLExpressionNode  result;
-		result = Term();
-		while (la.kind == 25 || la.kind == 26) {
-			if (la.kind == 25) {
-				Get();
-			} else {
-				Get();
-			}
-			Token op = t;
-			SLExpressionNode right = Term();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	SLExpressionNode  Term() {
-		SLExpressionNode  result;
-		result = Factor();
-		while (la.kind == 27 || la.kind == 28) {
-			if (la.kind == 27) {
-				Get();
-			} else {
-				Get();
-			}
-			Token op = t;
-			SLExpressionNode right = Factor();
-			result = factory.createBinary(op, result, right);
-		}
-		return result;
-	}
-
-	SLExpressionNode  Factor() {
-		SLExpressionNode  result;
-		result = null;
-		if (la.kind == 1) {
-			Get();
-			if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
-				result = MemberExpression(null, null, t);
-			} else if (StartOf(4)) {
-				result = factory.createRead(t);
-			} else SynErr(33);
-		} else if (la.kind == 2) {
-			Get();
-			result = factory.createStringLiteral(t);
-		} else if (la.kind == 3) {
-			Get();
-			result = factory.createNumericLiteral(t);
-		} else if (la.kind == 5) {
-			Get();
-			int start = t.charPos;
-			result = Expression();
-			SLExpressionNode expr = result;
-			Expect(7);
-			int length = (t.charPos + t.val.length()) - start;
-			result = factory.createParenExpression(expr, start, length);
-		} else SynErr(34);
-		return result;
-	}
-
-	SLExpressionNode  MemberExpression(SLExpressionNode r, SLExpressionNode assignmentReceiver, Token assignmentName) {
-		SLExpressionNode  result;
-		result = null;
-		SLExpressionNode receiver = r;
-		Token nestedAssignmentName = null;
-		if (la.kind == 5) {
-			Get();
-			List<SLExpressionNode> parameters = new ArrayList<>();
-			SLExpressionNode parameter;
-			if (receiver == null) {
-			   receiver = factory.createRead(assignmentName);
-			}
-			if (StartOf(2)) {
-				parameter = Expression();
-				parameters.add(parameter);
-				while (la.kind == 6) {
-					Get();
-					parameter = Expression();
-					parameters.add(parameter);
-				}
-			}
-			Expect(7);
-			Token finalToken = t;
-			result = factory.createCall(receiver, parameters, finalToken);
-		} else if (la.kind == 29) {
-			Get();
-			SLExpressionNode value = Expression();
-			if (assignmentName == null) {
-			   SemErr("invalid assignment target");
-			} else if (assignmentReceiver == null) {
-			   result = factory.createAssignment(assignmentName, value);
-			} else {
-			   result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
-			}
-		} else if (la.kind == 30) {
-			Get();
-			if (receiver == null) {
-			   receiver = factory.createRead(assignmentName);
-			}
-			Expect(1);
-			result = factory.createReadProperty(receiver, t);
-			nestedAssignmentName = t;
-		} else SynErr(35);
-		if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
-			result = MemberExpression(result, receiver, nestedAssignmentName);
-		}
-		return result;
-	}
-
-
-
-    public void Parse() {
-        la = new Token();
-        la.val = "";
-        Get();
-		SimpleLanguage();
-		Expect(0);
-
-    }
-
-    private static final boolean[][] set = {
-		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_T,_x, _T,_T,_T,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x},
-		{_x,_x,_x,_x, _x,_T,_T,_T, _x,_x,_x,_T, _x,_x,_x,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x}
-
-    };
-
-    public static void parseSL(SLContext context, Source source) {
-        Parser parser = new Parser(context, source);
-        parser.Parse();
-        if (parser.errors.errors.size() > 0) {
-            StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
-            for (String error : parser.errors.errors) {
-                msg.append(error).append("\n");
-            }
-            throw new SLException(msg.toString());
-        }
-    }
-} // end Parser
-
-class Errors {
-
-    protected final List<String> errors = new ArrayList<>();
-    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
-
-    protected void printMsg(int line, int column, String msg) {
-        StringBuffer b = new StringBuffer(errMsgFormat);
-        int pos = b.indexOf("{0}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, line);
-        }
-        pos = b.indexOf("{1}");
-        if (pos >= 0) {
-            b.delete(pos, pos + 3);
-            b.insert(pos, column);
-        }
-        pos = b.indexOf("{2}");
-        if (pos >= 0)
-            b.replace(pos, pos + 3, msg);
-        errors.add(b.toString());
-    }
-
-    public void SynErr(int line, int col, int n) {
-        String s;
-        switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "stringLiteral expected"; break;
-			case 3: s = "numericLiteral expected"; break;
-			case 4: s = "\"function\" expected"; break;
-			case 5: s = "\"(\" expected"; break;
-			case 6: s = "\",\" expected"; break;
-			case 7: s = "\")\" expected"; break;
-			case 8: s = "\"{\" expected"; break;
-			case 9: s = "\"}\" expected"; break;
-			case 10: s = "\"break\" expected"; break;
-			case 11: s = "\";\" expected"; break;
-			case 12: s = "\"continue\" expected"; break;
-			case 13: s = "\"while\" expected"; break;
-			case 14: s = "\"if\" expected"; break;
-			case 15: s = "\"else\" expected"; break;
-			case 16: s = "\"return\" expected"; break;
-			case 17: s = "\"||\" expected"; break;
-			case 18: s = "\"&&\" expected"; break;
-			case 19: s = "\"<\" expected"; break;
-			case 20: s = "\"<=\" expected"; break;
-			case 21: s = "\">\" expected"; break;
-			case 22: s = "\">=\" expected"; break;
-			case 23: s = "\"==\" expected"; break;
-			case 24: s = "\"!=\" expected"; break;
-			case 25: s = "\"+\" expected"; break;
-			case 26: s = "\"-\" expected"; break;
-			case 27: s = "\"*\" expected"; break;
-			case 28: s = "\"/\" expected"; break;
-			case 29: s = "\"=\" expected"; break;
-			case 30: s = "\".\" expected"; break;
-			case 31: s = "??? expected"; break;
-			case 32: s = "invalid Statement"; break;
-			case 33: s = "invalid Factor"; break;
-			case 34: s = "invalid Factor"; break;
-			case 35: s = "invalid MemberExpression"; break;
-            default:
-                s = "error " + n;
-                break;
-        }
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void SemErr(String s) {
-        errors.add(s);
-    }
-
-    public void Warning(int line, int col, String s) {
-        printMsg(line, col, s);
-    }
-
-    public void Warning(String s) {
-        errors.add(s);
-    }
-} // Errors
-
-class FatalError extends RuntimeException {
-
-    public static final long serialVersionUID = 1L;
-
-    public FatalError(String s) {
-        super(s);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.parser;
-
-import java.math.*;
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.access.*;
-import com.oracle.truffle.sl.nodes.call.*;
-import com.oracle.truffle.sl.nodes.controlflow.*;
-import com.oracle.truffle.sl.nodes.expression.*;
-import com.oracle.truffle.sl.nodes.local.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * Helper class used by the SL {@link Parser} to create nodes. The code is factored out of the
- * automatically generated parser to keep the attributed grammar of SL small.
- */
-public class SLNodeFactory {
-
-    /**
-     * Local variable names that are visible in the current block. Variables are not visible outside
-     * of their defining block, to prevent the usage of undefined variables. Because of that, we can
-     * decide during parsing if a name references a local variable or is a function name.
-     */
-    static class LexicalScope {
-        protected final LexicalScope outer;
-        protected final Map<String, FrameSlot> locals;
-
-        public LexicalScope(LexicalScope outer) {
-            this.outer = outer;
-            this.locals = new HashMap<>();
-            if (outer != null) {
-                locals.putAll(outer.locals);
-            }
-        }
-    }
-
-    /* State while parsing a source unit. */
-    private final SLContext context;
-    private final Source source;
-
-    /* State while parsing a function. */
-    private int functionStartPos;
-    private String functionName;
-    private int functionBodyStartPos; // includes parameter list
-    private int parameterCount;
-    private FrameDescriptor frameDescriptor;
-    private List<SLStatementNode> methodNodes;
-
-    /* State while parsing a block. */
-    private LexicalScope lexicalScope;
-
-    public SLNodeFactory(SLContext context, Source source) {
-        this.context = context;
-        this.source = source;
-    }
-
-    public void startFunction(Token nameToken, int bodyStartPos) {
-        assert functionStartPos == 0;
-        assert functionName == null;
-        assert functionBodyStartPos == 0;
-        assert parameterCount == 0;
-        assert frameDescriptor == null;
-        assert lexicalScope == null;
-
-        functionStartPos = nameToken.charPos;
-        functionName = nameToken.val;
-        functionBodyStartPos = bodyStartPos;
-        frameDescriptor = new FrameDescriptor();
-        methodNodes = new ArrayList<>();
-        startBlock();
-    }
-
-    public void addFormalParameter(Token nameToken) {
-        /*
-         * Method parameters are assigned to local variables at the beginning of the method. This
-         * ensures that accesses to parameters are specialized the same way as local variables are
-         * specialized.
-         */
-        final SourceSection src = srcFromToken(nameToken);
-        final SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount);
-        methodNodes.add(createAssignment(nameToken, readArg));
-        parameterCount++;
-    }
-
-    public void finishFunction(SLStatementNode bodyNode) {
-        methodNodes.add(bodyNode);
-        final int bodyEndPos = bodyNode.getSourceSection().getCharEndIndex();
-        final SourceSection functionSrc = source.createSection(functionName, functionStartPos, bodyEndPos - functionStartPos);
-        final SLStatementNode methodBlock = finishBlock(methodNodes, functionBodyStartPos, bodyEndPos - functionBodyStartPos);
-        assert lexicalScope == null : "Wrong scoping of blocks in parser";
-
-        final SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(functionSrc, methodBlock);
-        final SLRootNode rootNode = new SLRootNode(this.context, frameDescriptor, functionBodyNode, functionName);
-        rootNode.assignSourceSection(functionSrc);
-
-        context.getFunctionRegistry().register(functionName, rootNode);
-
-        functionStartPos = 0;
-        functionName = null;
-        functionBodyStartPos = 0;
-        parameterCount = 0;
-        frameDescriptor = null;
-        lexicalScope = null;
-    }
-
-    public void startBlock() {
-        lexicalScope = new LexicalScope(lexicalScope);
-    }
-
-    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes, int startPos, int length) {
-        lexicalScope = lexicalScope.outer;
-
-        List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size());
-        flattenBlocks(bodyNodes, flattenedNodes);
-
-        final SourceSection src = source.createSection("block", startPos, length);
-        return new SLBlockNode(src, flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
-    }
-
-    private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) {
-        for (Node n : bodyNodes) {
-            if (n instanceof SLBlockNode) {
-                flattenBlocks(n.getChildren(), flattenedNodes);
-            } else {
-                flattenedNodes.add((SLStatementNode) n);
-            }
-        }
-    }
-
-    /**
-     * Returns an {@link SLBreakNode} for the given token.
-     *
-     * @param breakToken The token containing the break node's info.
-     * @return A SLBreakNode for the given token.
-     */
-    public SLStatementNode createBreak(Token breakToken) {
-        final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken));
-        return breakNode;
-    }
-
-    /**
-     * Returns an {@link SLContinueNode} for the given token.
-     *
-     * @param continueToken The token containing the continue node's info.
-     * @return A SLContinueNode built using the given token.
-     */
-    public SLStatementNode createContinue(Token continueToken) {
-        final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken));
-        return continueNode;
-    }
-
-    /**
-     * Returns an {@link SLWhileNode} for the given parameters.
-     *
-     * @param whileToken The token containing the while node's info
-     * @param conditionNode The conditional node for this while loop
-     * @param bodyNode The body of the while loop
-     * @return A SLWhileNode built using the given parameters.
-     */
-    public SLStatementNode createWhile(Token whileToken, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
-        final int start = whileToken.charPos;
-        final int end = bodyNode.getSourceSection().getCharEndIndex();
-        final SLWhileNode whileNode = new SLWhileNode(source.createSection(whileToken.val, start, end - start), conditionNode, bodyNode);
-        return whileNode;
-    }
-
-    /**
-     * Returns an {@link SLIfNode} for the given parameters.
-     *
-     * @param ifToken The token containing the if node's info
-     * @param conditionNode The condition node of this if statement
-     * @param thenPartNode The then part of the if
-     * @param elsePartNode The else part of the if
-     * @return An SLIfNode for the given parameters.
-     */
-    public SLStatementNode createIf(Token ifToken, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
-        final int start = ifToken.charPos;
-        final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex();
-        final SLIfNode ifNode = new SLIfNode(source.createSection(ifToken.val, start, end - start), conditionNode, thenPartNode, elsePartNode);
-        return ifNode;
-    }
-
-    /**
-     * Returns an {@link SLReturnNode} for the given parameters.
-     *
-     * @param t The token containing the return node's info
-     * @param valueNode The value of the return
-     * @return An SLReturnNode for the given parameters.
-     */
-    public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) {
-        final int start = t.charPos;
-        final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start;
-        final SLReturnNode returnNode = new SLReturnNode(source.createSection(t.val, start, length), valueNode);
-        return returnNode;
-    }
-
-    /**
-     * Returns the corresponding subclass of {@link SLExpressionNode} for binary expressions.
-     * </br>These nodes are currently not instrumented.
-     *
-     * @param opToken The operator of the binary expression
-     * @param leftNode The left node of the expression
-     * @param rightNode The right node of the expression
-     * @return A subclass of SLExpressionNode using the given parameters based on the given opToken.
-     */
-    public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
-        int start = leftNode.getSourceSection().getCharIndex();
-        int length = rightNode.getSourceSection().getCharEndIndex() - start;
-        final SourceSection src = source.createSection(opToken.val, start, length);
-        switch (opToken.val) {
-            case "+":
-                return SLAddNodeGen.create(src, leftNode, rightNode);
-            case "*":
-                return SLMulNodeGen.create(src, leftNode, rightNode);
-            case "/":
-                return SLDivNodeGen.create(src, leftNode, rightNode);
-            case "-":
-                return SLSubNodeGen.create(src, leftNode, rightNode);
-            case "<":
-                return SLLessThanNodeGen.create(src, leftNode, rightNode);
-            case "<=":
-                return SLLessOrEqualNodeGen.create(src, leftNode, rightNode);
-            case ">":
-                return SLLogicalNotNodeGen.create(src, SLLessOrEqualNodeGen.create(null, leftNode, rightNode));
-            case ">=":
-                return SLLogicalNotNodeGen.create(src, SLLessThanNodeGen.create(null, leftNode, rightNode));
-            case "==":
-                return SLEqualNodeGen.create(src, leftNode, rightNode);
-            case "!=":
-                return SLLogicalNotNodeGen.create(src, SLEqualNodeGen.create(null, leftNode, rightNode));
-            case "&&":
-                return SLLogicalAndNodeGen.create(src, leftNode, rightNode);
-            case "||":
-                return SLLogicalOrNodeGen.create(src, leftNode, rightNode);
-            default:
-                throw new RuntimeException("unexpected operation: " + opToken.val);
-        }
-    }
-
-    /**
-     * Returns an {@link SLInvokeNode} for the given parameters.
-     *
-     * @param functionNode The function being called
-     * @param parameterNodes The parameters of the function call
-     * @param finalToken A token used to determine the end of the sourceSelection for this call
-     * @return An SLInvokeNode for the given parameters.
-     */
-    public SLExpressionNode createCall(SLExpressionNode functionNode, List<SLExpressionNode> parameterNodes, Token finalToken) {
-        final int startPos = functionNode.getSourceSection().getCharIndex();
-        final int endPos = finalToken.charPos + finalToken.val.length();
-        final SourceSection src = source.createSection(functionNode.getSourceSection().getIdentifier(), startPos, endPos - startPos);
-        return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
-    }
-
-    /**
-     * Returns an {@link SLWriteLocalVariableNode} for the given parameters.
-     *
-     * @param nameToken The name of the variable being assigned
-     * @param valueNode The value to be assigned
-     * @return An SLExpressionNode for the given parameters.
-     */
-    public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
-        FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val);
-        lexicalScope.locals.put(nameToken.val, frameSlot);
-        final int start = nameToken.charPos;
-        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
-        return SLWriteLocalVariableNodeGen.create(source.createSection("=", start, length), valueNode, frameSlot);
-    }
-
-    /**
-     * Returns a {@link SLReadLocalVariableNode} if this read is a local variable or a
-     * {@link SLFunctionLiteralNode} if this read is global. In Simple, the only global names are
-     * functions. </br> There is currently no instrumentation for this node.
-     *
-     * @param nameToken The name of the variable/function being read
-     * @return either:
-     *         <ul>
-     *         <li>A SLReadLocalVariableNode representing the local variable being read.</li>
-     *         <li>A SLFunctionLiteralNode representing the function definition</li>
-     *         </ul>
-     */
-    public SLExpressionNode createRead(Token nameToken) {
-        final FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
-        final SourceSection src = srcFromToken(nameToken);
-        if (frameSlot != null) {
-            /* Read of a local variable. */
-            return SLReadLocalVariableNodeGen.create(src, frameSlot);
-        } else {
-            /* Read of a global name. In our language, the only global names are functions. */
-            return new SLFunctionLiteralNode(src, context.getFunctionRegistry().lookup(nameToken.val));
-        }
-    }
-
-    public SLExpressionNode createStringLiteral(Token literalToken) {
-        /* Remove the trailing and ending " */
-        String literal = literalToken.val;
-        assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"");
-        final SourceSection src = srcFromToken(literalToken);
-        literal = literal.substring(1, literal.length() - 1);
-
-        return new SLStringLiteralNode(src, literal);
-    }
-
-    public SLExpressionNode createNumericLiteral(Token literalToken) {
-        final SourceSection src = srcFromToken(literalToken);
-        try {
-            /* Try if the literal is small enough to fit into a long value. */
-            return new SLLongLiteralNode(src, Long.parseLong(literalToken.val));
-        } catch (NumberFormatException ex) {
-            /* Overflow of long value, so fall back to BigInteger. */
-            return new SLBigIntegerLiteralNode(src, new BigInteger(literalToken.val));
-        }
-    }
-
-    public SLExpressionNode createParenExpression(SLExpressionNode expressionNode, int start, int length) {
-        final SourceSection src = source.createSection("()", start, length);
-        return new SLParenExpressionNode(src, expressionNode);
-    }
-
-    /**
-     * Returns an {@link SLReadPropertyNode} for the given parameters.
-     *
-     * @param receiverNode The receiver of the property access
-     * @param nameToken The name of the property being accessed
-     * @return An SLExpressionNode for the given parameters.
-     */
-    public SLExpressionNode createReadProperty(SLExpressionNode receiverNode, Token nameToken) {
-        final int startPos = receiverNode.getSourceSection().getCharIndex();
-        final int endPos = nameToken.charPos + nameToken.val.length();
-        final SourceSection src = source.createSection(".", startPos, endPos - startPos);
-        return SLReadPropertyNode.create(src, receiverNode, nameToken.val);
-    }
-
-    /**
-     * Returns an {@link SLWritePropertyNode} for the given parameters.
-     *
-     * @param receiverNode The receiver object of the property assignment
-     * @param nameToken The name of the property being assigned
-     * @param valueNode The value to be assigned
-     * @return An SLExpressionNode for the given parameters.
-     */
-    public SLExpressionNode createWriteProperty(SLExpressionNode receiverNode, Token nameToken, SLExpressionNode valueNode) {
-        final int start = receiverNode.getSourceSection().getCharIndex();
-        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
-        SourceSection src = source.createSection("=", start, length);
-        return SLWritePropertyNode.create(src, receiverNode, nameToken.val, valueNode);
-    }
-
-    /**
-     * Creates source description of a single token.
-     */
-    private SourceSection srcFromToken(Token token) {
-        return source.createSection(token.val, token.charPos, token.val.length());
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,515 +0,0 @@
-/*-------------------------------------------------------------------------
-Compiler Generator Coco/R,
-Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
-extended by M. Loeberbauer & A. Woess, Univ. of Linz
-ported from C# to Java by Wolfgang Ahorner
-with improvements by Pat Terry, Rhodes University
-
-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, 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.
-
-As an exception, it is allowed to write an extension of Coco/R that is
-used as a plugin in non-free software.
-
-If not otherwise stated, any source code generated by Coco/R (other than 
-Coco/R itself) does not fall under the GNU General Public License.
-------------------------------------------------------------------------*/
--->begin
-package com.oracle.truffle.sl.parser;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.Map;
-import java.util.HashMap;
-
-// Checkstyle: stop
-// @formatter:off
-class Token {
-
-    public int kind; // token kind
-    public int pos; // token position in bytes in the source text (starting at 0)
-    public int charPos; // token position in characters in the source text (starting at 0)
-    public int col; // token column (starting at 1)
-    public int line; // token line (starting at 1)
-    public String val; // token value
-    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
-}
-
-// -----------------------------------------------------------------------------------
-// Buffer
-// -----------------------------------------------------------------------------------
-class Buffer {
-
-    // This Buffer supports the following cases:
-    // 1) seekable stream (file)
-    // a) whole stream in buffer
-    // b) part of stream in buffer
-    // 2) non seekable stream (network, console)
-
-    public static final int EOF = Character.MAX_VALUE + 1;
-    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
-    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
-    private byte[] buf; // input buffer
-    private int bufStart; // position of first byte in buffer relative to input stream
-    private int bufLen; // length of buffer
-    private int fileLen; // length of input stream (may change if stream is no file)
-    private int bufPos; // current position in buffer
-    private RandomAccessFile file; // input stream (seekable)
-    private InputStream stream; // growing input stream (e.g.: console, network)
-
-    public Buffer(InputStream s) {
-        stream = s;
-        fileLen = bufLen = bufStart = bufPos = 0;
-        buf = new byte[MIN_BUFFER_LENGTH];
-    }
-
-    public Buffer(String fileName) {
-        try {
-            file = new RandomAccessFile(fileName, "r");
-            fileLen = (int) file.length();
-            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
-            buf = new byte[bufLen];
-            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
-            if (fileLen > 0)
-                setPos(0); // setup buffer to position 0 (start)
-            else
-                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
-            if (bufLen == fileLen)
-                Close();
-        } catch (IOException e) {
-            throw new FatalError("Could not open file " + fileName);
-        }
-    }
-
-    // don't use b after this call anymore
-    // called in UTF8Buffer constructor
-    protected Buffer(Buffer b) {
-        buf = b.buf;
-        bufStart = b.bufStart;
-        bufLen = b.bufLen;
-        fileLen = b.fileLen;
-        bufPos = b.bufPos;
-        file = b.file;
-        stream = b.stream;
-        // keep finalize from closing the file
-        b.file = null;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        Close();
-    }
-
-    protected void Close() {
-        if (file != null) {
-            try {
-                file.close();
-                file = null;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        }
-    }
-
-    public int Read() {
-        if (bufPos < bufLen) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (getPos() < fileLen) {
-            setPos(getPos()); // shift buffer start to pos
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (stream != null && ReadNextStreamChunk() > 0) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else {
-            return EOF;
-        }
-    }
-
-    public int Peek() {
-        int curPos = getPos();
-        int ch = Read();
-        setPos(curPos);
-        return ch;
-    }
-
-    // beg .. begin, zero-based, inclusive, in byte
-    // end .. end, zero-based, exclusive, in byte
-    public String GetString(int beg, int end) {
-        int len = 0;
-        char[] buffer = new char[end - beg];
-        int oldPos = getPos();
-        setPos(beg);
-        while (getPos() < end)
-            buffer[len++] = (char) Read();
-        setPos(oldPos);
-        return new String(buffer, 0, len);
-    }
-
-    public int getPos() {
-        return bufPos + bufStart;
-    }
-
-    public void setPos(int value) {
-        if (value >= fileLen && stream != null) {
-            // Wanted position is after buffer and the stream
-            // is not seek-able e.g. network or console,
-            // thus we have to read the stream manually till
-            // the wanted position is in sight.
-            while (value >= fileLen && ReadNextStreamChunk() > 0) {
-                // nothing to do...
-            }
-        }
-
-        if (value < 0 || value > fileLen) {
-            throw new FatalError("buffer out of bounds access, position: " + value);
-        }
-
-        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
-            bufPos = value - bufStart;
-        } else if (file != null) { // must be swapped in
-            try {
-                file.seek(value);
-                bufLen = file.read(buf);
-                bufStart = value;
-                bufPos = 0;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        } else {
-            // set the position to the end of the file, Pos will return fileLen.
-            bufPos = fileLen - bufStart;
-        }
-    }
-
-    // Read the next chunk of bytes from the stream, increases the buffer
-    // if needed and updates the fields fileLen and bufLen.
-    // Returns the number of bytes read.
-    private int ReadNextStreamChunk() {
-        int free = buf.length - bufLen;
-        if (free == 0) {
-            // in the case of a growing input stream
-            // we can neither seek in the stream, nor can we
-            // foresee the maximum length, thus we must adapt
-            // the buffer size on demand.
-            byte[] newBuf = new byte[bufLen * 2];
-            System.arraycopy(buf, 0, newBuf, 0, bufLen);
-            buf = newBuf;
-            free = bufLen;
-        }
-
-        int read;
-        try {
-            read = stream.read(buf, bufLen, free);
-        } catch (IOException ioex) {
-            throw new FatalError(ioex.getMessage());
-        }
-
-        if (read > 0) {
-            fileLen = bufLen = (bufLen + read);
-            return read;
-        }
-        // end of stream reached
-        return 0;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// UTF8Buffer
-// -----------------------------------------------------------------------------------
-class UTF8Buffer extends Buffer {
-
-    UTF8Buffer(Buffer b) {
-        super(b);
-    }
-
-    @Override
-    public int Read() {
-        int ch;
-        do {
-            ch = super.Read();
-            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
-        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
-        if (ch < 128 || ch == EOF) {
-            // nothing to do, first 127 chars are the same in ascii and utf8
-            // 0xxxxxxx or end of file character
-        } else if ((ch & 0xF0) == 0xF0) {
-            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x07;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = super.Read();
-            int c4 = ch & 0x3F;
-            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
-        } else if ((ch & 0xE0) == 0xE0) {
-            // 1110xxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x0F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = (((c1 << 6) | c2) << 6) | c3;
-        } else if ((ch & 0xC0) == 0xC0) {
-            // 110xxxxx 10xxxxxx
-            int c1 = ch & 0x1F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = (c1 << 6) | c2;
-        }
-        return ch;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// StartStates -- maps characters to start states of tokens
-// -----------------------------------------------------------------------------------
-class StartStates {
-
-    private static class Elem {
-
-        public int key, val;
-        public Elem next;
-
-        public Elem(int key, int val) {
-            this.key = key;
-            this.val = val;
-        }
-    }
-
-    private Elem[] tab = new Elem[128];
-
-    public void set(int key, int val) {
-        Elem e = new Elem(key, val);
-        int k = key % 128;
-        e.next = tab[k];
-        tab[k] = e;
-    }
-
-    public int state(int key) {
-        Elem e = tab[key % 128];
-        while (e != null && e.key != key)
-            e = e.next;
-        return e == null ? 0 : e.val;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// Scanner
-// -----------------------------------------------------------------------------------
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class Scanner {
-
-    static final char EOL = '\n';
-    static final int eofSym = 0;
--->declarations
-
-    public Buffer buffer; // scanner buffer
-
-    Token t; // current token
-    int ch; // current input character
-    int pos; // byte position of current character
-    int charPos; // position by unicode characters starting with 0
-    int col; // column number of current character
-    int line; // line number of current character
-    int oldEols; // EOLs that appeared in a comment;
-    static final StartStates start; // maps initial token character to start state
-    static final Map literals; // maps literal strings to literal kinds
-
-    Token tokens; // list of tokens already peeked (first token is a dummy)
-    Token pt; // current peek token
-
-    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
-    int tlen; // length of current token
-
-    static {
-        start = new StartStates();
-        literals = new HashMap();
--->initialization
-    }
-
-    public Scanner(String fileName) {
-        buffer = new Buffer(fileName);
-        Init();
-    }
-
-    public Scanner(InputStream s) {
-        buffer = new Buffer(s);
-        Init();
-    }
-
-    void Init() {
-        pos = -1;
-        line = 1;
-        col = 0;
-        charPos = -1;
-        oldEols = 0;
-        NextCh();
-        if (ch == 0xEF) { // check optional byte order mark for UTF-8
-            NextCh();
-            int ch1 = ch;
-            NextCh();
-            int ch2 = ch;
-            if (ch1 != 0xBB || ch2 != 0xBF) {
-                throw new FatalError("Illegal byte order mark at start of file");
-            }
-            buffer = new UTF8Buffer(buffer);
-            col = 0;
-            charPos = -1;
-            NextCh();
-        }
-        pt = tokens = new Token(); // first token is a dummy
-    }
-
-    void NextCh() {
-        if (oldEols > 0) {
-            ch = EOL;
-            oldEols--;
-        } else {
-            pos = buffer.getPos();
-            // buffer reads unicode chars, if UTF8 has been detected
-            ch = buffer.Read();
-            col++;
-            charPos++;
-            // replace isolated '\r' by '\n' in order to make
-            // eol handling uniform across Windows, Unix and Mac
-            if (ch == '\r' && buffer.Peek() != '\n')
-                ch = EOL;
-            if (ch == EOL) {
-                line++;
-                col = 0;
-            }
-        }
--->casing
-    }
-
-    void AddCh() {
-        if (tlen >= tval.length) {
-            char[] newBuf = new char[2 * tval.length];
-            System.arraycopy(tval, 0, newBuf, 0, tval.length);
-            tval = newBuf;
-        }
-        if (ch != Buffer.EOF) {
--->casing2
-            NextCh();
-        }
-    }
-
--->comments
-
-    void CheckLiteral() {
-        String val = t.val;
--->casing3
-        Object kind = literals.get(val);
-        if (kind != null) {
-            t.kind = ((Integer) kind).intValue();
-        }
-    }
-
-    Token NextToken() {
-        while (ch == ' ' || 
--->scan1
-        ) NextCh();
--->scan2
-        int recKind = noSym;
-        int recEnd = pos;
-        t = new Token();
-        t.pos = pos;
-        t.col = col;
-        t.line = line;
-        t.charPos = charPos;
-        int state = start.state(ch);
-        tlen = 0;
-        AddCh();
-
-        loop: for (;;) {
-            switch (state) {
-                case -1: {
-                    t.kind = eofSym;
-                    break loop;
-                } // NextCh already done
-                case 0: {
-                    if (recKind != noSym) {
-                        tlen = recEnd - t.pos;
-                        SetScannerBehindT();
-                    }
-                    t.kind = recKind;
-                    break loop;
-                } // NextCh already done
--->scan3
-            }
-        }
-        t.val = new String(tval, 0, tlen);
-        return t;
-    }
-
-    private void SetScannerBehindT() {
-        buffer.setPos(t.pos);
-        NextCh();
-        line = t.line;
-        col = t.col;
-        charPos = t.charPos;
-        for (int i = 0; i < tlen; i++)
-            NextCh();
-    }
-
-    // get the next token (possibly a token already seen during peeking)
-    public Token Scan() {
-        if (tokens.next == null) {
-            return NextToken();
-        } else {
-            pt = tokens = tokens.next;
-            return tokens;
-        }
-    }
-
-    // get the next token, ignore pragmas
-    public Token Peek() {
-        do {
-            if (pt.next == null) {
-                pt.next = NextToken();
-            }
-            pt = pt.next;
-        } while (pt.kind > maxT); // skip pragmas
-
-        return pt;
-    }
-
-    // make sure that peeking starts at current scan position
-    public void ResetPeek() {
-        pt = tokens;
-    }
-
-    // The following methods are used for the CLNG Editor and will be called with java.Reflection.
-    // If the editor won't be used these 3 functions are obsolete,
-    // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly
-// anymore.
-
-    // get the offset of the next Token
-    public int getPeekTokenOffset() {
-        return pt.pos;
-    }
-
-    // get the String value of the Token
-    public String getPeekTokenVal() {
-        return pt.val;
-    }
-
-    // get the Kind value of the Token
-    public int getPeekTokenKind() {
-        return pt.kind;
-    }
-
-} // end Scanner
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,654 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// The content of this file is automatically generated. DO NOT EDIT.
-
-package com.oracle.truffle.sl.parser;
-
-import java.io.*;
-import java.util.*;
-
-// Checkstyle: stop
-// @formatter:off
-class Token {
-
-    public int kind; // token kind
-    public int pos; // token position in bytes in the source text (starting at 0)
-    public int charPos; // token position in characters in the source text (starting at 0)
-    public int col; // token column (starting at 1)
-    public int line; // token line (starting at 1)
-    public String val; // token value
-    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
-}
-
-// -----------------------------------------------------------------------------------
-// Buffer
-// -----------------------------------------------------------------------------------
-class Buffer {
-
-    // This Buffer supports the following cases:
-    // 1) seekable stream (file)
-    // a) whole stream in buffer
-    // b) part of stream in buffer
-    // 2) non seekable stream (network, console)
-
-    public static final int EOF = Character.MAX_VALUE + 1;
-    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
-    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
-    private byte[] buf; // input buffer
-    private int bufStart; // position of first byte in buffer relative to input stream
-    private int bufLen; // length of buffer
-    private int fileLen; // length of input stream (may change if stream is no file)
-    private int bufPos; // current position in buffer
-    private RandomAccessFile file; // input stream (seekable)
-    private InputStream stream; // growing input stream (e.g.: console, network)
-
-    public Buffer(InputStream s) {
-        stream = s;
-        fileLen = bufLen = bufStart = bufPos = 0;
-        buf = new byte[MIN_BUFFER_LENGTH];
-    }
-
-    public Buffer(String fileName) {
-        try {
-            file = new RandomAccessFile(fileName, "r");
-            fileLen = (int) file.length();
-            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
-            buf = new byte[bufLen];
-            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
-            if (fileLen > 0)
-                setPos(0); // setup buffer to position 0 (start)
-            else
-                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
-            if (bufLen == fileLen)
-                Close();
-        } catch (IOException e) {
-            throw new FatalError("Could not open file " + fileName);
-        }
-    }
-
-    // don't use b after this call anymore
-    // called in UTF8Buffer constructor
-    protected Buffer(Buffer b) {
-        buf = b.buf;
-        bufStart = b.bufStart;
-        bufLen = b.bufLen;
-        fileLen = b.fileLen;
-        bufPos = b.bufPos;
-        file = b.file;
-        stream = b.stream;
-        // keep finalize from closing the file
-        b.file = null;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        Close();
-    }
-
-    protected void Close() {
-        if (file != null) {
-            try {
-                file.close();
-                file = null;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        }
-    }
-
-    public int Read() {
-        if (bufPos < bufLen) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (getPos() < fileLen) {
-            setPos(getPos()); // shift buffer start to pos
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else if (stream != null && ReadNextStreamChunk() > 0) {
-            return buf[bufPos++] & 0xff; // mask out sign bits
-        } else {
-            return EOF;
-        }
-    }
-
-    public int Peek() {
-        int curPos = getPos();
-        int ch = Read();
-        setPos(curPos);
-        return ch;
-    }
-
-    // beg .. begin, zero-based, inclusive, in byte
-    // end .. end, zero-based, exclusive, in byte
-    public String GetString(int beg, int end) {
-        int len = 0;
-        char[] buffer = new char[end - beg];
-        int oldPos = getPos();
-        setPos(beg);
-        while (getPos() < end)
-            buffer[len++] = (char) Read();
-        setPos(oldPos);
-        return new String(buffer, 0, len);
-    }
-
-    public int getPos() {
-        return bufPos + bufStart;
-    }
-
-    public void setPos(int value) {
-        if (value >= fileLen && stream != null) {
-            // Wanted position is after buffer and the stream
-            // is not seek-able e.g. network or console,
-            // thus we have to read the stream manually till
-            // the wanted position is in sight.
-            while (value >= fileLen && ReadNextStreamChunk() > 0) {
-                // nothing to do...
-            }
-        }
-
-        if (value < 0 || value > fileLen) {
-            throw new FatalError("buffer out of bounds access, position: " + value);
-        }
-
-        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
-            bufPos = value - bufStart;
-        } else if (file != null) { // must be swapped in
-            try {
-                file.seek(value);
-                bufLen = file.read(buf);
-                bufStart = value;
-                bufPos = 0;
-            } catch (IOException e) {
-                throw new FatalError(e.getMessage());
-            }
-        } else {
-            // set the position to the end of the file, Pos will return fileLen.
-            bufPos = fileLen - bufStart;
-        }
-    }
-
-    // Read the next chunk of bytes from the stream, increases the buffer
-    // if needed and updates the fields fileLen and bufLen.
-    // Returns the number of bytes read.
-    private int ReadNextStreamChunk() {
-        int free = buf.length - bufLen;
-        if (free == 0) {
-            // in the case of a growing input stream
-            // we can neither seek in the stream, nor can we
-            // foresee the maximum length, thus we must adapt
-            // the buffer size on demand.
-            byte[] newBuf = new byte[bufLen * 2];
-            System.arraycopy(buf, 0, newBuf, 0, bufLen);
-            buf = newBuf;
-            free = bufLen;
-        }
-
-        int read;
-        try {
-            read = stream.read(buf, bufLen, free);
-        } catch (IOException ioex) {
-            throw new FatalError(ioex.getMessage());
-        }
-
-        if (read > 0) {
-            fileLen = bufLen = (bufLen + read);
-            return read;
-        }
-        // end of stream reached
-        return 0;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// UTF8Buffer
-// -----------------------------------------------------------------------------------
-class UTF8Buffer extends Buffer {
-
-    UTF8Buffer(Buffer b) {
-        super(b);
-    }
-
-    @Override
-    public int Read() {
-        int ch;
-        do {
-            ch = super.Read();
-            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
-        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
-        if (ch < 128 || ch == EOF) {
-            // nothing to do, first 127 chars are the same in ascii and utf8
-            // 0xxxxxxx or end of file character
-        } else if ((ch & 0xF0) == 0xF0) {
-            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x07;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = super.Read();
-            int c4 = ch & 0x3F;
-            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
-        } else if ((ch & 0xE0) == 0xE0) {
-            // 1110xxxx 10xxxxxx 10xxxxxx
-            int c1 = ch & 0x0F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = super.Read();
-            int c3 = ch & 0x3F;
-            ch = (((c1 << 6) | c2) << 6) | c3;
-        } else if ((ch & 0xC0) == 0xC0) {
-            // 110xxxxx 10xxxxxx
-            int c1 = ch & 0x1F;
-            ch = super.Read();
-            int c2 = ch & 0x3F;
-            ch = (c1 << 6) | c2;
-        }
-        return ch;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// StartStates -- maps characters to start states of tokens
-// -----------------------------------------------------------------------------------
-class StartStates {
-
-    private static class Elem {
-
-        public int key, val;
-        public Elem next;
-
-        public Elem(int key, int val) {
-            this.key = key;
-            this.val = val;
-        }
-    }
-
-    private Elem[] tab = new Elem[128];
-
-    public void set(int key, int val) {
-        Elem e = new Elem(key, val);
-        int k = key % 128;
-        e.next = tab[k];
-        tab[k] = e;
-    }
-
-    public int state(int key) {
-        Elem e = tab[key % 128];
-        while (e != null && e.key != key)
-            e = e.next;
-        return e == null ? 0 : e.val;
-    }
-}
-
-// -----------------------------------------------------------------------------------
-// Scanner
-// -----------------------------------------------------------------------------------
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class Scanner {
-
-    static final char EOL = '\n';
-    static final int eofSym = 0;
-	static final int maxT = 31;
-	static final int noSym = 31;
-
-
-    public Buffer buffer; // scanner buffer
-
-    Token t; // current token
-    int ch; // current input character
-    int pos; // byte position of current character
-    int charPos; // position by unicode characters starting with 0
-    int col; // column number of current character
-    int line; // line number of current character
-    int oldEols; // EOLs that appeared in a comment;
-    static final StartStates start; // maps initial token character to start state
-    static final Map literals; // maps literal strings to literal kinds
-
-    Token tokens; // list of tokens already peeked (first token is a dummy)
-    Token pt; // current peek token
-
-    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
-    int tlen; // length of current token
-
-    static {
-        start = new StartStates();
-        literals = new HashMap();
-		for (int i = 65; i <= 90; ++i) start.set(i, 1);
-		for (int i = 97; i <= 122; ++i) start.set(i, 1);
-		for (int i = 49; i <= 57; ++i) start.set(i, 4);
-		start.set(34, 2);
-		start.set(48, 5);
-		start.set(40, 6);
-		start.set(44, 7);
-		start.set(41, 8);
-		start.set(123, 9);
-		start.set(125, 10);
-		start.set(59, 11);
-		start.set(124, 12);
-		start.set(38, 14);
-		start.set(60, 26);
-		start.set(62, 27);
-		start.set(61, 28);
-		start.set(33, 19);
-		start.set(43, 21);
-		start.set(45, 22);
-		start.set(42, 23);
-		start.set(47, 24);
-		start.set(46, 25);
-		start.set(Buffer.EOF, -1);
-		literals.put("function", new Integer(4));
-		literals.put("break", new Integer(10));
-		literals.put("continue", new Integer(12));
-		literals.put("while", new Integer(13));
-		literals.put("if", new Integer(14));
-		literals.put("else", new Integer(15));
-		literals.put("return", new Integer(16));
-
-    }
-
-    public Scanner(String fileName) {
-        buffer = new Buffer(fileName);
-        Init();
-    }
-
-    public Scanner(InputStream s) {
-        buffer = new Buffer(s);
-        Init();
-    }
-
-    void Init() {
-        pos = -1;
-        line = 1;
-        col = 0;
-        charPos = -1;
-        oldEols = 0;
-        NextCh();
-        if (ch == 0xEF) { // check optional byte order mark for UTF-8
-            NextCh();
-            int ch1 = ch;
-            NextCh();
-            int ch2 = ch;
-            if (ch1 != 0xBB || ch2 != 0xBF) {
-                throw new FatalError("Illegal byte order mark at start of file");
-            }
-            buffer = new UTF8Buffer(buffer);
-            col = 0;
-            charPos = -1;
-            NextCh();
-        }
-        pt = tokens = new Token(); // first token is a dummy
-    }
-
-    void NextCh() {
-        if (oldEols > 0) {
-            ch = EOL;
-            oldEols--;
-        } else {
-            pos = buffer.getPos();
-            // buffer reads unicode chars, if UTF8 has been detected
-            ch = buffer.Read();
-            col++;
-            charPos++;
-            // replace isolated '\r' by '\n' in order to make
-            // eol handling uniform across Windows, Unix and Mac
-            if (ch == '\r' && buffer.Peek() != '\n')
-                ch = EOL;
-            if (ch == EOL) {
-                line++;
-                col = 0;
-            }
-        }
-
-    }
-
-    void AddCh() {
-        if (tlen >= tval.length) {
-            char[] newBuf = new char[2 * tval.length];
-            System.arraycopy(tval, 0, newBuf, 0, tval.length);
-            tval = newBuf;
-        }
-        if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch;
-
-            NextCh();
-        }
-    }
-
-
-	boolean Comment0() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '/') {
-			NextCh();
-			for(;;) {
-				if (ch == 10) {
-					level--;
-					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-					NextCh();
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
-
-	boolean Comment1() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '*') {
-			NextCh();
-			for(;;) {
-				if (ch == '*') {
-					NextCh();
-					if (ch == '/') {
-						level--;
-						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-						NextCh();
-					}
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
-
-
-    void CheckLiteral() {
-        String val = t.val;
-
-        Object kind = literals.get(val);
-        if (kind != null) {
-            t.kind = ((Integer) kind).intValue();
-        }
-    }
-
-    Token NextToken() {
-        while (ch == ' ' ||
-			ch >= 9 && ch <= 10 || ch == 13
-        ) NextCh();
-		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
-        int recKind = noSym;
-        int recEnd = pos;
-        t = new Token();
-        t.pos = pos;
-        t.col = col;
-        t.line = line;
-        t.charPos = charPos;
-        int state = start.state(ch);
-        tlen = 0;
-        AddCh();
-
-        loop: for (;;) {
-            switch (state) {
-                case -1: {
-                    t.kind = eofSym;
-                    break loop;
-                } // NextCh already done
-                case 0: {
-                    if (recKind != noSym) {
-                        tlen = recEnd - t.pos;
-                        SetScannerBehindT();
-                    }
-                    t.kind = recKind;
-                    break loop;
-                } // NextCh already done
-				case 1:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 2:
-					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
-					else if (ch == '"') {AddCh(); state = 3; break;}
-					else {state = 0; break;}
-				case 3:
-					{t.kind = 2; break loop;}
-				case 4:
-					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
-					else {t.kind = 3; break loop;}
-				case 5:
-					{t.kind = 3; break loop;}
-				case 6:
-					{t.kind = 5; break loop;}
-				case 7:
-					{t.kind = 6; break loop;}
-				case 8:
-					{t.kind = 7; break loop;}
-				case 9:
-					{t.kind = 8; break loop;}
-				case 10:
-					{t.kind = 9; break loop;}
-				case 11:
-					{t.kind = 11; break loop;}
-				case 12:
-					if (ch == '|') {AddCh(); state = 13; break;}
-					else {state = 0; break;}
-				case 13:
-					{t.kind = 17; break loop;}
-				case 14:
-					if (ch == '&') {AddCh(); state = 15; break;}
-					else {state = 0; break;}
-				case 15:
-					{t.kind = 18; break loop;}
-				case 16:
-					{t.kind = 20; break loop;}
-				case 17:
-					{t.kind = 22; break loop;}
-				case 18:
-					{t.kind = 23; break loop;}
-				case 19:
-					if (ch == '=') {AddCh(); state = 20; break;}
-					else {state = 0; break;}
-				case 20:
-					{t.kind = 24; break loop;}
-				case 21:
-					{t.kind = 25; break loop;}
-				case 22:
-					{t.kind = 26; break loop;}
-				case 23:
-					{t.kind = 27; break loop;}
-				case 24:
-					{t.kind = 28; break loop;}
-				case 25:
-					{t.kind = 30; break loop;}
-				case 26:
-					recEnd = pos; recKind = 19;
-					if (ch == '=') {AddCh(); state = 16; break;}
-					else {t.kind = 19; break loop;}
-				case 27:
-					recEnd = pos; recKind = 21;
-					if (ch == '=') {AddCh(); state = 17; break;}
-					else {t.kind = 21; break loop;}
-				case 28:
-					recEnd = pos; recKind = 29;
-					if (ch == '=') {AddCh(); state = 18; break;}
-					else {t.kind = 29; break loop;}
-
-            }
-        }
-        t.val = new String(tval, 0, tlen);
-        return t;
-    }
-
-    private void SetScannerBehindT() {
-        buffer.setPos(t.pos);
-        NextCh();
-        line = t.line;
-        col = t.col;
-        charPos = t.charPos;
-        for (int i = 0; i < tlen; i++)
-            NextCh();
-    }
-
-    // get the next token (possibly a token already seen during peeking)
-    public Token Scan() {
-        if (tokens.next == null) {
-            return NextToken();
-        } else {
-            pt = tokens = tokens.next;
-            return tokens;
-        }
-    }
-
-    // get the next token, ignore pragmas
-    public Token Peek() {
-        do {
-            if (pt.next == null) {
-                pt.next = NextToken();
-            }
-            pt = pt.next;
-        } while (pt.kind > maxT); // skip pragmas
-
-        return pt;
-    }
-
-    // make sure that peeking starts at current scan position
-    public void ResetPeek() {
-        pt = tokens;
-    }
-
-    // The following methods are used for the CLNG Editor and will be called with java.Reflection.
-    // If the editor won't be used these 3 functions are obsolete,
-    // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly
-// anymore.
-
-    // get the offset of the next Token
-    public int getPeekTokenOffset() {
-        return pt.pos;
-    }
-
-    // get the String value of the Token
-    public String getPeekTokenVal() {
-        return pt.val;
-    }
-
-    // get the Kind value of the Token
-    public int getPeekTokenKind() {
-        return pt.kind;
-    }
-
-} // end Scanner
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This is the grammar of SL that is used to automatically generate the Parser.java and Scanner.java
- * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run
- * "java -jar Coco.jar SimpleLanguage.atg"
- */
-
-COMPILER SimpleLanguage
-
-CHARACTERS
-
-letter = 'A'..'Z' + 'a'..'z'.
-nonZeroDigit = "123456789".
-digit = "0123456789".
-cr = '\r'.
-lf = '\n'.
-tab = '\t'.
-stringChar = ANY - "\"" - '\\' - cr - lf.
-
-TOKENS
-
-identifier = letter {letter | digit}.
-stringLiteral = "\"" { stringChar } "\"".
-numericLiteral = "0" | nonZeroDigit { digit }.
-
-PRAGMAS
-
-COMMENTS FROM "/*" TO "*/"
-COMMENTS FROM "//" TO lf
-IGNORE cr + lf + tab
-
-PRODUCTIONS
-
-
-SimpleLanguage
-=
-Function
-{
-     Function
-}
-.
-
-
-Function
-=
-"function"
-identifier                                      (. Token identifierToken = t; .)
-"("                                             (. int bodyStartPos = t.charPos; .)
-                                                (. factory.startFunction(identifierToken, bodyStartPos); .)
-[
-    identifier                                  (. factory.addFormalParameter(t); .)
-    {
-        ","
-        identifier                              (. factory.addFormalParameter(t); .)
-    }
-]
-")"
-Block<out SLStatementNode body, false>          (. factory.finishFunction(body); .)
-.
-
-
-
-Block<out SLStatementNode result, boolean inLoop>
-=                                               (. factory.startBlock();
-                                                   List<SLStatementNode> body = new ArrayList<>(); .)
-"{"                                             (. int start = t.charPos; .)
-{
-    Statement<out SLStatementNode s, inLoop>    (. body.add(s); .)
-}
-"}"                                             (. int length = (t.charPos + t.val.length()) - start; .)
-                                                (. result = factory.finishBlock(body, start, length); .)
-.
-
-
-Statement<out SLStatementNode result, boolean inLoop>
-=                                               (. result = null; .)
-(
-    WhileStatement<out result>
-|
-    "break"                                     (. if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } .)
-    ";"
-|
-    "continue"                                  (. if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } .)
-    ";"
-|
-    IfStatement<out result, inLoop>
-|
-    ReturnStatement<out result>
-|
-    Expression<out result> ";"
-)
-.
-
-
-WhileStatement<out SLStatementNode result>
-=
-"while"                                         (. Token whileToken = t; .)
-"("
-Expression<out SLExpressionNode condition>
-")"
-Block<out SLStatementNode body, true>           (. result = factory.createWhile(whileToken, condition, body); .)
-.
-
-
-IfStatement<out SLStatementNode result, boolean inLoop>
-=
-"if"                                            (. Token ifToken = t; .)
-"("
-Expression<out SLExpressionNode condition>
-")"
-Block<out SLStatementNode thenPart, inLoop>     (. SLStatementNode elsePart = null; .)
-[
-    "else"
-    Block<out elsePart, inLoop>
-]                                               (. result = factory.createIf(ifToken, condition, thenPart, elsePart); .)
-.
-
-
-ReturnStatement<out SLStatementNode result>
-=
-"return"                                        (. Token returnToken = t;
-                                                   SLExpressionNode value = null; .)
-[
-    Expression<out value>
-]                                               (. result = factory.createReturn(returnToken, value); .)
-";"
-.
-
-
-Expression<out SLExpressionNode result>
-=
-LogicTerm<out result>
-{
-    "||"                                        (. Token op = t; .)
-    LogicTerm<out SLExpressionNode right>       (. result = factory.createBinary(op, result, right); .)
-}
-.
-
-
-LogicTerm<out SLExpressionNode result>
-=
-LogicFactor<out result>
-{
-    "&&"                                        (. Token op = t; .)
-    LogicFactor<out SLExpressionNode right>     (. result = factory.createBinary(op, result, right); .)
-}
-.
-
-
-LogicFactor<out SLExpressionNode result>
-=
-Arithmetic<out result>
-[
-    ("<" | "<=" | ">" | ">=" | "==" | "!=" )    (. Token op = t; .)
-    Arithmetic<out SLExpressionNode right>      (.  result = factory.createBinary(op, result, right); .)
-]
-.
-
-
-Arithmetic<out SLExpressionNode result>
-=
-Term<out result>
-{
-    ("+" | "-")                                 (. Token op = t; .)
-    Term<out SLExpressionNode right>            (. result = factory.createBinary(op, result, right); .)
-}
-.
-
-
-Term<out SLExpressionNode result>
-=
-Factor<out result>
-{
-    ("*" | "/")                                 (. Token op = t; .)
-    Factor<out SLExpressionNode right>          (. result = factory.createBinary(op, result, right); .)
-}
-.
-
-
-Factor<out SLExpressionNode result>
-=                                               (. result = null; .)
-(
-    identifier
-    (
-        MemberExpression<out result, null, null, t>
-    |
-                                                (. result = factory.createRead(t); .)
-    )
-|
-    stringLiteral                               (. result = factory.createStringLiteral(t); .)
-|
-    numericLiteral                              (. result = factory.createNumericLiteral(t); .)
-|
-    "("                                         (. int start = t.charPos; .)
-    Expression<out result>                      (. SLExpressionNode expr = result; .)
-    ")"                                         (. int length = (t.charPos + t.val.length()) - start; .)
-                                                (. result = factory.createParenExpression(expr, start, length); .)
-)
-.
-
-
-MemberExpression<out SLExpressionNode result, SLExpressionNode r, SLExpressionNode assignmentReceiver, Token assignmentName>
-=                                               (. result = null;
-                                                   SLExpressionNode receiver = r;
-                                                   Token nestedAssignmentName = null; .)
-(
-    "("                                         (. List<SLExpressionNode> parameters = new ArrayList<>();
-                                                   SLExpressionNode parameter;
-                                                   if (receiver == null) {
-                                                       receiver = factory.createRead(assignmentName); 
-                                                   } .)
-    [
-        Expression<out parameter>               (. parameters.add(parameter); .)
-        {
-            ","
-            Expression<out parameter>           (. parameters.add(parameter); .)
-        }
-    ]
-    ")"                                         (. Token finalToken = t; .)
-                                                (. result = factory.createCall(receiver, parameters, finalToken); .)
-|
-    "="
-    Expression<out SLExpressionNode value>      (. if (assignmentName == null) {
-                                                       SemErr("invalid assignment target");
-                                                   } else if (assignmentReceiver == null) {
-                                                       result = factory.createAssignment(assignmentName, value);
-                                                   } else {
-                                                       result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
-                                                   } .)
-|
-    "."                                         (. if (receiver == null) {
-                                                       receiver = factory.createRead(assignmentName); 
-                                                   } .)
-    identifier
-                                                (. result = factory.createReadProperty(receiver, t); .)
-                                                (. nestedAssignmentName = t; .)
-)
-[
-    MemberExpression<out result, result, receiver, nestedAssignmentName>
-]
-.
-
-
-END SimpleLanguage.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.runtime;
-
-import java.io.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.object.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.sl.builtins.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.local.*;
-import com.oracle.truffle.sl.parser.*;
-
-/**
- * The run-time state of SL during execution. One context is instantiated before any source code is
- * parsed, and this context is passed around to all methods that need access to it. For example, the
- * context is used during {@link SLNodeFactory parsing} and by {@link SLBuiltinNode#getContext()
- * builtin functions}.
- * <p>
- * It would be an error to have two different context instances during the execution of one script.
- * However, if two separate scripts run in one Java VM at the same time, they have a different
- * context. Therefore, the context is not a singleton.
- */
-public final class SLContext extends ExecutionContext {
-    private static final Layout LAYOUT = Layout.createLayout();
-
-    private final BufferedReader input;
-    private final PrintWriter output;
-    private final SLFunctionRegistry functionRegistry;
-    private final Shape emptyShape;
-
-    public SLContext(BufferedReader input, PrintWriter output) {
-        this.input = input;
-        this.output = output;
-        this.functionRegistry = new SLFunctionRegistry();
-        installBuiltins();
-
-        this.emptyShape = LAYOUT.createShape(new ObjectType());
-    }
-
-    /**
-     * Returns the default input, i.e., the source for the {@link SLReadlnBuiltin}. To allow unit
-     * testing, we do not use {@link System#in} directly.
-     */
-    public BufferedReader getInput() {
-        return input;
-    }
-
-    /**
-     * The default default, i.e., the output for the {@link SLPrintlnBuiltin}. To allow unit
-     * testing, we do not use {@link System#out} directly.
-     */
-    public PrintWriter getOutput() {
-        return output;
-    }
-
-    /**
-     * Returns the registry of all functions that are currently defined.
-     */
-    public SLFunctionRegistry getFunctionRegistry() {
-        return functionRegistry;
-    }
-
-    /**
-     * Adds all builtin functions to the {@link SLFunctionRegistry}. This method lists all
-     * {@link SLBuiltinNode builtin implementation classes}.
-     */
-    private void installBuiltins() {
-        installBuiltin(SLReadlnBuiltinFactory.getInstance());
-        installBuiltin(SLPrintlnBuiltinFactory.getInstance());
-        installBuiltin(SLNanoTimeBuiltinFactory.getInstance());
-        installBuiltin(SLDefineFunctionBuiltinFactory.getInstance());
-        installBuiltin(SLStackTraceBuiltinFactory.getInstance());
-        installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
-        installBuiltin(SLAssertTrueBuiltinFactory.getInstance());
-        installBuiltin(SLAssertFalseBuiltinFactory.getInstance());
-        installBuiltin(SLNewObjectBuiltinFactory.getInstance());
-    }
-
-    public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
-        /*
-         * The builtin node factory is a class that is automatically generated by the Truffle DSL.
-         * The signature returned by the factory reflects the signature of the @Specialization
-         * methods in the builtin classes.
-         */
-        int argumentCount = factory.getExecutionSignature().size();
-        SLExpressionNode[] argumentNodes = new SLExpressionNode[argumentCount];
-        /*
-         * Builtin functions are like normal functions, i.e., the arguments are passed in as an
-         * Object[] array encapsulated in SLArguments. A SLReadArgumentNode extracts a parameter
-         * from this array.
-         */
-        for (int i = 0; i < argumentCount; i++) {
-            argumentNodes[i] = new SLReadArgumentNode(null, i);
-        }
-        /* Instantiate the builtin node. This node performs the actual functionality. */
-        SLBuiltinNode builtinBodyNode = factory.createNode(argumentNodes, this);
-        /* The name of the builtin function is specified via an annotation on the node class. */
-        String name = lookupNodeInfo(builtinBodyNode.getClass()).shortName();
-        /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */
-        SLRootNode rootNode = new SLRootNode(this, new FrameDescriptor(), builtinBodyNode, name);
-
-        /* Register the builtin function in our function registry. */
-        getFunctionRegistry().register(name, rootNode);
-    }
-
-    public static NodeInfo lookupNodeInfo(Class<?> clazz) {
-        if (clazz == null) {
-            return null;
-        }
-        NodeInfo info = clazz.getAnnotation(NodeInfo.class);
-        if (info != null) {
-            return info;
-        } else {
-            return lookupNodeInfo(clazz.getSuperclass());
-        }
-    }
-
-    /**
-     * Evaluate a source, causing any definitions to be registered (but not executed).
-     *
-     * @param source The {@link Source} to parse.
-     */
-    public void evalSource(Source source) {
-        Parser.parseSL(this, source);
-    }
-
-    public DynamicObject createObject() {
-        return LAYOUT.newInstance(emptyShape);
-    }
-
-    public static boolean isSLObject(Object value) {
-        return LAYOUT.getType().isInstance(value);
-    }
-
-    public static DynamicObject castSLObject(Object value) {
-        return LAYOUT.getType().cast(value);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.runtime;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.interop.*;
-import com.oracle.truffle.api.utilities.*;
-
-/**
- * Represents a SL function. On the Truffle level, a callable element is represented by a
- * {@link RootCallTarget call target}. This class encapsulates a call target, and adds version
- * support: functions in SL can be redefined, i.e. changed at run time. When a function is
- * redefined, the call target managed by this function object is changed (and {@link #callTarget} is
- * therefore not a final field).
- * <p>
- * Function redefinition is expected to be rare, therefore optimized call nodes want to speculate
- * that the call target is stable. This is possible with the help of a Truffle {@link Assumption}: a
- * call node can keep the call target returned by {@link #getCallTarget()} cached until the
- * assumption returned by {@link #getCallTargetStable()} is valid.
- * <p>
- * The {@link #callTarget} can be {@code null}. To ensure that only one {@link SLFunction} instance
- * per name exists, the {@link SLFunctionRegistry} creates an instance also when performing name
- * lookup. A function that has been looked up, i.e., used, but not defined, has no call target.
- */
-public final class SLFunction implements TruffleObject {
-
-    /** The name of the function. */
-    private final String name;
-
-    /** The current implementation of this function. */
-    private RootCallTarget callTarget;
-
-    /**
-     * Manages the assumption that the {@link #callTarget} is stable. We use the utility class
-     * {@link CyclicAssumption}, which automatically creates a new {@link Assumption} when the old
-     * one gets invalidated.
-     */
-    private final CyclicAssumption callTargetStable;
-
-    protected SLFunction(String name) {
-        this.name = name;
-        this.callTargetStable = new CyclicAssumption(name);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    protected void setCallTarget(RootCallTarget callTarget) {
-        this.callTarget = callTarget;
-        /*
-         * We have a new call target. Invalidate all code that speculated that the old call target
-         * was stable.
-         */
-        callTargetStable.invalidate();
-    }
-
-    public RootCallTarget getCallTarget() {
-        return callTarget;
-    }
-
-    public Assumption getCallTargetStable() {
-        return callTargetStable.getAssumption();
-    }
-
-    /**
-     * This method is, e.g., called when using a function literal in a string concatenation. So
-     * changing it has an effect on SL programs.
-     */
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * In case you want some of your objects to co-operate with other languages, you need to make
-     * them implement {@link TruffleObject} and provide additional {@link SLFunctionForeignAccess
-     * foreign access implementation}.
-     */
-    @Override
-    public ForeignAccess getForeignAccess() {
-        return SLFunctionForeignAccess.INSTANCE;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.runtime;
-
-import com.oracle.truffle.api.CallTarget;
-import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.RootNode;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.sl.nodes.call.SLDispatchNode;
-import com.oracle.truffle.sl.nodes.call.SLDispatchNodeGen;
-import java.math.BigInteger;
-import java.util.List;
-
-/**
- * Implementation of foreign access for {@link SLFunction}.
- */
-final class SLFunctionForeignAccess implements ForeignAccess.Factory {
-    public static final ForeignAccess INSTANCE = ForeignAccess.create(new SLFunctionForeignAccess());
-
-    private SLFunctionForeignAccess() {
-    }
-
-    @Override
-    public boolean canHandle(TruffleObject o) {
-        return o instanceof SLFunction;
-    }
-
-    @Override
-    public CallTarget accessMessage(Message tree) {
-        if (Message.createExecute(0).equals(tree)) {
-            return Truffle.getRuntime().createCallTarget(new SLForeignCallerRootNode());
-        } else if (Message.IS_NULL.equals(tree)) {
-            return Truffle.getRuntime().createCallTarget(new SLForeignNullCheckNode());
-        } else {
-            throw new IllegalArgumentException(tree.toString() + " not supported");
-        }
-    }
-
-    private static class SLForeignCallerRootNode extends RootNode {
-        @Child private SLDispatchNode dispatch = SLDispatchNodeGen.create();
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            SLFunction function = (SLFunction) ForeignAccess.getReceiver(frame);
-            // the calling convention of interop passes the receiver of a
-            // function call (the this object)
-            // as an implicit 1st argument; we need to ignore this argument for SL
-            List<Object> args = ForeignAccess.getArguments(frame);
-            Object[] arr = args.subList(1, args.size()).toArray();
-            for (int i = 0; i < arr.length; i++) {
-                Object a = arr[i];
-                if (a instanceof Long) {
-                    continue;
-                }
-                if (a instanceof BigInteger) {
-                    continue;
-                }
-                if (a instanceof Number) {
-                    arr[i] = ((Number) a).longValue();
-                }
-            }
-            return dispatch.executeDispatch(frame, function, arr);
-        }
-
-    }
-
-    private static class SLForeignNullCheckNode extends RootNode {
-        @Override
-        public Object execute(VirtualFrame frame) {
-            Object receiver = ForeignAccess.getReceiver(frame);
-            return SLNull.SINGLETON == receiver;
-        }
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.runtime;
-
-import java.util.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * Manages the mapping from function names to {@link SLFunction function objects}.
- */
-public final class SLFunctionRegistry {
-
-    private final Map<String, SLFunction> functions = new HashMap<>();
-
-    /**
-     * Returns the canonical {@link SLFunction} object for the given name. If it does not exist yet,
-     * it is created.
-     */
-    public SLFunction lookup(String name) {
-        SLFunction result = functions.get(name);
-        if (result == null) {
-            result = new SLFunction(name);
-            functions.put(name, result);
-        }
-        return result;
-    }
-
-    /**
-     * Associates the {@link SLFunction} with the given name with the given implementation root
-     * node. If the function did not exist before, it defines the function. If the function existed
-     * before, it redefines the function and the old implementation is discarded.
-     */
-    public void register(String name, SLRootNode rootNode) {
-        SLFunction function = lookup(name);
-        RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
-        function.setCallTarget(callTarget);
-    }
-
-    /**
-     * Returns the sorted list of all functions, for printing purposes only.
-     */
-    public List<SLFunction> getFunctions() {
-        List<SLFunction> result = new ArrayList<>(functions.values());
-        Collections.sort(result, new Comparator<SLFunction>() {
-            public int compare(SLFunction f1, SLFunction f2) {
-                return f1.toString().compareTo(f2.toString());
-            }
-        });
-        return result;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.runtime;
-
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.TruffleObject;
-
-/**
- * The SL type for a {@code null} (i.e., undefined) value. In Truffle, it is generally discouraged
- * to use the Java {@code null} value to represent the guest language {@code null} value. It is not
- * possible to specialize on Java {@code null} (since you cannot ask it for the Java class), and
- * there is always the danger of a spurious {@link NullPointerException}. Representing the guest
- * language {@code null} as a singleton, as in {@link #SINGLETON this class}, is the recommended
- * practice.
- */
-public final class SLNull implements TruffleObject {
-
-    /**
-     * The canonical value to represent {@code null} in SL.
-     */
-    public static final SLNull SINGLETON = new SLNull();
-
-    /**
-     * Disallow instantiation from outside to ensure that the {@link #SINGLETON} is the only
-     * instance.
-     */
-    private SLNull() {
-    }
-
-    /**
-     * This method is, e.g., called when using the {@code null} value in a string concatenation. So
-     * changing it has an effect on SL programs.
-     */
-    @Override
-    public String toString() {
-        return "null";
-    }
-
-    @Override
-    public ForeignAccess getForeignAccess() {
-        return SLFunctionForeignAccess.INSTANCE;
-    }
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/EagerStackTraceDecorator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import org.junit.runner.notification.*;
-
-class EagerStackTraceDecorator extends TruffleJUnitRunListenerDecorator {
-
-    public EagerStackTraceDecorator(TruffleJUnitRunListener l) {
-        super(l);
-    }
-
-    @Override
-    public void testFailed(Failure failure) {
-        super.testFailed(failure);
-        failure.getException().printStackTrace(getWriter());
-    }
-
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/GCAfterTestDecorator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import org.junit.runner.*;
-
-final class GCAfterTestDecorator extends TruffleJUnitRunListenerDecorator {
-
-    public GCAfterTestDecorator(TruffleJUnitRunListener l) {
-        super(l);
-    }
-
-    @Override
-    public void testFinished(Description description) {
-        System.gc();
-        super.testFinished(description);
-    }
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TimingDecorator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import org.junit.runner.*;
-
-/**
- * Timing support for JUnit test runs.
- */
-class TimingDecorator extends TruffleJUnitRunListenerDecorator {
-
-    private long startTime;
-    private long classStartTime;
-
-    public TimingDecorator(TruffleJUnitRunListener l) {
-        super(l);
-    }
-
-    @Override
-    public void testClassStarted(Class<?> clazz) {
-        classStartTime = System.nanoTime();
-        super.testClassStarted(clazz);
-    }
-
-    @Override
-    public void testClassFinished(Class<?> clazz) {
-        long totalTime = System.nanoTime() - classStartTime;
-        super.testClassFinished(clazz);
-        getWriter().print(' ' + valueToString(totalTime));
-    }
-
-    @Override
-    public void testStarted(Description description) {
-        startTime = System.nanoTime();
-        super.testStarted(description);
-    }
-
-    @Override
-    public void testFinished(Description description) {
-        long totalTime = System.nanoTime() - startTime;
-        super.testFinished(description);
-        getWriter().print(" " + valueToString(totalTime));
-    }
-
-    private static String valueToString(long value) {
-        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
-    }
-
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitCore.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import java.io.*;
-import java.lang.reflect.Modifier;
-import java.nio.charset.Charset;
-import java.nio.file.*;
-import java.util.*;
-
-import junit.runner.*;
-
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.notification.*;
-import org.junit.runners.*;
-import org.junit.runners.model.*;
-
-final class TruffleJUnitCore {
-
-    /**
-     * Run the tests contained in the classes named in the <code>args</code>. A single test method
-     * can be specified by adding #method after the class name. Only a single test can be run in
-     * this way. If all tests run successfully, exit with a status of 0. Otherwise exit with a
-     * status of 1. Write feedback while tests are running and write stack traces for all failed
-     * tests after the tests all complete.
-     *
-     * @param args names of classes in which to find tests to run
-     */
-    public static void main(String... args) {
-        JUnitSystem system = new RealSystem();
-        JUnitCore junitCore = new JUnitCore();
-        system.out().println("TruffleJUnitCore");
-        system.out().println("JUnit version " + Version.id());
-        List<Class<?>> classes = new ArrayList<>();
-        String methodName = null;
-        List<Failure> missingClasses = new ArrayList<>();
-        boolean verbose = false;
-        boolean enableTiming = false;
-        boolean failFast = false;
-        boolean eagerStackTrace = false;
-        boolean gcAfterTest = false;
-
-        String[] expandedArgs = expandArgs(args);
-        for (int i = 0; i < expandedArgs.length; i++) {
-            String each = expandedArgs[i];
-            if (each.charAt(0) == '-') {
-                // command line arguments
-                if (each.contentEquals("-JUnitVerbose")) {
-                    verbose = true;
-                } else if (each.contentEquals("-JUnitFailFast")) {
-                    failFast = true;
-                } else if (each.contentEquals("-JUnitEnableTiming")) {
-                    enableTiming = true;
-                } else if (each.contentEquals("-JUnitEagerStackTrace")) {
-                    eagerStackTrace = true;
-                } else if (each.contentEquals("-JUnitGCAfterTest")) {
-                    gcAfterTest = true;
-                } else {
-                    system.out().println("Unknown command line argument: " + each);
-                }
-
-            } else {
-                /*
-                 * Entries of the form class#method are handled specially. Only one can be specified
-                 * on the command line as there's no obvious way to build a runner for multiple
-                 * ones.
-                 */
-                if (methodName != null) {
-                    system.out().println("Only a single class and method can be specified: " + each);
-                    System.exit(1);
-                } else if (each.contains("#")) {
-                    String[] pair = each.split("#");
-                    if (pair.length != 2) {
-                        system.out().println("Malformed class and method request: " + each);
-                        System.exit(1);
-                    } else if (classes.size() != 0) {
-                        system.out().println("Only a single class and method can be specified: " + each);
-                        System.exit(1);
-                    } else {
-                        methodName = pair[1];
-                        each = pair[0];
-                    }
-                }
-                try {
-                    Class<?> cls = Class.forName(each, false, TruffleJUnitCore.class.getClassLoader());
-                    if ((cls.getModifiers() & Modifier.ABSTRACT) == 0) {
-                        classes.add(cls);
-                    }
-                } catch (ClassNotFoundException e) {
-                    system.out().println("Could not find class: " + each);
-                    Description description = Description.createSuiteDescription(each);
-                    Failure failure = new Failure(description, e);
-                    missingClasses.add(failure);
-                }
-            }
-        }
-        final TruffleTextListener textListener;
-        if (!verbose) {
-            textListener = new TruffleTextListener(system);
-        } else {
-            textListener = new TruffleVerboseTextListener(system);
-        }
-        TruffleJUnitRunListener listener = textListener;
-        if (enableTiming) {
-            listener = new TimingDecorator(listener);
-        }
-        if (eagerStackTrace) {
-            listener = new EagerStackTraceDecorator(listener);
-        }
-        if (gcAfterTest) {
-            listener = new GCAfterTestDecorator(listener);
-        }
-        junitCore.addListener(TruffleTextListener.createRunListener(listener));
-        Request request;
-        if (methodName == null) {
-            request = Request.classes(classes.toArray(new Class[0]));
-            if (failFast) {
-                Runner runner = request.getRunner();
-                if (runner instanceof ParentRunner) {
-                    ParentRunner<?> parentRunner = (ParentRunner<?>) runner;
-                    parentRunner.setScheduler(new RunnerScheduler() {
-                        public void schedule(Runnable childStatement) {
-                            if (textListener.getLastFailure() == null) {
-                                childStatement.run();
-                            }
-                        }
-
-                        public void finished() {
-                        }
-                    });
-                } else {
-                    system.out().println("Unexpected Runner subclass " + runner.getClass().getName() + " - fail fast not supported");
-                }
-            }
-        } else {
-            if (failFast) {
-                system.out().println("Single method selected - fail fast not supported");
-            }
-            request = Request.method(classes.get(0), methodName);
-        }
-        Result result = junitCore.run(request);
-        for (Failure each : missingClasses) {
-            result.getFailures().add(each);
-        }
-        System.exit(result.wasSuccessful() ? 0 : 1);
-    }
-
-    /**
-     * Gets the command line for the current process.
-     *
-     * @return the command line arguments for the current process or {@code null} if they are not
-     *         available
-     */
-    public static List<String> getProcessCommandLine() {
-        String processArgsFile = System.getenv().get("MX_SUBPROCESS_COMMAND_FILE");
-        if (processArgsFile != null) {
-            try {
-                return Files.readAllLines(new File(processArgsFile).toPath(), Charset.forName("UTF-8"));
-            } catch (IOException e) {
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Expand any arguments starting with @ and return the resulting argument array.
-     *
-     * @param args
-     * @return the expanded argument array
-     */
-    private static String[] expandArgs(String[] args) {
-        List<String> result = null;
-        for (int i = 0; i < args.length; i++) {
-            String arg = args[i];
-            if (arg.length() > 0 && arg.charAt(0) == '@') {
-                if (result == null) {
-                    result = new ArrayList<>();
-                    for (int j = 0; j < i; j++) {
-                        result.add(args[j]);
-                    }
-                    expandArg(arg.substring(1), result);
-                }
-            } else if (result != null) {
-                result.add(arg);
-            }
-        }
-        return result != null ? result.toArray(new String[0]) : args;
-    }
-
-    /**
-     * Add each line from {@code filename} to the list {@code args}.
-     *
-     * @param filename
-     * @param args
-     */
-    private static void expandArg(String filename, List<String> args) {
-        BufferedReader br = null;
-        try {
-            br = new BufferedReader(new FileReader(filename));
-
-            String buf;
-            while ((buf = br.readLine()) != null) {
-                args.add(buf);
-            }
-            br.close();
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
-            System.exit(2);
-        } finally {
-            try {
-                if (br != null) {
-                    br.close();
-                }
-            } catch (IOException ioe) {
-                ioe.printStackTrace();
-                System.exit(3);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import java.io.*;
-
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.notification.*;
-
-interface TruffleJUnitRunListener {
-
-    /**
-     * Called before any tests have been run.
-     *
-     * @param description describes the tests to be run
-     */
-    void testRunStarted(Description description);
-
-    /**
-     * Called when all tests have finished.
-     *
-     * @param result the summary of the test run, including all the tests that failed
-     */
-    void testRunFinished(Result result);
-
-    /**
-     * Called when a test class is about to be started.
-     *
-     * @param clazz the test class
-     */
-    void testClassStarted(Class<?> clazz);
-
-    /**
-     * Called when all tests of a test class have finished.
-     *
-     * @param clazz the test class
-     */
-    void testClassFinished(Class<?> clazz);
-
-    /**
-     * Called when an atomic test is about to be started. This is also called for ignored tests.
-     *
-     * @param description the description of the test that is about to be run (generally a class and
-     *            method name)
-     */
-    void testStarted(Description description);
-
-    /**
-     * Called when an atomic test has finished, whether the test succeeds, fails or is ignored.
-     *
-     * @param description the description of the test that just ran
-     */
-    void testFinished(Description description);
-
-    /**
-     * Called when an atomic test fails.
-     *
-     * @param failure describes the test that failed and the exception that was thrown
-     */
-    void testFailed(Failure failure);
-
-    /**
-     * Called when a test will not be run, generally because a test method is annotated with
-     * {@link org.junit.Ignore}.
-     *
-     * @param description describes the test that will not be run
-     */
-    void testIgnored(Description description);
-
-    /**
-     * Called when an atomic test succeeds.
-     *
-     * @param description describes the test that will not be run
-     */
-    void testSucceeded(Description description);
-
-    /**
-     * Called when an atomic test flags that it assumes a condition that is false.
-     *
-     * @param failure describes the test that failed and the {@link AssumptionViolatedException}
-     *            that was thrown
-     */
-    void testAssumptionFailure(Failure failure);
-
-    /**
-     * Called after {@link #testClassFinished(Class)}.
-     */
-    void testClassFinishedDelimiter();
-
-    /**
-     * Called after {@link #testClassStarted(Class)}.
-     */
-    void testClassStartedDelimiter();
-
-    /**
-     * Called after {@link #testStarted(Description)}.
-     */
-    void testStartedDelimiter();
-
-    /**
-     * Called after {@link #testFailed(Failure)}.
-     */
-    void testFinishedDelimiter();
-
-    PrintStream getWriter();
-
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListenerDecorator.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import java.io.*;
-
-import org.junit.runner.*;
-import org.junit.runner.notification.*;
-
-class TruffleJUnitRunListenerDecorator implements TruffleJUnitRunListener {
-
-    private final TruffleJUnitRunListener l;
-
-    public TruffleJUnitRunListenerDecorator(TruffleJUnitRunListener l) {
-        this.l = l;
-    }
-
-    @Override
-    public void testRunStarted(Description description) {
-        l.testRunStarted(description);
-    }
-
-    @Override
-    public void testRunFinished(Result result) {
-        l.testRunFinished(result);
-    }
-
-    @Override
-    public void testAssumptionFailure(Failure failure) {
-        l.testAssumptionFailure(failure);
-    }
-
-    @Override
-    public void testIgnored(Description description) {
-        l.testIgnored(description);
-    }
-
-    @Override
-    public void testClassStarted(Class<?> clazz) {
-        l.testClassStarted(clazz);
-    }
-
-    @Override
-    public void testClassFinished(Class<?> clazz) {
-        l.testClassFinished(clazz);
-    }
-
-    @Override
-    public void testStarted(Description description) {
-        l.testStarted(description);
-    }
-
-    @Override
-    public void testFinished(Description description) {
-        l.testFinished(description);
-    }
-
-    @Override
-    public void testFailed(Failure failure) {
-        l.testFailed(failure);
-    }
-
-    @Override
-    public void testSucceeded(Description description) {
-        l.testSucceeded(description);
-    }
-
-    @Override
-    public PrintStream getWriter() {
-        return l.getWriter();
-    }
-
-    public void testClassFinishedDelimiter() {
-        l.testClassFinishedDelimiter();
-    }
-
-    public void testClassStartedDelimiter() {
-        l.testClassStartedDelimiter();
-    }
-
-    public void testStartedDelimiter() {
-        l.testStartedDelimiter();
-    }
-
-    public void testFinishedDelimiter() {
-        l.testFinishedDelimiter();
-    }
-
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import com.oracle.truffle.api.vm.TruffleVM;
-import java.io.IOException;
-import java.util.Random;
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-/**
- * A collection of tests that can certify language implementation to be compliant with most recent
- * requirements of the Truffle infrastructure and tooling. Subclass, implement abstract methods and
- * include in your test suite.
- */
-public abstract class TruffleTCK {
-    private TruffleVM tckVM;
-
-    protected TruffleTCK() {
-    }
-
-    /**
-     * This methods is called before first test is executed. It's purpose is to set a TruffleVM with
-     * your language up, so it is ready for testing.
-     * {@link TruffleVM#eval(java.lang.String, java.lang.String) Execute} any scripts you need, and
-     * prepare global symbols with proper names. The symbols will then be looked up by the
-     * infrastructure (using the names provided by you from methods like {@link #plusInt()}) and
-     * used for internal testing.
-     *
-     * @return initialized Truffle virtual machine
-     * @throws java.lang.Exception thrown when the VM preparation fails
-     */
-    protected abstract TruffleVM prepareVM() throws Exception;
-
-    /**
-     * Mimetype associated with your language. The mimetype will be passed to
-     * {@link TruffleVM#eval(java.lang.String, java.lang.String)} method of the {@link #prepareVM()
-     * created TruffleVM}.
-     *
-     * @return mime type of the tested language
-     */
-    protected abstract String mimeType();
-
-    /**
-     * Name of function which will return value 42 as a number. The return value of the method
-     * should be instance of {@link Number} and its {@link Number#intValue()} should return
-     * <code>42</code>.
-     *
-     * @return name of globally exported symbol
-     */
-    protected abstract String fourtyTwo();
-
-    /**
-     * Name of a function that returns <code>null</code>. Truffle languages are encouraged to have
-     * their own type representing <code>null</code>, but when such value is returned from
-     * {@link TruffleVM#eval}, it needs to be converted to real Java <code>null</code> by sending a
-     * foreign access <em>isNull</em> message. There is a test to verify it is really true.
-     *
-     * @return name of globally exported symbol
-     */
-    protected abstract String returnsNull();
-
-    /**
-     * Name of function to add two integer values together. The symbol will be invoked with two
-     * parameters of type {@link Integer} and expects result of type {@link Number} which's
-     * {@link Number#intValue()} is equivalent of <code>param1 + param2</code>.
-     *
-     * @return name of globally exported symbol
-     */
-    protected abstract String plusInt();
-
-    /**
-     * Return a code snippet that is invalid in your language. Its
-     * {@link TruffleVM#eval(java.lang.String, java.lang.String) evaluation} should fail and yield
-     * an exception.
-     *
-     * @return code snippet invalid in the tested language
-     */
-    protected abstract String invalidCode();
-
-    private TruffleVM vm() throws Exception {
-        if (tckVM == null) {
-            tckVM = prepareVM();
-        }
-        return tckVM;
-    }
-
-    //
-    // The tests
-    //
-
-    @Test
-    public void testFortyTwo() throws Exception {
-        TruffleVM.Symbol fourtyTwo = findGlobalSymbol(fourtyTwo());
-
-        Object res = fourtyTwo.invoke(null);
-
-        assert res instanceof Number : "should yield a number, but was: " + res;
-
-        Number n = (Number) res;
-
-        assert 42 == n.intValue() : "The value is 42 =  " + n.intValue();
-    }
-
-    @Test
-    public void testNull() throws Exception {
-        if (getClass() == TruffleTCK.class) {
-            return;
-        }
-        TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull());
-
-        Object res = retNull.invoke(null);
-
-        assertNull("Should yield real Java null", res);
-    }
-
-    @Test
-    public void testPlusWithInts() throws Exception {
-        Random r = new Random();
-        int a = r.nextInt(100);
-        int b = r.nextInt(100);
-
-        TruffleVM.Symbol plus = findGlobalSymbol(plusInt());
-
-        Object res = plus.invoke(null, a, b);
-
-        assert res instanceof Number : "+ on two ints should yield a number, but was: " + res;
-
-        Number n = (Number) res;
-
-        assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") =  " + n.intValue();
-    }
-
-    @Test(expected = IOException.class)
-    public void testInvalidTestMethod() throws Exception {
-        String mime = mimeType();
-        String code = invalidCode();
-        Object ret = vm().eval(mime, code);
-        fail("Should yield IOException, but returned " + ret);
-    }
-
-    private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception {
-        TruffleVM.Symbol s = vm().findGlobalSymbol(name);
-        assert s != null : "Symbol " + name + " is not found!";
-        return s;
-    }
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTextListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import java.io.*;
-
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.notification.*;
-
-class TruffleTextListener implements TruffleJUnitRunListener {
-
-    private final PrintStream fWriter;
-    protected Failure lastFailure;
-
-    public TruffleTextListener(JUnitSystem system) {
-        this(system.out());
-    }
-
-    public TruffleTextListener(PrintStream writer) {
-        fWriter = writer;
-    }
-
-    @Override
-    public PrintStream getWriter() {
-        return fWriter;
-    }
-
-    public Failure getLastFailure() {
-        return lastFailure;
-    }
-
-    @Override
-    public void testRunStarted(Description description) {
-    }
-
-    @Override
-    public void testRunFinished(Result result) {
-    }
-
-    @Override
-    public void testAssumptionFailure(Failure failure) {
-    }
-
-    @Override
-    public void testClassStarted(Class<?> clazz) {
-    }
-
-    @Override
-    public void testClassFinished(Class<?> clazz) {
-    }
-
-    @Override
-    public void testStarted(Description description) {
-        getWriter().print('.');
-    }
-
-    @Override
-    public void testFinished(Description description) {
-    }
-
-    @Override
-    public void testFailed(Failure failure) {
-        getWriter().print('E');
-        lastFailure = failure;
-    }
-
-    @Override
-    public void testSucceeded(Description description) {
-    }
-
-    @Override
-    public void testIgnored(Description description) {
-        getWriter().print('I');
-    }
-
-    @Override
-    public void testClassFinishedDelimiter() {
-    }
-
-    @Override
-    public void testClassStartedDelimiter() {
-    }
-
-    @Override
-    public void testStartedDelimiter() {
-    }
-
-    @Override
-    public void testFinishedDelimiter() {
-    }
-
-    public static RunListener createRunListener(final TruffleJUnitRunListener l) {
-        return new TextListener(l.getWriter()) {
-            private Class<?> lastClass;
-            private boolean failed;
-
-            @Override
-            public final void testStarted(Description description) {
-                Class<?> currentClass = description.getTestClass();
-                if (currentClass != lastClass) {
-                    if (lastClass != null) {
-                        l.testClassFinished(lastClass);
-                        l.testClassFinishedDelimiter();
-                    }
-                    lastClass = currentClass;
-                    l.testClassStarted(currentClass);
-                    l.testClassStartedDelimiter();
-                }
-                failed = false;
-                l.testStarted(description);
-                l.testStartedDelimiter();
-            }
-
-            @Override
-            public final void testFailure(Failure failure) {
-                failed = true;
-                l.testFailed(failure);
-            }
-
-            @Override
-            public final void testFinished(Description description) {
-                // we have to do this because there is no callback for successful tests
-                if (!failed) {
-                    l.testSucceeded(description);
-                }
-                l.testFinished(description);
-                l.testFinishedDelimiter();
-            }
-
-            @Override
-            public void testIgnored(Description description) {
-                l.testStarted(description);
-                l.testStartedDelimiter();
-                l.testIgnored(description);
-                l.testFinished(description);
-                l.testFinishedDelimiter();
-            }
-
-            @Override
-            public void testRunStarted(Description description) {
-                l.testRunStarted(description);
-            }
-
-            @Override
-            public void testRunFinished(Result result) {
-                if (lastClass != null) {
-                    l.testClassFinished(lastClass);
-                }
-                l.testRunFinished(result);
-                super.testRunFinished(result);
-            }
-
-            @Override
-            public void testAssumptionFailure(Failure failure) {
-                l.testAssumptionFailure(failure);
-            }
-
-        };
-    }
-
-}
--- a/graal/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleVerboseTextListener.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tck;
-
-import java.io.*;
-
-import org.junit.internal.*;
-import org.junit.runner.*;
-import org.junit.runner.notification.*;
-
-class TruffleVerboseTextListener extends TruffleTextListener {
-
-    public TruffleVerboseTextListener(JUnitSystem system) {
-        this(system.out());
-    }
-
-    public TruffleVerboseTextListener(PrintStream writer) {
-        super(writer);
-    }
-
-    @Override
-    public void testClassStarted(Class<?> clazz) {
-        getWriter().print(clazz.getName() + " started");
-    }
-
-    @Override
-    public void testClassFinished(Class<?> clazz) {
-        getWriter().print(clazz.getName() + " finished");
-    }
-
-    @Override
-    public void testStarted(Description description) {
-        getWriter().print("  " + description.getMethodName() + ": ");
-    }
-
-    @Override
-    public void testIgnored(Description description) {
-        getWriter().print("Ignored");
-    }
-
-    @Override
-    public void testSucceeded(Description description) {
-        getWriter().print("Passed");
-    }
-
-    @Override
-    public void testAssumptionFailure(Failure failure) {
-        getWriter().printf("(%s) ", failure.getMessage());
-    }
-
-    @Override
-    public void testFailed(Failure failure) {
-        getWriter().print("FAILED");
-        lastFailure = failure;
-    }
-
-    @Override
-    public void testClassFinishedDelimiter() {
-        getWriter().println();
-    }
-
-    @Override
-    public void testClassStartedDelimiter() {
-        getWriter().println();
-    }
-
-    @Override
-    public void testFinishedDelimiter() {
-        getWriter().println();
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/Breakpoint.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.source.*;
-
-public abstract class Breakpoint {
-
-    /**
-     * A general model of the states occupied by a breakpoint during its lifetime.
-     */
-    public enum BreakpointState {
-
-        /**
-         * Not attached, enabled.
-         * <p>
-         * Created for a source location but not yet attached: perhaps just created and the source
-         * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
-         * probed so a breakpoint cannot be attached. Can be either enabled or disabled.
-         */
-        ENABLED_UNRESOLVED("Enabled/Unresolved"),
-
-        /**
-         * Not attached, disabled.
-         * <p>
-         * Created for a source location but not yet attached: perhaps just created and the source
-         * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
-         * probed so a breakpoint cannot be attached.
-         */
-        DISABLED_UNRESOLVED("Disabled/Unresolved"),
-
-        /**
-         * Attached, instrument enabled.
-         * <p>
-         * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
-         * at a specific node in the AST, and the breakpoint is enabled.
-         */
-        ENABLED("Enabled"),
-
-        /**
-         * Attached, instrument disabled.
-         * <p>
-         * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
-         * at a specific node in the AST, and the breakpoint is disabled.
-         */
-        DISABLED("Disabled"),
-
-        /**
-         * Not attached, instrument is permanently disabled.
-         */
-        DISPOSED("Disposed");
-
-        private final String name;
-
-        BreakpointState(String name) {
-            this.name = name;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-
-    }
-
-    private static int nextBreakpointId = 0;
-
-    private final int id;
-    private final int groupId;
-    private final boolean isOneShot;
-
-    private int ignoreCount;
-
-    private int hitCount = 0;
-
-    private BreakpointState state;
-
-    Breakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
-        this.state = state;
-        this.id = nextBreakpointId++;
-        this.groupId = groupId;
-        this.isOneShot = isOneShot;
-        this.ignoreCount = ignoreCount;
-    }
-
-    /**
-     * Unique ID.
-     */
-    public final int getId() {
-        return id;
-    }
-
-    /**
-     * Group ID, set when created.
-     */
-    public final int getGroupId() {
-        return groupId;
-    }
-
-    /**
-     * Enables or disables this breakpoint's AST instrumentation. The breakpoint is enabled by
-     * default.
-     *
-     * @param enabled <code>true</code> to activate the instrumentation, <code>false</code> to
-     *            deactivate the instrumentation so that it has no effect.
-     */
-    public abstract void setEnabled(boolean enabled);
-
-    /**
-     * Is this breakpoint active?
-     */
-    public abstract boolean isEnabled();
-
-    /**
-     * Sets the condition on this breakpoint, {@code null} to make it unconditional.
-     *
-     * @param expr if non{@code -null}, a boolean expression, expressed in the guest language, to be
-     *            evaluated in the lexical context at the breakpoint location.
-     * @throws DebugException if condition is invalid
-     * @throws UnsupportedOperationException if the breakpoint does not support conditions
-     */
-    public abstract void setCondition(String expr) throws DebugException;
-
-    /**
-     * Gets the string, expressed in the Guest Language, that defines the current condition on this
-     * breakpoint; {@code null} if this breakpoint is currently unconditional.
-     */
-    public String getCondition() {
-        return null;
-    }
-
-    /**
-     * Does this breakpoint remove itself after first activation?
-     */
-    public final boolean isOneShot() {
-        return isOneShot;
-    }
-
-    /**
-     * Gets the number of hits left to be ignored before halting.
-     */
-    public final int getIgnoreCount() {
-        return ignoreCount;
-    }
-
-    /**
-     * Change the threshold for when this breakpoint should start causing a break. When both an
-     * ignore count and a {@linkplain #setCondition(String) condition} are specified, the condition
-     * is evaluated first: if {@code false} it is not considered to be a hit. In other words, the
-     * ignore count is for successful conditions only.
-     */
-    public final void setIgnoreCount(int ignoreCount) {
-        this.ignoreCount = ignoreCount;
-    }
-
-    /**
-     * Number of times this breakpoint has reached, with one exception; if the breakpoint has a
-     * condition that evaluates to {@code false}, it does not count as a hit.
-     */
-    public final int getHitCount() {
-        return hitCount;
-    }
-
-    /**
-     * Disables this breakpoint and removes any associated instrumentation; it becomes permanently
-     * inert.
-     */
-    public abstract void dispose();
-
-    /**
-     * Gets a human-sensible description of this breakpoint's location in a {@link Source}.
-     */
-    public abstract String getLocationDescription();
-
-    public final BreakpointState getState() {
-        return state;
-    }
-
-    final void assertState(BreakpointState s) {
-        assert state == s;
-    }
-
-    final void setState(BreakpointState state) {
-        this.state = state;
-    }
-
-    /**
-     * Assumes that all conditions for causing the break have been satisfied, so increments the
-     * <em>hit count</em>. Then checks if the <em>ignore count</em> has been exceeded, and if so
-     * returns {@code true}. If not, it still counts as a <em>hit</em> but should be ignored.
-     *
-     * @return whether to proceed
-     */
-    final boolean incrHitCountCheckIgnore() {
-        return ++hitCount > ignoreCount;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
-        sb.append(" state=");
-        sb.append(getState() == null ? "<none>" : getState().getName());
-        if (isOneShot()) {
-            sb.append(", " + "One-Shot");
-        }
-        if (getCondition() != null) {
-            sb.append(", condition=\"" + getCondition() + "\"");
-        }
-        return sb.toString();
-    }
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-
-/**
- * A client of the debugger where certain events should be posted.
- *
- * @see DebugEngine
- */
-public interface DebugClient {
-
-    /**
-     * Notifies client that program execution has been halted at some location; execution will
-     * resume when this method returns.
-     *
-     * @param astNode AST node that is just about to be executed
-     * @param mFrame frame that will be passed to the node when executed
-     * @param warnings any warnings generated since the most recent halt.
-     */
-    void haltedAt(Node astNode, MaterializedFrame mFrame, List<String> warnings);
-
-    /**
-     * Gets information and services for the language being debugged.
-     */
-    Language getLanguage();
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,851 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-import com.oracle.truffle.tools.debug.engine.DebugExecutionSupport.DebugExecutionListener;
-
-/**
- * Language-agnostic engine for running Truffle languages under debugging control.
- */
-public final class DebugEngine {
-
-    private static final boolean TRACE = false;
-    private static final String TRACE_PREFIX = "DEBUG ENGINE: ";
-
-    private static final PrintStream OUT = System.out;
-
-    private static final SyntaxTag STEPPING_TAG = StandardSyntaxTag.STATEMENT;
-    private static final SyntaxTag CALL_TAG = StandardSyntaxTag.CALL;
-
-    private static void trace(String format, Object... args) {
-        if (TRACE) {
-            OUT.println(TRACE_PREFIX + String.format(format, args));
-        }
-    }
-
-    interface BreakpointCallback {
-
-        /**
-         * Passes control to the debugger with execution suspended.
-         */
-        void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason);
-    }
-
-    interface WarningLog {
-
-        /**
-         * Logs a warning that is kept until the start of the next execution.
-         */
-        void addWarning(String warning);
-    }
-
-    private final Language language;
-
-    /**
-     * The client of this engine.
-     */
-    private final DebugClient debugClient;
-
-    private final DebugExecutionSupport executionSupport;
-
-    /**
-     * Implementation of line-oriented breakpoints.
-     */
-    private final LineBreakpointFactory lineBreaks;
-
-    /**
-     * Implementation of tag-oriented breakpoints.
-     */
-    private final TagBreakpointFactory tagBreaks;
-
-    /**
-     * Head of the stack of executions.
-     */
-    private DebugExecutionContext debugContext;
-
-    /**
-     * @param debugClient
-     * @param language
-     */
-    private DebugEngine(DebugClient debugClient, Language language) {
-        this.debugClient = debugClient;
-        this.language = language;
-        this.executionSupport = new DebugExecutionSupport(language.getShortName(), language.getDebugSupport());
-
-        Source.setFileCaching(true);
-
-        // Initialize execution context stack
-        debugContext = new DebugExecutionContext(null, null);
-        prepareContinue();
-        debugContext.contextTrace("START EXEC DEFAULT");
-
-        executionSupport.addExecutionListener(new DebugExecutionListener() {
-
-            public void executionStarted(Source source, boolean stepInto) {
-                // Push a new execution context onto stack
-                DebugEngine.this.debugContext = new DebugExecutionContext(source, DebugEngine.this.debugContext);
-                if (stepInto) {
-                    DebugEngine.this.prepareStepInto(1);
-                } else {
-                    DebugEngine.this.prepareContinue();
-                }
-                DebugEngine.this.debugContext.contextTrace("START EXEC ");
-            }
-
-            public void executionEnded() {
-                DebugEngine.this.lineBreaks.disposeOneShots();
-                DebugEngine.this.tagBreaks.disposeOneShots();
-                DebugEngine.this.debugContext.clearStrategy();
-                DebugEngine.this.debugContext.contextTrace("END EXEC ");
-                // Pop the stack of execution contexts.
-                DebugEngine.this.debugContext = DebugEngine.this.debugContext.predecessor;
-            }
-        });
-
-        final BreakpointCallback breakpointCallback = new BreakpointCallback() {
-
-            @TruffleBoundary
-            public void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason) {
-                debugContext.halt(astNode, mFrame, true, haltReason);
-            }
-        };
-
-        final WarningLog warningLog = new WarningLog() {
-
-            public void addWarning(String warning) {
-                assert debugContext != null;
-                debugContext.logWarning(warning);
-            }
-        };
-
-        this.lineBreaks = new LineBreakpointFactory(executionSupport, breakpointCallback, warningLog);
-
-        this.tagBreaks = new TagBreakpointFactory(executionSupport, breakpointCallback, warningLog);
-    }
-
-    public static DebugEngine create(DebugClient debugClient, Language language) {
-        return new DebugEngine(debugClient, language);
-    }
-
-    /**
-     * Runs a script. If "StepInto" is requested, halts at the first location tagged as a
-     * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}.
-     *
-     * @throws DebugException if an unexpected failure occurs
-     */
-    public void run(Source source, boolean stepInto) throws DebugException {
-        executionSupport.run(source, stepInto);
-    }
-
-    /**
-     * Sets a breakpoint to halt at a source line.
-     *
-     * @param groupId
-     * @param ignoreCount number of hits to ignore before halting
-     * @param lineLocation where to set the breakpoint (source, line number)
-     * @param oneShot breakpoint disposes itself after fist hit, if {@code true}
-     * @return a new breakpoint, initially enabled
-     * @throws DebugException if the breakpoint can not be set.
-     */
-    @TruffleBoundary
-    public LineBreakpoint setLineBreakpoint(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) throws DebugException {
-        return lineBreaks.create(groupId, ignoreCount, lineLocation, oneShot);
-    }
-
-    /**
-     * Sets a breakpoint to halt at any node holding a specified {@link SyntaxTag}.
-     *
-     * @param groupId
-     * @param ignoreCount number of hits to ignore before halting
-     * @param oneShot if {@code true} breakpoint removes it self after a hit
-     * @return a new breakpoint, initially enabled
-     * @throws DebugException if the breakpoint already set
-     */
-    @TruffleBoundary
-    public Breakpoint setTagBreakpoint(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) throws DebugException {
-        return tagBreaks.create(groupId, ignoreCount, tag, oneShot);
-    }
-
-    /**
-     * Finds a breakpoint created by this engine, but not yet disposed, by id.
-     */
-    @TruffleBoundary
-    public Breakpoint findBreakpoint(long id) {
-        final Breakpoint breakpoint = lineBreaks.find(id);
-        return breakpoint == null ? tagBreaks.find(id) : breakpoint;
-    }
-
-    /**
-     * Gets all existing breakpoints, whatever their status, in natural sorted order. Modification
-     * save.
-     */
-    @TruffleBoundary
-    public Collection<Breakpoint> getBreakpoints() {
-        final Collection<Breakpoint> result = new ArrayList<>();
-        result.addAll(lineBreaks.getAll());
-        result.addAll(tagBreaks.getAll());
-        return result;
-    }
-
-    /**
-     * Prepare to execute in Continue mode when guest language program execution resumes. In this
-     * mode:
-     * <ul>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a node to which an enabled breakpoint is attached,
-     * <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * </ul>
-     */
-    @TruffleBoundary
-    public void prepareContinue() {
-        debugContext.setStrategy(new Continue());
-    }
-
-    /**
-     * Prepare to execute in StepInto mode when guest language program execution resumes. In this
-     * mode:
-     * <ul>
-     * <li>User breakpoints are disabled.</li>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a node with the tag {@linkplain StandardSyntaxTag#STATEMENT
-     * STATMENT}, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * <li>
-     * StepInto mode persists only through one resumption (i.e. {@code stepIntoCount} steps), and
-     * reverts by default to Continue mode.</li>
-     * </ul>
-     *
-     * @param stepCount the number of times to perform StepInto before halting
-     * @throws IllegalArgumentException if the specified number is {@code <= 0}
-     */
-    @TruffleBoundary
-    public void prepareStepInto(int stepCount) {
-        if (stepCount <= 0) {
-            throw new IllegalArgumentException();
-        }
-        debugContext.setStrategy(new StepInto(stepCount));
-    }
-
-    /**
-     * Prepare to execute in StepOut mode when guest language program execution resumes. In this
-     * mode:
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at the nearest enclosing call site on the stack, <strong>or</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * <li>StepOut mode persists only through one resumption, and reverts by default to Continue
-     * mode.</li>
-     * </ul>
-     */
-    @TruffleBoundary
-    public void prepareStepOut() {
-        debugContext.setStrategy(new StepOut());
-    }
-
-    /**
-     * Prepare to execute in StepOver mode when guest language program execution resumes. In this
-     * mode:
-     * <ul>
-     * <li>Execution will continue until either:
-     * <ol>
-     * <li>execution arrives at a node with the tag {@linkplain StandardSyntaxTag#STATEMENT
-     * STATEMENT} when not nested in one or more function/method calls, <strong>or:</strong></li>
-     * <li>execution arrives at a node to which a breakpoint is attached and when nested in one or
-     * more function/method calls, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * <li>StepOver mode persists only through one resumption (i.e. {@code stepOverCount} steps),
-     * and reverts by default to Continue mode.</li>
-     * </ul>
-     *
-     * @param stepCount the number of times to perform StepInto before halting
-     * @throws IllegalArgumentException if the specified number is {@code <= 0}
-     */
-    @TruffleBoundary
-    public void prepareStepOver(int stepCount) {
-        if (stepCount <= 0) {
-            throw new IllegalArgumentException();
-        }
-        debugContext.setStrategy(new StepOver(stepCount));
-    }
-
-    /**
-     * Gets the stack frames from the (topmost) halted Truffle execution; {@code null} null if no
-     * execution.
-     */
-    @TruffleBoundary
-    public List<FrameDebugDescription> getStack() {
-        return debugContext == null ? null : debugContext.getFrames();
-    }
-
-    /**
-     * Evaluates code in a halted execution context, at top-level if <code>mFrame==null</code>.
-     *
-     * @throws DebugException
-     */
-    public Object eval(Source source, Node node, MaterializedFrame mFrame) throws DebugException {
-        return executionSupport.evalInContext(source, node, mFrame);
-    }
-
-    /**
-     * A mode of user navigation from a current code location to another, e.g "step in" vs.
-     * "step over".
-     */
-    private abstract class StepStrategy {
-
-        private DebugExecutionContext context;
-        protected final String strategyName;
-
-        protected StepStrategy() {
-            this.strategyName = getClass().getSimpleName();
-        }
-
-        final String getName() {
-            return strategyName;
-        }
-
-        /**
-         * Reconfigure the debugger so that when execution continues the program will halt at the
-         * location specified by this strategy.
-         */
-        final void enable(DebugExecutionContext c, int stackDepth) {
-            this.context = c;
-            setStrategy(stackDepth);
-        }
-
-        /**
-         * Return the debugger to the default navigation mode.
-         */
-        final void disable() {
-            unsetStrategy();
-        }
-
-        @TruffleBoundary
-        final void halt(Node astNode, MaterializedFrame mFrame, boolean before) {
-            context.halt(astNode, mFrame, before, this.getClass().getSimpleName());
-        }
-
-        @TruffleBoundary
-        final void replaceStrategy(StepStrategy newStrategy) {
-            context.setStrategy(newStrategy);
-        }
-
-        @TruffleBoundary
-        protected final void strategyTrace(String action, String format, Object... args) {
-            if (TRACE) {
-                context.contextTrace("%s (%s) %s", action, strategyName, String.format(format, args));
-            }
-        }
-
-        @TruffleBoundary
-        protected final void suspendUserBreakpoints() {
-            lineBreaks.setActive(false);
-            tagBreaks.setActive(false);
-        }
-
-        @SuppressWarnings("unused")
-        protected final void restoreUserBreakpoints() {
-            lineBreaks.setActive(true);
-            tagBreaks.setActive(true);
-        }
-
-        /**
-         * Reconfigure the debugger so that when execution continues, it will do so using this mode
-         * of navigation.
-         */
-        protected abstract void setStrategy(int stackDepth);
-
-        /**
-         * Return to the debugger to the default mode of navigation.
-         */
-        protected abstract void unsetStrategy();
-    }
-
-    /**
-     * Strategy: the null stepping strategy.
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution continues until either:
-     * <ol>
-     * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * </ul>
-     */
-    private final class Continue extends StepStrategy {
-
-        @Override
-        protected void setStrategy(int stackDepth) {
-        }
-
-        @Override
-        protected void unsetStrategy() {
-        }
-    }
-
-    /**
-     * Strategy: per-statement stepping.
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution continues until either:
-     * <ol>
-     * <li>execution <em>arrives</em> at a STATEMENT node, <strong>or:</strong></li>
-     * <li>execution <em>returns</em> to a CALL node and the call stack is smaller then when
-     * execution started, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * </ul>
-     *
-     * @see DebugEngine#prepareStepInto(int)
-     */
-    private final class StepInto extends StepStrategy {
-        private int unfinishedStepCount;
-
-        StepInto(int stepCount) {
-            super();
-            this.unfinishedStepCount = stepCount;
-        }
-
-        @Override
-        protected void setStrategy(final int stackDepth) {
-            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
-
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    // HALT: just before statement
-                    --unfinishedStepCount;
-                    strategyTrace("TRAP BEFORE", "unfinished steps=%d", unfinishedStepCount);
-                    // Should run in fast path
-                    if (unfinishedStepCount <= 0) {
-                        halt(node, mFrame, true);
-                    }
-                    strategyTrace("RESUME BEFORE", "");
-                }
-            });
-            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
-
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    --unfinishedStepCount;
-                    strategyTrace(null, "TRAP AFTER unfinished steps=%d", unfinishedStepCount);
-                    if (currentStackDepth() < stackDepth) {
-                        // HALT: just "stepped out"
-                        if (unfinishedStepCount <= 0) {
-                            halt(node, mFrame, false);
-                        }
-                    }
-                    strategyTrace("RESUME AFTER", "");
-                }
-            });
-        }
-
-        @Override
-        protected void unsetStrategy() {
-            Probe.setBeforeTagTrap(null);
-            Probe.setAfterTagTrap(null);
-        }
-    }
-
-    /**
-     * Strategy: execution to nearest enclosing call site.
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution continues until either:
-     * <ol>
-     * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
-     * <li>execution <em>returns</em> to a CALL node and the call stack is smaller than when
-     * execution started, <strong>or:</strong></li>
-     * <li>execution completes.</li>
-     * </ol>
-     * </ul>
-     *
-     * @see DebugEngine#prepareStepOut()
-     */
-    private final class StepOut extends StepStrategy {
-
-        @Override
-        protected void setStrategy(final int stackDepth) {
-            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
-
-                @TruffleBoundary
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    // HALT:
-                    final int currentStackDepth = currentStackDepth();
-                    strategyTrace("TRAP AFTER", "stackDepth: start=%d current=%d", stackDepth, currentStackDepth);
-                    if (currentStackDepth < stackDepth) {
-                        halt(node, mFrame, false);
-                    }
-                    strategyTrace("RESUME AFTER", "");
-                }
-            });
-        }
-
-        @Override
-        protected void unsetStrategy() {
-            Probe.setAfterTagTrap(null);
-        }
-    }
-
-    /**
-     * Strategy: per-statement stepping, so long as not nested in method calls (i.e. at original
-     * stack depth).
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution continues until either:
-     * <ol>
-     * <li>execution arrives at a STATEMENT node with stack depth no more than when started
-     * <strong>or:</strong></li>
-     * <li>the program completes.</li>
-     * </ol>
-     * </ul>
-     */
-    private final class StepOver extends StepStrategy {
-        private int unfinishedStepCount;
-
-        StepOver(int stepCount) {
-            this.unfinishedStepCount = stepCount;
-        }
-
-        @Override
-        protected void setStrategy(int stackDepth) {
-            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
-
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    final int currentStackDepth = currentStackDepth();
-                    if (currentStackDepth <= stackDepth) {
-                        // HALT: stack depth unchanged or smaller; treat like StepInto
-                        --unfinishedStepCount;
-                        if (TRACE) {
-                            strategyTrace("TRAP BEFORE", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
-                        }
-                        // Test should run in fast path
-                        if (unfinishedStepCount <= 0) {
-                            halt(node, mFrame, true);
-                        }
-                    } else {
-                        // CONTINUE: Stack depth increased; don't count as a step
-                        strategyTrace("STEP INTO", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
-                        // Stop treating like StepInto, start treating like StepOut
-                        replaceStrategy(new StepOverNested(unfinishedStepCount, stackDepth));
-                    }
-                    strategyTrace("RESUME BEFORE", "");
-                }
-            });
-
-            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
-
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    final int currentStackDepth = currentStackDepth();
-                    if (currentStackDepth < stackDepth) {
-                        // HALT: just "stepped out"
-                        --unfinishedStepCount;
-                        strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth: start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
-                        // Should run in fast path
-                        if (unfinishedStepCount <= 0) {
-                            halt(node, mFrame, false);
-                        }
-                        strategyTrace("RESUME AFTER", "");
-                    }
-                }
-            });
-        }
-
-        @Override
-        protected void unsetStrategy() {
-            Probe.setBeforeTagTrap(null);
-            Probe.setAfterTagTrap(null);
-        }
-    }
-
-    /**
-     * Strategy: per-statement stepping, not into method calls, in effect while at increased stack
-     * depth
-     * <ul>
-     * <li>User breakpoints are enabled.</li>
-     * <li>Execution continues until either:
-     * <ol>
-     * <li>execution arrives at a STATEMENT node with stack depth no more than when started
-     * <strong>or:</strong></li>
-     * <li>the program completes <strong>or:</strong></li>
-     * </ol>
-     * </ul>
-     */
-    private final class StepOverNested extends StepStrategy {
-        private int unfinishedStepCount;
-        private final int startStackDepth;
-
-        StepOverNested(int stepCount, int startStackDepth) {
-            this.unfinishedStepCount = stepCount;
-            this.startStackDepth = startStackDepth;
-        }
-
-        @Override
-        protected void setStrategy(int stackDepth) {
-            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
-
-                @Override
-                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
-                    final int currentStackDepth = currentStackDepth();
-                    if (currentStackDepth <= startStackDepth) {
-                        // At original step depth (or smaller) after being nested
-                        --unfinishedStepCount;
-                        strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
-                        if (unfinishedStepCount <= 0) {
-                            halt(node, mFrame, false);
-                        }
-                        // TODO (mlvdv) fixme for multiple steps
-                        strategyTrace("RESUME BEFORE", "");
-                    }
-                }
-            });
-        }
-
-        @Override
-        protected void unsetStrategy() {
-            Probe.setBeforeTagTrap(null);
-        }
-    }
-
-    /**
-     * Information and debugging state for a single Truffle execution (which make take place over
-     * one or more suspended executions). This holds interaction state, for example what is
-     * executing (e.g. some {@link Source}), what the execution mode is ("stepping" or
-     * "continuing"). When not running, this holds a cache of the Truffle stack for this particular
-     * execution, effectively hiding the Truffle stack for any currently suspended executions (down
-     * the stack).
-     */
-    private final class DebugExecutionContext {
-
-        // Previous halted context in stack
-        private final DebugExecutionContext predecessor;
-
-        // The current execution level; first is 0.
-        private final int level;  // Number of contexts suspended below
-        private final Source source;
-        private final int contextStackBase;  // Where the stack for this execution starts
-        private final List<String> warnings = new ArrayList<>();
-
-        private boolean running;
-
-        /**
-         * The stepping strategy currently configured in the debugger.
-         */
-        private StepStrategy strategy;
-
-        /**
-         * Where halted; null if running.
-         */
-        private Node haltedNode;
-
-        /**
-         * Where halted; null if running.
-         */
-        private MaterializedFrame haltedFrame;
-
-        /**
-         * Cached list of stack frames when halted; null if running.
-         */
-        private List<FrameDebugDescription> frames = new ArrayList<>();
-
-        private DebugExecutionContext(Source executionSource, DebugExecutionContext previousContext) {
-            this.source = executionSource;
-            this.predecessor = previousContext;
-            this.level = previousContext == null ? 0 : previousContext.level + 1;
-
-            // "Base" is the number of stack frames for all nested (halted) executions.
-            this.contextStackBase = currentStackDepth();
-            this.running = true;
-            contextTrace("NEW CONTEXT");
-        }
-
-        /**
-         * Sets up a strategy for the next resumption of execution.
-         *
-         * @param stepStrategy
-         */
-        void setStrategy(StepStrategy stepStrategy) {
-            if (this.strategy == null) {
-                this.strategy = stepStrategy;
-                this.strategy.enable(this, currentStackDepth());
-                if (TRACE) {
-                    contextTrace("SET MODE <none>-->" + stepStrategy.getName());
-                }
-            } else {
-                strategy.disable();
-                strategy = stepStrategy;
-                strategy.enable(this, currentStackDepth());
-                contextTrace("SWITCH MODE %s-->%s", strategy.getName(), stepStrategy.getName());
-            }
-        }
-
-        void clearStrategy() {
-            if (strategy != null) {
-                final StepStrategy oldStrategy = strategy;
-                strategy.disable();
-                strategy = null;
-                contextTrace("CLEAR MODE %s--><none>", oldStrategy.getName());
-            }
-        }
-
-        /**
-         * Handle a program halt, caused by a breakpoint, stepping strategy, or other cause.
-         *
-         * @param astNode the guest language node at which execution is halted
-         * @param mFrame the current execution frame where execution is halted
-         * @param before {@code true} if halted <em>before</em> the node, else <em>after</em>.
-         */
-        @TruffleBoundary
-        void halt(Node astNode, MaterializedFrame mFrame, boolean before, String haltReason) {
-            assert running;
-            assert frames.isEmpty();
-            assert haltedNode == null;
-            assert haltedFrame == null;
-
-            haltedNode = astNode;
-            haltedFrame = mFrame;
-            running = false;
-
-            clearStrategy();
-
-            // Clean up, just in cased the one-shot breakpoints got confused
-            lineBreaks.disposeOneShots();
-
-            // Map the Truffle stack for this execution, ignore nested executions
-            // The top (current) frame is not produced by the iterator.
-            frames.add(new FrameDebugDescription(0, haltedNode, Truffle.getRuntime().getCurrentFrame()));
-            final int contextStackDepth = currentStackDepth() - contextStackBase;
-            final int[] frameCount = {1};
-            Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<FrameInstance>() {
-                @Override
-                public FrameInstance visitFrame(FrameInstance frameInstance) {
-                    if (frameCount[0] < contextStackDepth) {
-                        frames.add(new FrameDebugDescription(frameCount[0], frameInstance.getCallNode(), frameInstance));
-                        frameCount[0] = frameCount[0] + 1;
-                        return null;
-                    }
-                    return frameInstance;
-                }
-            });
-
-            if (TRACE) {
-                final String reason = haltReason == null ? "" : haltReason + "";
-                final String where = before ? "BEFORE" : "AFTER";
-                contextTrace("HALT %s : (%s) stack base=%d", where, reason, contextStackBase);
-                contextTrace("CURRENT STACK:");
-                printStack(OUT);
-            }
-
-            final List<String> recentWarnings = new ArrayList<>(warnings);
-            warnings.clear();
-
-            try {
-                // Pass control to the debug client with current execution suspended
-                debugClient.haltedAt(astNode, mFrame, recentWarnings);
-                // Debug client finished normally, execution resumes
-                // Presume that the client has set a new strategy (or default to Continue)
-                running = true;
-            } catch (KillException e) {
-                contextTrace("KILL");
-                throw e;
-            } finally {
-                haltedNode = null;
-                haltedFrame = null;
-                frames.clear();
-            }
-
-        }
-
-        List<FrameDebugDescription> getFrames() {
-            return Collections.unmodifiableList(frames);
-        }
-
-        void logWarning(String warning) {
-            warnings.add(warning);
-        }
-
-        // For tracing
-        private void printStack(PrintStream stream) {
-            getFrames();
-            if (frames == null) {
-                stream.println("<empty stack>");
-            } else {
-                final Visualizer visualizer = language.getDebugSupport().getVisualizer();
-                for (FrameDebugDescription frameDesc : frames) {
-                    final StringBuilder sb = new StringBuilder("    frame " + Integer.toString(frameDesc.index()));
-                    sb.append(":at " + visualizer.displaySourceLocation(frameDesc.node()));
-                    sb.append(":in '" + visualizer.displayMethodName(frameDesc.node()) + "'");
-                    stream.println(sb.toString());
-                }
-            }
-        }
-
-        void contextTrace(String format, Object... args) {
-            if (TRACE) {
-                final String srcName = (source != null) ? source.getName() : "no source";
-                DebugEngine.trace("<%d> %s (%s)", level, String.format(format, args), srcName);
-            }
-        }
-    }
-
-    // TODO (mlvdv) wish there were fast-path access to stack depth
-    /**
-     * Depth of current Truffle stack, including nested executions. Includes the top/current frame,
-     * which the standard iterator does not count: {@code 0} if no executions.
-     */
-    @TruffleBoundary
-    private static int currentStackDepth() {
-        final int[] count = {0};
-        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
-            @Override
-            public Void visitFrame(FrameInstance frameInstance) {
-                count[0] = count[0] + 1;
-                return null;
-            }
-        });
-        return count[0] == 0 ? 0 : count[0] + 1;
-
-    }
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-/**
- * An unexpected failure in the operation of the {@link DebugEngine}.
- */
-public class DebugException extends Exception {
-
-    public DebugException(String string) {
-        super(string);
-    }
-
-    public DebugException(Exception ex) {
-        super(ex);
-    }
-
-    private static final long serialVersionUID = 3307454453821997224L;
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import java.util.*;
-
-import com.oracle.truffle.api.debug.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Access to language-specific support for debugging.
- */
-final class DebugExecutionSupport {
-
-    interface DebugExecutionListener {
-
-        /**
-         * Notifies that execution is about to start and requests initial execution mode.
-         */
-        void executionStarted(Source source, boolean stepInto);
-
-        /**
-         * Notification that the current execution has just ended.
-         */
-        void executionEnded();
-    }
-
-    private final String languageName;
-    private final DebugSupportProvider provider;
-    private final List<DebugExecutionListener> listeners = new ArrayList<>();
-
-    DebugExecutionSupport(String languageName, DebugSupportProvider provider) {
-        this.languageName = languageName;
-        this.provider = provider;
-    }
-
-    void addExecutionListener(DebugExecutionListener listener) {
-        assert listener != null;
-        listeners.add(listener);
-    }
-
-    String getLanguageName() {
-        return languageName;
-    }
-
-    Visualizer getVisualizer() {
-        return provider.getVisualizer();
-    }
-
-    /**
-     * Runs a script. If "StepInto" is specified, halts at the first location tagged as a
-     * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}.
-     */
-    void run(Source source, boolean stepInto) throws DebugException {
-        for (DebugExecutionListener listener : listeners) {
-            listener.executionStarted(source, stepInto);
-        }
-        try {
-            provider.run(source);
-        } catch (DebugSupportException ex) {
-            throw new DebugException(ex);
-        } finally {
-            for (DebugExecutionListener listener : listeners) {
-                listener.executionEnded();
-            }
-        }
-    }
-
-    /**
-     * Evaluates string of language code in a halted execution context, at top level if
-     * <code>mFrame==null</code>.
-     *
-     * @throws DebugException
-     */
-    Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugException {
-        for (DebugExecutionListener listener : listeners) {
-            listener.executionStarted(source, false);
-        }
-        try {
-            return provider.evalInContext(source, node, mFrame);
-        } catch (DebugSupportException ex) {
-            throw new DebugException(ex);
-        } finally {
-            for (DebugExecutionListener listener : listeners) {
-                listener.executionEnded();
-            }
-        }
-    }
-
-    /**
-     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
-     * that, when executed, computes the result of a textual expression in the language; used to
-     * create an
-     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
-     * Advanced Instrument}.
-     *
-     * @param expr a guest language expression
-     * @param resultListener optional listener for the result of each evaluation.
-     * @return a new factory
-     * @throws DebugException if the factory cannot be created, for example if the expression is
-     *             badly formed.
-     */
-    AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException {
-        try {
-            return provider.createAdvancedInstrumentRootFactory(expr, resultListener);
-        } catch (DebugSupportException ex) {
-            throw new DebugException(ex);
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/FrameDebugDescription.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-/**
- * A summary description of a Truffle {@link Frame} in a particular stack context.
- *
- * @see DebugEngine
- */
-public final class FrameDebugDescription {
-
-    private final int index;
-    private final Node node;
-    private final FrameInstance frameInstance;
-
-    FrameDebugDescription(int index, Node node, FrameInstance frameInstance) {
-        this.index = index;
-        this.node = node;
-        this.frameInstance = frameInstance;
-    }
-
-    /**
-     * Position in the current stack: {@code 0} at the top.
-     */
-    public int index() {
-        return index;
-    }
-
-    /**
-     * AST location.
-     */
-    public Node node() {
-        return node;
-    }
-
-    /**
-     * Access to the Truffle {@link Frame}.
-     */
-    public FrameInstance frameInstance() {
-        return frameInstance;
-    }
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpoint.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import com.oracle.truffle.api.source.*;
-
-// TODO (mlvdv) generic?
-/**
- * A breakpoint associated with a {@linkplain LineLocation source line location}.
- *
- * @see DebugEngine
- */
-public abstract class LineBreakpoint extends Breakpoint {
-
-    LineBreakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
-        super(state, groupId, ignoreCount, isOneShot);
-    }
-
-    /**
-     * Gets the {@linkplain LineLocation source line location} that specifies where this breakpoint
-     * will trigger.
-     */
-    public abstract LineLocation getLineLocation();
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import static com.oracle.truffle.tools.debug.engine.Breakpoint.BreakpointState.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.tools.*;
-import com.oracle.truffle.tools.debug.engine.DebugEngine.BreakpointCallback;
-import com.oracle.truffle.tools.debug.engine.DebugEngine.WarningLog;
-
-//TODO (mlvdv) some common functionality could be factored out of this and TagBreakpointSupport
-
-/**
- * Support class for creating and managing all existing ordinary (user visible) line breakpoints.
- * <p>
- * Notes:
- * <ol>
- * <li>Line breakpoints can only be set at nodes tagged as {@link StandardSyntaxTag#STATEMENT}.</li>
- * <li>A newly created breakpoint looks for probes matching the location, attaches to them if found
- * by installing an {@link Instrument} that calls back to the breakpoint.</li>
- * <li>When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be
- * copied along with the rest of the AST and will call back to the same breakpoint.</li>
- * <li>When notification is received of a new Node being tagged as a statement, and if a
- * breakpoint's line location matches the Probe's line location, then the breakpoint will attach a
- * new Instrument at the probe to activate the breakpoint at that location.</li>
- * <li>A breakpoint may have multiple Instruments deployed, one attached to each Probe that matches
- * the breakpoint's line location; this might happen when a source is reloaded.</li>
- * </ol>
- *
- */
-final class LineBreakpointFactory {
-
-    private static final boolean TRACE = false;
-    private static final PrintStream OUT = System.out;
-
-    private static final String BREAKPOINT_NAME = "LINE BREAKPOINT";
-
-    private static void trace(String format, Object... args) {
-        if (TRACE) {
-            OUT.println(String.format("%s: %s", BREAKPOINT_NAME, String.format(format, args)));
-        }
-    }
-
-    private static final Comparator<Entry<LineLocation, LineBreakpointImpl>> BREAKPOINT_COMPARATOR = new Comparator<Entry<LineLocation, LineBreakpointImpl>>() {
-
-        @Override
-        public int compare(Entry<LineLocation, LineBreakpointImpl> entry1, Entry<LineLocation, LineBreakpointImpl> entry2) {
-            final LineLocation line1 = entry1.getKey();
-            final LineLocation line2 = entry2.getKey();
-            final int nameOrder = line1.getSource().getShortName().compareTo(line2.getSource().getShortName());
-            if (nameOrder != 0) {
-                return nameOrder;
-            }
-            return Integer.compare(line1.getLineNumber(), line2.getLineNumber());
-        }
-    };
-
-    private final DebugExecutionSupport executionSupport;
-    private final BreakpointCallback breakpointCallback;
-    private final WarningLog warningLog;
-
-    /**
-     * Map: Source lines ==> attached breakpoints. There may be no more than one line breakpoint
-     * associated with a line.
-     */
-    private final Map<LineLocation, LineBreakpointImpl> lineToBreakpoint = new HashMap<>();
-
-    /**
-     * A map of {@link LineLocation} to a collection of {@link Probe}s. This list must be
-     * initialized and filled prior to being used by this class.
-     */
-    private final LineToProbesMap lineToProbesMap;
-
-    /**
-     * Globally suspends all line breakpoint activity when {@code false}, ignoring whether
-     * individual breakpoints are enabled.
-     */
-    @CompilationFinal private boolean breakpointsActive = true;
-    private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active");
-
-    LineBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) {
-        this.executionSupport = executionSupport;
-        this.breakpointCallback = breakpointCallback;
-        this.warningLog = warningLog;
-
-        lineToProbesMap = new LineToProbesMap();
-        lineToProbesMap.install();
-
-        Probe.addProbeListener(new DefaultProbeListener() {
-
-            @Override
-            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-                if (tag == StandardSyntaxTag.STATEMENT) {
-                    final SourceSection sourceSection = probe.getProbedSourceSection();
-                    if (sourceSection != null) {
-                        final LineLocation lineLocation = sourceSection.getLineLocation();
-                        if (lineLocation != null) {
-                            // A Probe with line location tagged STATEMENT we haven't seen before.
-                            final LineBreakpointImpl breakpoint = lineToBreakpoint.get(lineLocation);
-                            if (breakpoint != null) {
-                                try {
-                                    breakpoint.attach(probe);
-                                } catch (DebugException e) {
-                                    warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
-                                    if (TRACE) {
-                                        OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * Globally enables line breakpoint activity; all breakpoints are ignored when set to
-     * {@code false}. When set to {@code true}, the enabled/disabled status of each breakpoint
-     * determines whether it will trigger when flow of execution reaches it.
-     *
-     * @param breakpointsActive
-     */
-    void setActive(boolean breakpointsActive) {
-        if (this.breakpointsActive != breakpointsActive) {
-            breakpointsActiveUnchanged.invalidate();
-            this.breakpointsActive = breakpointsActive;
-        }
-    }
-
-    /**
-     * Returns the (not yet disposed) breakpoint by id; null if none.
-     */
-    LineBreakpoint find(long id) {
-        for (LineBreakpoint breakpoint : lineToBreakpoint.values()) {
-            if (breakpoint.getId() == id) {
-                return breakpoint;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Gets all current line breakpoints,regardless of status; sorted and modification safe.
-     */
-    List<LineBreakpoint> getAll() {
-        ArrayList<Entry<LineLocation, LineBreakpointImpl>> entries = new ArrayList<>(lineToBreakpoint.entrySet());
-        Collections.sort(entries, BREAKPOINT_COMPARATOR);
-
-        final ArrayList<LineBreakpoint> breakpoints = new ArrayList<>(entries.size());
-        for (Entry<LineLocation, LineBreakpointImpl> entry : entries) {
-            breakpoints.add(entry.getValue());
-        }
-        return breakpoints;
-    }
-
-    /**
-     * Creates a new line breakpoint if one doesn't already exist. If one does exist, then resets
-     * the <em>ignore count</em>.
-     *
-     * @param lineLocation where to set the breakpoint
-     * @param ignoreCount number of initial hits before the breakpoint starts causing breaks.
-     * @param oneShot whether the breakpoint should dispose itself after one hit
-     * @return a possibly new breakpoint
-     * @throws DebugException if a breakpoint already exists at the location and the ignore count is
-     *             the same
-     */
-    LineBreakpoint create(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) throws DebugException {
-
-        LineBreakpointImpl breakpoint = lineToBreakpoint.get(lineLocation);
-
-        if (breakpoint == null) {
-            breakpoint = new LineBreakpointImpl(groupId, ignoreCount, lineLocation, oneShot);
-
-            if (TRACE) {
-                trace("NEW " + breakpoint.getShortDescription());
-            }
-
-            lineToBreakpoint.put(lineLocation, breakpoint);
-
-            for (Probe probe : lineToProbesMap.findProbes(lineLocation)) {
-                if (probe.isTaggedAs(StandardSyntaxTag.STATEMENT)) {
-                    breakpoint.attach(probe);
-                    break;
-                }
-            }
-        } else {
-            if (ignoreCount == breakpoint.getIgnoreCount()) {
-                throw new DebugException(BREAKPOINT_NAME + " already set at line " + lineLocation);
-            }
-            breakpoint.setIgnoreCount(ignoreCount);
-            if (TRACE) {
-                trace("CHANGED ignoreCount %s", breakpoint.getShortDescription());
-            }
-        }
-        return breakpoint;
-    }
-
-    /**
-     * Returns the {@link LineBreakpoint} for a given line. There should only ever be one breakpoint
-     * per line.
-     *
-     * @param lineLocation The {@link LineLocation} to get the breakpoint for.
-     * @return The breakpoint for the given line.
-     */
-    LineBreakpoint get(LineLocation lineLocation) {
-        return lineToBreakpoint.get(lineLocation);
-    }
-
-    /**
-     * Removes the associated instrumentation for all one-shot breakpoints only.
-     */
-    void disposeOneShots() {
-        List<LineBreakpointImpl> breakpoints = new ArrayList<>(lineToBreakpoint.values());
-        for (LineBreakpointImpl breakpoint : breakpoints) {
-            if (breakpoint.isOneShot()) {
-                breakpoint.dispose();
-            }
-        }
-    }
-
-    /**
-     * Removes all knowledge of a breakpoint, presumed disposed.
-     */
-    private void forget(LineBreakpointImpl breakpoint) {
-        lineToBreakpoint.remove(breakpoint.getLineLocation());
-    }
-
-    /**
-     * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
-     * probe at the designated source location.
-     */
-    private final class LineBreakpointImpl extends LineBreakpoint implements AdvancedInstrumentResultListener {
-
-        private static final String SHOULD_NOT_HAPPEN = "LineBreakpointImpl:  should not happen";
-
-        private final LineLocation lineLocation;
-
-        // Cached assumption that the global status of line breakpoint activity has not changed.
-        private Assumption breakpointsActiveAssumption;
-
-        // Whether this breakpoint is enable/disabled
-        @CompilationFinal private boolean isEnabled;
-        private Assumption enabledUnchangedAssumption;
-
-        private String conditionExpr;
-
-        /**
-         * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
-         * {@code null} if not attached.
-         */
-        private List<Instrument> instruments = new ArrayList<>();
-
-        public LineBreakpointImpl(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) {
-            super(ENABLED_UNRESOLVED, groupId, ignoreCount, oneShot);
-            this.lineLocation = lineLocation;
-
-            this.breakpointsActiveAssumption = LineBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
-            this.isEnabled = true;
-            this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption(BREAKPOINT_NAME + " enabled state unchanged");
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return isEnabled;
-        }
-
-        @Override
-        public void setEnabled(boolean enabled) {
-            if (enabled != isEnabled) {
-                switch (getState()) {
-                    case ENABLED:
-                        assert !enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(false);
-                        changeState(DISABLED);
-                        break;
-                    case ENABLED_UNRESOLVED:
-                        assert !enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(false);
-                        changeState(DISABLED_UNRESOLVED);
-                        break;
-                    case DISABLED:
-                        assert enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(true);
-                        changeState(ENABLED);
-                        break;
-                    case DISABLED_UNRESOLVED:
-                        assert enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(true);
-                        changeState(DISABLED_UNRESOLVED);
-                        break;
-                    case DISPOSED:
-                        assert false : "breakpoint disposed";
-                        break;
-                    default:
-                        assert false : SHOULD_NOT_HAPPEN;
-                        break;
-                }
-            }
-        }
-
-        @Override
-        public void setCondition(String expr) throws DebugException {
-            if (this.conditionExpr != null || expr != null) {
-                // De-instrument the Probes instrumented by this breakpoint
-                final ArrayList<Probe> probes = new ArrayList<>();
-                for (Instrument instrument : instruments) {
-                    probes.add(instrument.getProbe());
-                    instrument.dispose();
-                }
-                instruments.clear();
-                this.conditionExpr = expr;
-                // Re-instrument the probes previously instrumented
-                for (Probe probe : probes) {
-                    attach(probe);
-                }
-            }
-        }
-
-        @Override
-        public String getCondition() {
-            return conditionExpr;
-        }
-
-        @Override
-        public void dispose() {
-            if (getState() != DISPOSED) {
-                for (Instrument instrument : instruments) {
-                    instrument.dispose();
-                }
-                changeState(DISPOSED);
-                LineBreakpointFactory.this.forget(this);
-            }
-        }
-
-        private void attach(Probe newProbe) throws DebugException {
-            if (getState() == DISPOSED) {
-                throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
-            }
-            Instrument newInstrument = null;
-            if (conditionExpr == null) {
-                newInstrument = Instrument.create(new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME);
-            } else {
-                newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
-            }
-            newProbe.attach(newInstrument);
-            instruments.add(newInstrument);
-            changeState(isEnabled ? ENABLED : DISABLED);
-        }
-
-        private void doSetEnabled(boolean enabled) {
-            if (this.isEnabled != enabled) {
-                enabledUnchangedAssumption.invalidate();
-                this.isEnabled = enabled;
-            }
-        }
-
-        private String getShortDescription() {
-            return BREAKPOINT_NAME + "@" + getLineLocation().getShortDescription();
-        }
-
-        private void changeState(BreakpointState after) {
-            if (TRACE) {
-                trace("STATE %s-->%s %s", getState().getName(), after.getName(), getShortDescription());
-            }
-            setState(after);
-        }
-
-        private void doBreak(Node node, VirtualFrame vFrame) {
-            if (incrHitCountCheckIgnore()) {
-                breakpointCallback.haltedAt(node, vFrame.materialize(), BREAKPOINT_NAME);
-            }
-        }
-
-        /**
-         * Receives notification from the attached instrument that execution is about to enter node
-         * where the breakpoint is set. Designed so that when in the fast path, there is either an
-         * unconditional "halt" call to the debugger or nothing.
-         */
-        private void nodeEnter(Node astNode, VirtualFrame vFrame) {
-
-            // Deopt if the global active/inactive flag has changed
-            try {
-                this.breakpointsActiveAssumption.check();
-            } catch (InvalidAssumptionException ex) {
-                this.breakpointsActiveAssumption = LineBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
-            }
-
-            // Deopt if the enabled/disabled state of this breakpoint has changed
-            try {
-                this.enabledUnchangedAssumption.check();
-            } catch (InvalidAssumptionException ex) {
-                this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption("LineBreakpoint enabled state unchanged");
-            }
-
-            if (LineBreakpointFactory.this.breakpointsActive && this.isEnabled) {
-                if (isOneShot()) {
-                    dispose();
-                }
-                LineBreakpointImpl.this.doBreak(astNode, vFrame);
-            }
-        }
-
-        public void notifyResult(Node node, VirtualFrame vFrame, Object result) {
-            final boolean condition = (Boolean) result;
-            if (TRACE) {
-                trace("breakpoint condition = %b  %s", condition, getShortDescription());
-            }
-            if (condition) {
-                nodeEnter(node, vFrame);
-            }
-        }
-
-        @TruffleBoundary
-        public void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
-            warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
-            if (TRACE) {
-                trace("breakpoint failure = %s  %s", ex.toString(), getShortDescription());
-            }
-            // Take the breakpoint if evaluation fails.
-            nodeEnter(node, vFrame);
-        }
-
-        @Override
-        public String getLocationDescription() {
-            return "Line: " + lineLocation.getShortDescription();
-        }
-
-        @Override
-        public LineLocation getLineLocation() {
-            return lineLocation;
-        }
-
-        private final class UnconditionalLineBreakInstrumentListener extends DefaultStandardInstrumentListener {
-
-            @Override
-            public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-                LineBreakpointImpl.this.nodeEnter(node, vFrame);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpoint.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import com.oracle.truffle.api.instrument.*;
-
-// TODO (mlvdv) generic?
-/**
- * A breakpoint associated with a {@link SyntaxTag}.
- *
- * @see DebugEngine
- */
-public abstract class TagBreakpoint extends Breakpoint {
-
-    TagBreakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
-        super(state, groupId, ignoreCount, isOneShot);
-    }
-
-    /**
-     * Gets the tag that specifies where this breakpoint will trigger.
-     */
-    public abstract SyntaxTag getTag();
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,441 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.engine;
-
-import static com.oracle.truffle.tools.debug.engine.Breakpoint.BreakpointState.*;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.utilities.*;
-import com.oracle.truffle.tools.debug.engine.DebugEngine.BreakpointCallback;
-import com.oracle.truffle.tools.debug.engine.DebugEngine.WarningLog;
-
-// TODO (mlvdv) some common functionality could be factored out of this and LineBreakpointSupport
-
-/**
- * Support class for creating and managing "Tag Breakpoints". A Tag Breakpoint halts execution just
- * before reaching any node whose Probe carries a specified {@linkplain SyntaxTag Tag}.
- * <p>
- * The {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Tag Trap}, which is built directly into the
- * Instrumentation Framework, does the same thing more efficiently, but there may only be one Tag
- * Trap active at a time. Any number of tag breakpoints may coexist with the Tag Trap, but it would
- * be confusing to have a Tag Breakpoint set for the same Tag as the current Tag Trap.
- * <p>
- * Notes:
- * <ol>
- * <li>Only one Tag Breakpoint can be active for a specific {@linkplain SyntaxTag Tag}.</li>
- * <li>A newly created breakpoint looks for probes matching the tag, attaches to them if found by
- * installing an {@link Instrument}.</li>
- * <li>When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be
- * copied along with the rest of the AST and will call back to the same breakpoint.</li>
- * <li>When notification is received that the breakpoint's Tag has been newly added to a Node, then
- * the breakpoint will attach a new Instrument at the probe to activate the breakpoint at that
- * location.</li>
- * <li>A breakpoint may have multiple Instruments deployed, one attached to each Probe that holds
- * the breakpoint's tag; this might happen when a source is reloaded.</li>
- * </ol>
- */
-final class TagBreakpointFactory {
-
-    private static final boolean TRACE = false;
-    private static final PrintStream OUT = System.out;
-
-    private static final String BREAKPOINT_NAME = "TAG BREAKPOINT";
-
-    private static void trace(String format, Object... args) {
-        if (TRACE) {
-            OUT.println(String.format("%s: %s", BREAKPOINT_NAME, String.format(format, args)));
-        }
-    }
-
-    private static final Comparator<Entry<SyntaxTag, TagBreakpointImpl>> BREAKPOINT_COMPARATOR = new Comparator<Entry<SyntaxTag, TagBreakpointImpl>>() {
-
-        @Override
-        public int compare(Entry<SyntaxTag, TagBreakpointImpl> entry1, Entry<SyntaxTag, TagBreakpointImpl> entry2) {
-            return entry1.getKey().name().compareTo(entry2.getKey().name());
-        }
-    };
-
-    private final DebugExecutionSupport executionSupport;
-    private final BreakpointCallback breakpointCallback;
-    private final WarningLog warningLog;
-
-    /**
-     * Map: Tags ==> Tag Breakpoints. There may be no more than one breakpoint per Tag.
-     */
-    private final Map<SyntaxTag, TagBreakpointImpl> tagToBreakpoint = new HashMap<>();
-
-    /**
-     * Globally suspends all line breakpoint activity when {@code false}, ignoring whether
-     * individual breakpoints are enabled.
-     */
-    @CompilationFinal private boolean breakpointsActive = true;
-    private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active");
-
-    TagBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) {
-        this.executionSupport = executionSupport;
-        this.breakpointCallback = breakpointCallback;
-        this.warningLog = warningLog;
-
-        Probe.addProbeListener(new DefaultProbeListener() {
-
-            @Override
-            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-                final TagBreakpointImpl breakpoint = tagToBreakpoint.get(tag);
-                if (breakpoint != null) {
-                    try {
-                        breakpoint.attach(probe);
-                    } catch (DebugException e) {
-                        warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
-                        if (TRACE) {
-                            OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * Globally enables tag breakpoint activity; all breakpoints are ignored when set to
-     * {@code false}. When set to {@code true}, the enabled/disabled status of each breakpoint
-     * determines whether it will trigger when flow of execution reaches it.
-     *
-     * @param breakpointsActive
-     */
-    void setActive(boolean breakpointsActive) {
-        if (this.breakpointsActive != breakpointsActive) {
-            breakpointsActiveUnchanged.invalidate();
-            this.breakpointsActive = breakpointsActive;
-        }
-    }
-
-    /**
-     * Returns the (not yet disposed) breakpoint by id, if any; null if none.
-     */
-    TagBreakpoint find(long id) {
-        for (TagBreakpointImpl breakpoint : tagToBreakpoint.values()) {
-            if (breakpoint.getId() == id) {
-                return breakpoint;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Gets all current tag breakpoints,regardless of status; sorted and modification safe.
-     */
-    List<TagBreakpoint> getAll() {
-        ArrayList<Entry<SyntaxTag, TagBreakpointImpl>> entries = new ArrayList<>(tagToBreakpoint.entrySet());
-        Collections.sort(entries, BREAKPOINT_COMPARATOR);
-
-        final ArrayList<TagBreakpoint> breakpoints = new ArrayList<>(entries.size());
-        for (Entry<SyntaxTag, TagBreakpointImpl> entry : entries) {
-            breakpoints.add(entry.getValue());
-        }
-        return breakpoints;
-    }
-
-    /**
-     * Creates a new tag breakpoint if one doesn't already exist. If one does exist, then resets the
-     * <em>ignore count</em>.
-     *
-     * @param tag where to set the breakpoint
-     * @param ignoreCount number of initial hits before the breakpoint starts causing breaks.
-     * @param oneShot whether the breakpoint should dispose itself after one hit
-     * @return a possibly new breakpoint
-     * @throws DebugException if a breakpoint already exists for the tag and the ignore count is the
-     *             same
-     */
-    TagBreakpoint create(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) throws DebugException {
-
-        TagBreakpointImpl breakpoint = tagToBreakpoint.get(tag);
-
-        if (breakpoint == null) {
-            breakpoint = new TagBreakpointImpl(groupId, ignoreCount, tag, oneShot);
-
-            if (TRACE) {
-                trace("NEW " + breakpoint.getShortDescription());
-            }
-
-            tagToBreakpoint.put(tag, breakpoint);
-
-            for (Probe probe : Probe.findProbesTaggedAs(tag)) {
-                breakpoint.attach(probe);
-            }
-        } else {
-            if (ignoreCount == breakpoint.getIgnoreCount()) {
-                throw new DebugException(BREAKPOINT_NAME + " already set for tag " + tag.name());
-            }
-            breakpoint.setIgnoreCount(ignoreCount);
-            if (TRACE) {
-                trace("CHANGED ignoreCount %s", breakpoint.getShortDescription());
-            }
-        }
-        return breakpoint;
-    }
-
-    /**
-     * Returns the {@link TagBreakpoint} for a given tag, {@code null} if none.
-     */
-    TagBreakpoint get(SyntaxTag tag) {
-        return tagToBreakpoint.get(tag);
-    }
-
-    /**
-     * Removes the associated instrumentation for all one-shot breakpoints only.
-     */
-    void disposeOneShots() {
-        List<TagBreakpointImpl> breakpoints = new ArrayList<>(tagToBreakpoint.values());
-        for (TagBreakpointImpl breakpoint : breakpoints) {
-            if (breakpoint.isOneShot()) {
-                breakpoint.dispose();
-            }
-        }
-    }
-
-    /**
-     * Removes all knowledge of a breakpoint, presumed disposed.
-     */
-    private void forget(TagBreakpointImpl breakpoint) {
-        tagToBreakpoint.remove(breakpoint.getTag());
-    }
-
-    /**
-     * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
-     * probe at the designated source location.
-     */
-    private final class TagBreakpointImpl extends TagBreakpoint implements AdvancedInstrumentResultListener {
-
-        private static final String SHOULD_NOT_HAPPEN = "TagBreakpointImpl:  should not happen";
-
-        private final SyntaxTag tag;
-
-        // Cached assumption that the global status of tag breakpoint activity has not changed.
-        private Assumption breakpointsActiveAssumption;
-
-        // Whether this breakpoint is enable/disabled
-        @CompilationFinal private boolean isEnabled;
-        private Assumption enabledUnchangedAssumption;
-
-        private String conditionExpr;
-
-        /**
-         * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
-         * {@code null} if not attached.
-         */
-        private List<Instrument> instruments = new ArrayList<>();
-
-        private TagBreakpointImpl(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) {
-            super(ENABLED, groupId, ignoreCount, oneShot);
-            this.tag = tag;
-            this.breakpointsActiveAssumption = TagBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
-            this.isEnabled = true;
-            this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption(BREAKPOINT_NAME + " enabled state unchanged");
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return isEnabled;
-        }
-
-        @Override
-        public void setEnabled(boolean enabled) {
-            // Tag Breakpoints are never unresolved
-            if (enabled != isEnabled) {
-                switch (getState()) {
-                    case ENABLED:
-                        assert !enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(false);
-                        changeState(DISABLED);
-                        break;
-                    case DISABLED:
-                        assert enabled : SHOULD_NOT_HAPPEN;
-                        doSetEnabled(true);
-                        changeState(ENABLED);
-                        break;
-                    case DISPOSED:
-                        assert false : "breakpoint disposed";
-                        break;
-                    case ENABLED_UNRESOLVED:
-                    case DISABLED_UNRESOLVED:
-                    default:
-                        assert false : SHOULD_NOT_HAPPEN;
-                        break;
-                }
-            }
-        }
-
-        @Override
-        public void setCondition(String expr) throws DebugException {
-            if (this.conditionExpr != null || expr != null) {
-                // De-instrument the Probes instrumented by this breakpoint
-                final ArrayList<Probe> probes = new ArrayList<>();
-                for (Instrument instrument : instruments) {
-                    probes.add(instrument.getProbe());
-                    instrument.dispose();
-                }
-                instruments.clear();
-                this.conditionExpr = expr;
-                // Re-instrument the probes previously instrumented
-                for (Probe probe : probes) {
-                    attach(probe);
-                }
-            }
-        }
-
-        @Override
-        public String getCondition() {
-            return conditionExpr;
-        }
-
-        @Override
-        public void dispose() {
-            if (getState() != DISPOSED) {
-                for (Instrument instrument : instruments) {
-                    instrument.dispose();
-                }
-                changeState(DISPOSED);
-                TagBreakpointFactory.this.forget(this);
-            }
-        }
-
-        private void attach(Probe newProbe) throws DebugException {
-            if (getState() == DISPOSED) {
-                throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
-            }
-            Instrument newInstrument = null;
-            if (conditionExpr == null) {
-                newInstrument = Instrument.create(new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME);
-            } else {
-                newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
-            }
-            newProbe.attach(newInstrument);
-            instruments.add(newInstrument);
-            changeState(isEnabled ? ENABLED : DISABLED);
-        }
-
-        private void doSetEnabled(boolean enabled) {
-            if (this.isEnabled != enabled) {
-                enabledUnchangedAssumption.invalidate();
-                this.isEnabled = enabled;
-            }
-        }
-
-        private String getShortDescription() {
-            return BREAKPOINT_NAME + "@" + tag.name();
-        }
-
-        private void changeState(BreakpointState after) {
-            if (TRACE) {
-                trace("STATE %s-->%s %s", getState().getName(), after.getName(), getShortDescription());
-            }
-            setState(after);
-        }
-
-        private void doBreak(Node node, VirtualFrame vFrame) {
-            if (incrHitCountCheckIgnore()) {
-                breakpointCallback.haltedAt(node, vFrame.materialize(), BREAKPOINT_NAME);
-            }
-        }
-
-        /**
-         * Receives notification from the attached instrument that execution is about to enter node
-         * where the breakpoint is set. Designed so that when in the fast path, there is either an
-         * unconditional "halt" call to the debugger or nothing.
-         */
-        private void nodeEnter(Node astNode, VirtualFrame vFrame) {
-
-            // Deopt if the global active/inactive flag has changed
-            try {
-                this.breakpointsActiveAssumption.check();
-            } catch (InvalidAssumptionException ex) {
-                this.breakpointsActiveAssumption = TagBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
-            }
-
-            // Deopt if the enabled/disabled state of this breakpoint has changed
-            try {
-                this.enabledUnchangedAssumption.check();
-            } catch (InvalidAssumptionException ex) {
-                this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption("LineBreakpoint enabled state unchanged");
-            }
-
-            if (TagBreakpointFactory.this.breakpointsActive && this.isEnabled) {
-                if (isOneShot()) {
-                    dispose();
-                }
-                TagBreakpointImpl.this.doBreak(astNode, vFrame);
-            }
-
-        }
-
-        public void notifyResult(Node node, VirtualFrame vFrame, Object result) {
-            final boolean condition = (Boolean) result;
-            if (TRACE) {
-                trace("breakpoint condition = %b  %s", condition, getShortDescription());
-            }
-            if (condition) {
-                nodeEnter(node, vFrame);
-            }
-        }
-
-        public void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
-            warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
-            if (TRACE) {
-                trace("breakpoint failure = %s  %s", ex.toString(), getShortDescription());
-            }
-            // Take the breakpoint if evaluation fails.
-            nodeEnter(node, vFrame);
-        }
-
-        @Override
-        public String getLocationDescription() {
-            return "Tag " + tag.name();
-        }
-
-        @Override
-        public SyntaxTag getTag() {
-            return tag;
-        }
-
-        private final class UnconditionalTagBreakInstrumentListener extends DefaultStandardInstrumentListener {
-
-            @Override
-            public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-                TagBreakpointImpl.this.nodeEnter(node, vFrame);
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/package-info.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * This package contains the shared (language-agnostic) support for implementing debuggers
- * that work with Truffle-implemented languages.
- * <p>
- * This implementation is made possible by the general purpose Instrumentation Framework built
- * into the Truffle platform.  Some online documentation for the Instrumentation Framework is available
- * online:
- * <quote>
- * <a href="https://wiki.openjdk.java.net/display/Graal/Instrumentation+API">https://wiki.openjdk.java.net/display/Graal/Instrumentation+API</a>
- * </quote>
- * <p>
- * Debugging services for a Truffle-implemented language are provided by creating an instance
- * of {@link com.oracle.truffle.tools.debug.engine.DebugEngine} specialized for a specific language.  The DebugEngine can:
- * <ul>
- * <li>Load and run sources in the language</li>
- * <li>Set breakpoints possibly with conditions and other attributes, on source lines</li>
- * <li>Navigate by Continue, StepIn, StepOver, or StepOut</li>
- * <li>Examine the execution stack</li>
- * <li>Examine the contents of a stack frame</li>
- * <li>Evaluate a code fragment in the context of a stack frame</li>
- * </ul>
- * <p>
- * Specialization of the DebugEngine for a Truffle-implemented language takes several forms:
- * <ol>
- * <li>A specification from the language implementor that adds Instrumentation "tags" to the nodes
- * that a debugger should know about, for example Statements, Calls, and Throws</li>
- * <li>Methods to run programs/scripts generally, and more specifically run text fragments in the context of
- * a particular frame/Node in a halted Truffle execution</li>
- * <li>Utility methods, such as providing textual displays of Objects that represent values in the language</li>
- * </ol>
- * <p>
- * <strong>Note:</strong> Both the functionality and API for this package are under active development.
- * <p>
- * @see com.oracle.truffle.api.instrument
- */
-package com.oracle.truffle.tools.debug.engine;
-
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLClient.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell;
-
-/**
- * The client side of a simple message-based protocol for a possibly remote language
- * Read-Eval-Print-Loop.
- */
-public interface REPLClient {
-
-    /**
-     * Accepts a reply from the server; there may be more than one reply in response to a request.
-     */
-    REPLMessage receive(REPLMessage reply);
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-
-/**
- * A message for communication between a Read-Eval-Print-Loop server associated with a language
- * implementation and a possibly remote client.
- *
- * @see REPLClient
- * @see REPLServer
- */
-public final class REPLMessage {
-
-    // Some standard keys and values
-    public static final String AST = "ast";
-    public static final String AST_DEPTH = "show-max-depth";
-    public static final String BACKTRACE = "backtrace";
-    public static final String BREAK_AT_LINE = "break-at-line";
-    public static final String BREAK_AT_LINE_ONCE = "break-at-line-once";
-    public static final String BREAK_AT_THROW = "break-at-throw";
-    public static final String BREAK_AT_THROW_ONCE = "break-at-throw-once";
-    public static final String BREAKPOINT_CONDITION = "breakpoint-condition";
-    public static final String BREAKPOINT_GROUP_ID = "breakpoint-group-id";
-    public static final String BREAKPOINT_HIT_COUNT = "breakpoint-hit-count";
-    public static final String BREAKPOINT_ID = "breakpoint-id";
-    public static final String BREAKPOINT_IGNORE_COUNT = "breakpoint-ignore-count";
-    public static final String BREAKPOINT_INFO = "breakpoint-info";
-    public static final String BREAKPOINT_STATE = "breakpoint-state";
-    public static final String CLEAR_BREAK = "clear-breakpoint";
-    public static final String CODE = "code";
-    public static final String CONTINUE = "continue";
-    public static final String DEBUG_LEVEL = "debug-level";
-    public static final String DELETE_BREAK = "delete-breakpoint";
-    public static final String DISABLE_BREAK = "disable-breakpoint";
-    public static final String DISPLAY_MSG = "displayable-message";
-    public static final String DOWN = "down";
-    public static final String ENABLE_BREAK = "enable-breakpoint";
-    public static final String EVAL = "eval";
-    public static final String FAILED = "failed";
-    public static final String FILE = "file";
-    public static final String FILE_PATH = "path";
-    public static final String FRAME = "frame";
-    public static final String FRAME_INFO = "frame-info";
-    public static final String FRAME_NUMBER = "frame-number";
-    public static final String INFO = "info";
-    public static final String INFO_KEY = "info-key";
-    public static final String INFO_VALUE = "info-value";
-    public static final String KILL = "kill";
-    public static final String LANGUAGE = "language";
-    public static final String LINE_NUMBER = "line-number";
-    public static final String LIST = "list";
-    public static final String LOAD_RUN = "load-run-source";
-    public static final String LOAD_STEP = "load-step-into-source";
-    public static final String METHOD_NAME = "method-name";
-    public static final String OP = "op";
-    public static final String OPTION = "option";
-    public static final String QUIT = "quit";
-    public static final String REPEAT = "repeat";
-    public static final String SET = "set";
-    public static final String SET_BREAK_CONDITION = "set-breakpoint-condition";
-    public static final String SOURCE_LINE_TEXT = "source-line-text";
-    public static final String SOURCE_LOCATION = "source-location";
-    public static final String SOURCE_NAME = "source-name";
-    public static final String SOURCE_TEXT = "source-text";
-    public static final String STACK_SIZE = "stack-size";
-    public static final String STATUS = "status";
-    public static final String STEP_INTO = "step-into";
-    public static final String STEP_OUT = "step-out";
-    public static final String STEP_OVER = "step-over";
-    public static final String STOPPED = "stopped";
-    public static final String SUB = "sub";
-    public static final String SUBTREE = "subtree";
-    public static final String SUCCEEDED = "succeeded";
-    public static final String TOPIC = "topic";
-    public static final String TRUFFLE = "truffle";
-    public static final String TRUFFLE_AST = "truffle-ast";
-    public static final String TRUFFLE_NODE = "truffle-node";
-    public static final String TRUFFLE_SUBTREE = "truffle-subtree";
-    public static final String UNSET_BREAK_CONDITION = "unset-breakpoint-condition";
-    public static final String UP = "up";
-    public static final String VALUE = "value";
-    public static final String WARNINGS = "warnings";
-    private final Map<String, String> map;
-
-    /**
-     * Creates an empty REPL message.
-     */
-    public REPLMessage() {
-        this.map = new TreeMap<>();
-    }
-
-    /**
-     * Creates a REPL message with an initial entry.
-     */
-    public REPLMessage(String key, String value) {
-        this();
-        map.put(key, value);
-    }
-
-    public REPLMessage(REPLMessage message) {
-        this.map = new TreeMap<>(message.map);
-    }
-
-    public String get(String key) {
-        return map.get(key);
-    }
-
-    /**
-     * Returns the specified key value as an integer; {@code null} if missing or non-numeric.
-     */
-    public Integer getIntValue(String key) {
-        final String value = map.get(key);
-        if (value != null) {
-            try {
-                return Integer.parseInt(value);
-            } catch (NumberFormatException e) {
-
-            }
-        }
-        return null;
-    }
-
-    public String put(String key, String value) {
-        return map.put(key, value);
-    }
-
-    public String remove(String key) {
-        return map.remove(key);
-    }
-
-    public Set<String> keys() {
-        return map.keySet();
-    }
-
-    public void print(PrintStream out, String linePrefix) {
-        map.keySet();
-
-        for (Entry<String, String> entry : map.entrySet()) {
-            String value = entry.getValue();
-            if (value != null && value.length() > 50) {
-                value = value.substring(0, 50) + " ...";
-            }
-            out.println(linePrefix + entry.getKey() + " = \"" + value + "\"");
-        }
-    }
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLServer.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell;
-
-/**
- * The server side of a simple message-based protocol for a possibly remote language
- * Read-Eval-Print-Loop.
- */
-public interface REPLServer {
-
-    /**
-     * Starts up a server; status returned in a message.
-     */
-    REPLMessage start();
-
-    /**
-     * Ask the server to handle a request. Return a non-empty array of messages to simulate remote
-     * operation where the protocol has possibly multiple messages being returned asynchronously in
-     * response to each request.
-     */
-    REPLMessage[] receive(REPLMessage request);
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLClientContext.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-/**
- * Client context for interaction with a program halted by the {@link REPLServer}.
- */
-public interface REPLClientContext {
-
-    /**
-     * The source code halted in this context.
-     */
-    Source source();
-
-    /**
-     * The 1-based line at which execution is halted in this context; 0 means unknown.
-     */
-    int lineNumber();
-
-    /**
-     * The Truffle stack where execution is halted in this context.
-     */
-    List<REPLFrame> frames();
-
-    /**
-     * The nesting level of the execution context: 0 means evaluating shell commands outside any
-     * executing program.
-     */
-    int level();
-
-    /**
-     * The source currently selected by the user; defaults to where halted.
-     */
-    Source getSelectedSource();
-
-    /**
-     * The frame number in this execution context currently selected by the user; defaults to 0.
-     */
-    int getSelectedFrameNumber();
-
-    /**
-     * Issue a command to the REPLServer that
-     * <ul>
-     * <li>can be specified by a single "op",</li>
-     * <li>produces information in the form of a single string, and</li>
-     * <li>has no effect on the execution state.</li>
-     * </ul>
-     */
-    String stringQuery(String op);
-
-    /**
-     * Sets a new "default" frame number for frame-related commands.
-     */
-    void selectFrameNumber(int frameNumber);
-
-    /**
-     * Sends an information message.
-     */
-    void displayInfo(String message);
-
-    void displayStack();
-
-    /**
-     * Send a message related to handling a command in this context.
-     */
-    void displayReply(String message);
-
-    /**
-     * Send a message related to failure while handling a command in this context.
-     */
-    void displayFailReply(String message);
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLCommand.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-// TODO (mlvdv)  write a real command line parser
-abstract class REPLCommand {
-
-    private final String command;
-    private final String abbreviation;
-    private final String description;
-
-    public REPLCommand(String command, String abbreviation, String description) {
-        this.command = command;
-        this.abbreviation = abbreviation;
-        this.description = description;
-    }
-
-    public final String getCommand() {
-        return command;
-    }
-
-    public final String getAbbreviation() {
-        return abbreviation;
-    }
-
-    public final String getDescription() {
-        return description;
-    }
-
-    public String[] getHelp() {
-        return new String[]{getCommand() + ": " + getDescription()};
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLContinueException.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-class REPLContinueException extends RuntimeException {
-
-    private static final long serialVersionUID = 4763527450877123326L;
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLFrame.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-/**
- * Information about a stack frame in the current {@link REPLClientContext}.
- */
-interface REPLFrame {
-
-    /**
-     * Index of the frame.
-     */
-    int index();
-
-    /**
-     * File path; null if unknown.
-     */
-    String locationFilePath();
-
-    /**
-     * Line number of frame location; null if unknown.
-     */
-    Integer locationLineNumber();
-
-    /**
-     * Short description of the code location.
-     */
-    String locationDescription();
-
-    /**
-     * Name of the method body containing the location.
-     */
-    String name();
-
-    /**
-     * The line of text at the code location.
-     */
-    String sourceLineText();
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,696 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-// TODO (mlvdv)  write a real command line parser
-public abstract class REPLRemoteCommand extends REPLCommand {
-
-    public REPLRemoteCommand(String command, String abbreviation, String description) {
-        super(command, abbreviation, description);
-    }
-
-    protected abstract REPLMessage createRequest(REPLClientContext context, String[] args);
-
-    void processReply(REPLClientContext context, REPLMessage[] replies) {
-        REPLMessage firstReply = replies[0];
-
-        if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-            final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
-            context.displayFailReply(result != null ? result : firstReply.toString());
-        } else {
-            final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
-            context.displayReply(result != null ? result : firstReply.toString());
-        }
-
-        for (int i = 1; i < replies.length; i++) {
-            REPLMessage reply = replies[i];
-            final String result = reply.get(REPLMessage.DISPLAY_MSG);
-            context.displayInfo(result != null ? result : reply.toString());
-        }
-    }
-
-    public static final REPLRemoteCommand BREAK_AT_LINE_CMD = new REPLRemoteCommand("break-at-line", "break", "Set a breakpoint") {
-
-        private final String[] help = {"break <n> [ignore=<n>] : set breakpoint at line <n> in current file", "break <filename>:<n> [ignore=<n>] : set breakpoint at line <n> in <filename>",
-                        " optionally ignore first <n> hits (default 0)"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            try {
-                final REPLineLocation lineLocation = REPLineLocation.parse(context, args);
-                final REPLMessage requestMessage = lineLocation.createMessage(REPLMessage.BREAK_AT_LINE);
-                int ignoreCount = 0;
-                if (args.length > 2) {
-                    final String ignoreText = args[2];
-                    if (ignoreText.equals("ignore")) {
-                        throw new IllegalArgumentException("No ignore count specified");
-                    }
-                    final String[] split = ignoreText.split("=");
-                    if (split.length == 2 && split[0].equals("ignore")) {
-                        try {
-                            ignoreCount = Integer.parseInt(split[1]);
-                            if (ignoreCount < 0) {
-                                throw new IllegalArgumentException("Illegal ignore count: " + split[1]);
-                            }
-                        } catch (NumberFormatException e) {
-                            throw new IllegalArgumentException("No ignore count specified");
-                        }
-                    } else {
-                        throw new IllegalArgumentException("Unrecognized argument \"" + ignoreText + "\"");
-                    }
-                }
-                requestMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(ignoreCount));
-                return requestMessage;
-            } catch (IllegalArgumentException ex) {
-                context.displayFailReply(ex.getMessage());
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final String number = firstReply.get(REPLMessage.BREAKPOINT_ID);
-                final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
-                final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
-                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + number + " set at " + fileName + ":" + lineNumber);
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand BREAK_AT_LINE_ONCE_CMD = new REPLRemoteCommand("break-at-line-once", "break1", "Set a one-shot breakpoint") {
-
-        private final String[] help = {"break <n>: set one-shot breakpoint at line <n> in current file", "break <filename>:<n>: set one-shot breakpoint at line <n> in current file"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            try {
-                return REPLineLocation.parse(context, args).createMessage(REPLMessage.BREAK_AT_LINE_ONCE);
-            } catch (IllegalArgumentException ex) {
-                context.displayFailReply(ex.getMessage());
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
-                final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
-                firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint set at " + fileName + ":" + lineNumber);
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand BREAK_AT_THROW_CMD = new REPLRemoteCommand("break-at-throw", "breakthrow", "Break at any throw") {
-
-        private final String[] help = {"break-at-throw: set breakpoint on any throw"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint at any throw set");
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand BREAK_AT_THROW_ONCE_CMD = new REPLRemoteCommand("break-at-throw-once", "break1throw", "Break once at any throw") {
-
-        private final String[] help = {"break-at-throw: set one-short breakpoint on any throw"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW_ONCE);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint at any throw set");
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand CLEAR_BREAK_CMD = new REPLRemoteCommand("clear", null, "Clear a breakpoint") {
-
-        private final String[] help = {"clear <n>: clear breakpoint number <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length == 1) {
-                context.displayFailReply("breakpoint number not speciified:  \"break <n>\"");
-            } else if (args.length > 2) {
-                context.displayFailReply("breakpoint number not understood:  \"break <n>\"");
-            } else {
-                try {
-                    final int breakpointNumber = Integer.parseInt(args[1]);
-                    final REPLMessage request = new REPLMessage();
-                    request.put(REPLMessage.OP, REPLMessage.CLEAR_BREAK);
-                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-                    return request;
-                } catch (IllegalArgumentException ex) {
-                    context.displayFailReply(ex.getMessage());
-                }
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
-                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " cleared");
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand CONDITION_BREAK_CMD = new REPLRemoteCommand("cond", null, "Set new condition on a breakpoint") {
-
-        private final String[] help = {"cond <n> [expr]: sets new condition on breakpoint number <n>; make unconditional if no [expr]"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length == 1) {
-                context.displayFailReply("breakpoint number not speciified:  \"cond <n>\"");
-            } else {
-                try {
-                    final int breakpointNumber = Integer.parseInt(args[1]);
-                    final REPLMessage request = new REPLMessage();
-                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-                    if (args.length == 2) {
-                        request.put(REPLMessage.OP, REPLMessage.UNSET_BREAK_CONDITION);
-                    } else {
-                        final StringBuilder exprBuilder = new StringBuilder();
-                        for (int i = 2; i < args.length; i++) {
-                            exprBuilder.append(args[i]).append(" ");
-                        }
-                        request.put(REPLMessage.BREAKPOINT_CONDITION, exprBuilder.toString().trim());
-                        request.put(REPLMessage.OP, REPLMessage.SET_BREAK_CONDITION);
-                    }
-                    return request;
-                } catch (IllegalArgumentException ex) {
-                    context.displayFailReply(ex.getMessage());
-                }
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
-                final String condition = firstReply.get(REPLMessage.BREAKPOINT_CONDITION);
-                if (condition == null) {
-                    firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition cleared");
-                } else {
-                    firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition=\"" + condition + "\"");
-                }
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand CONTINUE_CMD = new REPLRemoteCommand("continue", "c", "Continue execution") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.CONTINUE);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-
-            throw new REPLContinueException();
-
-        }
-    };
-
-    public static final REPLRemoteCommand DELETE_CMD = new REPLRemoteCommand("delete", "d", "Delete all breakpoints") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.DELETE_BREAK);
-            return request;
-        }
-    };
-
-    public static final REPLRemoteCommand DISABLE_CMD = new REPLRemoteCommand("disable", null, "Disable a breakpoint") {
-
-        private final String[] help = {"disable <n>: disable breakpoint number <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length == 1) {
-                context.displayFailReply("breakpoint number not speciified:  \"disable <n>\"");
-            } else if (args.length > 2) {
-                context.displayFailReply("breakpoint number not understood:  \"disable <n>\"");
-            } else {
-                try {
-                    final int breakpointNumber = Integer.parseInt(args[1]);
-                    final REPLMessage request = new REPLMessage();
-                    request.put(REPLMessage.OP, REPLMessage.DISABLE_BREAK);
-                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-                    return request;
-                } catch (IllegalArgumentException ex) {
-                    context.displayFailReply(ex.getMessage());
-                }
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
-                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " disabled");
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand DOWN_CMD = new REPLRemoteCommand("down", null, "Move down a stack frame") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final List<REPLFrame> frames = context.frames();
-            final int newFrameSelection = context.getSelectedFrameNumber() + 1;
-            if (newFrameSelection > frames.size() - 1) {
-                context.displayFailReply("at bottom of stack");
-                return null;
-            }
-            context.selectFrameNumber(newFrameSelection);
-            return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
-                context.displayFailReply(result != null ? result : firstReply.toString());
-            } else {
-                context.displayStack();
-            }
-        }
-    };
-
-    public static final REPLRemoteCommand ENABLE_CMD = new REPLRemoteCommand("enable", null, "Enable a breakpoint") {
-
-        private final String[] help = {"enable <n>: enable breakpoint number <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length == 1) {
-                context.displayFailReply("breakpoint number not speciified:  \"enable <n>\"");
-            } else if (args.length > 2) {
-                context.displayFailReply("breakpoint number not understood:  \"enable <n>\"");
-            } else {
-                try {
-                    final int breakpointNumber = Integer.parseInt(args[1]);
-                    final REPLMessage request = new REPLMessage();
-                    request.put(REPLMessage.OP, REPLMessage.ENABLE_BREAK);
-                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-                    return request;
-                } catch (IllegalArgumentException ex) {
-                    context.displayFailReply(ex.getMessage());
-                }
-            }
-            return null;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
-                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " enabled");
-            }
-            super.processReply(context, replies);
-        }
-    };
-
-    public static final REPLRemoteCommand FRAME_CMD = new REPLRemoteCommand("frame", null, "Display a stack frame") {
-
-        private final String[] help = {"frame : display currently selected frame", "frame <n> : display frame <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.FRAME);
-
-            int frameNumber = context.getSelectedFrameNumber();
-            if (args.length > 1) {
-                if (args.length == 2) {
-                    try {
-                        frameNumber = Integer.parseInt(args[1]);
-                    } catch (NumberFormatException e) {
-                        throw new IllegalArgumentException("Unrecognized argument \"" + args[1] + "\"");
-                    }
-                } else {
-                    throw new IllegalArgumentException("Unrecognized argument \"" + args[2] + "\"");
-                }
-            }
-            request.put(REPLMessage.FRAME_NUMBER, Integer.toString(frameNumber));
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                Integer frameNumber = replies[0].getIntValue(REPLMessage.FRAME_NUMBER);
-                context.selectFrameNumber(frameNumber);
-                context.displayReply("Frame " + frameNumber + ":");
-                for (REPLMessage message : replies) {
-                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
-                        context.displayInfo(line);
-                    }
-                }
-            }
-        }
-    };
-
-    public static final REPLRemoteCommand KILL_CMD = new REPLRemoteCommand("kill", null, "Stop program execution") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, "kill");
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
-                context.displayReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            }
-        }
-    };
-
-    public static final REPLRemoteCommand LOAD_RUN_CMD = new REPLRemoteCommand("load-run", "loadr", "Load and run a source") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            Source runSource = null;
-            if (args.length == 1) {
-                runSource = context.getSelectedSource();
-                if (runSource == null) {
-                    context.displayFailReply("No file selected");
-                    return null;
-                }
-            } else {
-                try {
-                    runSource = Source.fromFileName(args[1]);
-                } catch (IOException e) {
-                    context.displayFailReply("Can't find file: " + args[1]);
-                    return null;
-                }
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.LOAD_RUN);
-            request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
-            return request;
-        }
-    };
-
-    public static final REPLRemoteCommand LOAD_STEP_CMD = new REPLRemoteCommand("load-step", "loads", "Load and step into a source") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            Source runSource = null;
-            if (args.length == 1) {
-                runSource = context.getSelectedSource();
-                if (runSource == null) {
-                    context.displayFailReply("No file selected");
-                    return null;
-                }
-            } else {
-                try {
-                    runSource = Source.fromFileName(args[1]);
-                } catch (IOException e) {
-                    context.displayFailReply("Can't find file: " + args[1]);
-                    return null;
-                }
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.LOAD_STEP);
-            request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
-            return request;
-        }
-    };
-
-    public static final REPLRemoteCommand STEP_INTO_CMD = new REPLRemoteCommand("step", "s", "(StepInto) next statement, going into functions.") {
-
-        @Override
-        public String[] getHelp() {
-            return new String[]{"step into:  step to next statement (into calls)", "step <n>: step to nth next statement (into calls)"};
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.STEP_INTO);
-
-            if (args.length >= 2) {
-                final String nText = args[1];
-                try {
-                    final int nSteps = Integer.parseInt(nText);
-                    if (nSteps > 0) {
-                        request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
-                    } else {
-                        return null;
-                    }
-                } catch (NumberFormatException e) {
-                    context.displayFailReply("Step into count \"" + nText + "\" not recognized");
-                    return null;
-                }
-            }
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-
-            throw new REPLContinueException();
-        }
-    };
-
-    public static final REPLRemoteCommand STEP_OUT_CMD = new REPLRemoteCommand("finish", null, "(StepOut) continue to end of function") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.STEP_OUT);
-
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-
-            throw new REPLContinueException();
-        }
-    };
-
-    public static final REPLRemoteCommand STEP_OVER_CMD = new REPLRemoteCommand("next", "n", "(StepOver) execute next line of code, not into functions.") {
-
-        @Override
-        public String[] getHelp() {
-            return new String[]{"next:  (StepOver) execute next line of code, not into functions.", "next <n>: (StepOver) execute to nth next statement (not counting into functions)"};
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.STEP_OVER);
-
-            if (args.length >= 2) {
-                final String nText = args[1];
-                try {
-                    final int nSteps = Integer.parseInt(nText);
-                    if (nSteps > 0) {
-                        request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
-                    } else {
-                        return null;
-                    }
-                } catch (NumberFormatException e) {
-                    context.displayFailReply("Next count \"" + nText + "\" not recognized");
-                    return null;
-                }
-            }
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-
-            throw new REPLContinueException();
-        }
-    };
-
-    public static final REPLRemoteCommand UP_CMD = new REPLRemoteCommand("up", null, "Move up a stack frame") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (context.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final int newFrameSelection = context.getSelectedFrameNumber() - 1;
-            if (newFrameSelection < 0) {
-                context.displayFailReply("at top of stack");
-                return null;
-            }
-            context.selectFrameNumber(newFrameSelection);
-            return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
-                context.displayFailReply(result != null ? result : firstReply.toString());
-            } else {
-                context.displayStack();
-            }
-        }
-    };
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLineLocation.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-import java.io.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-final class REPLineLocation {
-
-    private final Source source;
-    private final int lineNumber;
-
-    /**
-     * Attempts to extract description of a source line from {@code arg[1]}, either
-     * "<source name>:<n>" or just "<n>".
-     */
-    static REPLineLocation parse(REPLClientContext context, String[] args) throws IllegalArgumentException {
-        if (args.length == 1) {
-            throw new IllegalArgumentException("no location specified");
-        }
-
-        Source source = null;
-        int lineNumber = -1;
-        String lineNumberText = null;
-
-        final String[] split = args[1].split(":");
-        if (split.length == 1) {
-            // Specification only has one part; it should be a line number
-            lineNumberText = split[0];
-            try {
-                lineNumber = Integer.parseInt(lineNumberText);
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException("no line number specified");
-            }
-            // If only line number specified, then there must be a selected file
-            final Source selectedSource = context.getSelectedSource();
-            if (selectedSource == null) {
-                throw new IllegalArgumentException("no selected file set");
-            }
-            source = selectedSource;
-
-        } else {
-            final String fileName = split[0];
-            lineNumberText = split[1];
-            try {
-                source = Source.fromFileName(fileName);
-            } catch (IOException e1) {
-                throw new IllegalArgumentException("Can't find file \"" + fileName + "\"");
-            }
-            try {
-                lineNumber = Integer.parseInt(lineNumberText);
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException("Invalid line number \"" + lineNumberText + "\"");
-            }
-            if (lineNumber <= 0) {
-                throw new IllegalArgumentException("Invalid line number \"" + lineNumberText + "\"");
-            }
-        }
-
-        return new REPLineLocation(source, lineNumber);
-    }
-
-    REPLineLocation(Source source, int lineNumber) {
-        this.source = source;
-        this.lineNumber = lineNumber;
-    }
-
-    public Source getSource() {
-        return source;
-    }
-
-    public int getLineNumber() {
-        return lineNumber;
-    }
-
-    /**
-     * Creates a message containing an "op" and a line location.
-     *
-     * @param op the operation to be performed on this location
-     */
-    public REPLMessage createMessage(String op) {
-        final REPLMessage msg = new REPLMessage(REPLMessage.OP, op);
-        msg.put(REPLMessage.SOURCE_NAME, source.getShortName());
-        msg.put(REPLMessage.FILE_PATH, source.getPath());
-        msg.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
-        return msg;
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1397 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.client;
-
-import java.io.*;
-import java.util.*;
-
-import jline.console.*;
-
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-/**
- * A very simple line-oriented, language-agnostic debugging client shell: the first step toward a
- * general, extensible debugging framework designed to be adapted for remote debugging.
- * <p>
- * The architecture of this debugging framework is modeled loosely on <a
- * href="https://github.com/clojure/tools.nrepl">nREPL</a>, a network REPL developed by the Clojure
- * community with a focus on generality:
- * <ul>
- * <li>Client and (possibly remote) server communicate via <em>messages</em> carried over some
- * <em>transport</em>;</li>
- * <li>A message is a <em>map</em> of key/value pairs;</li>
- * <li>Keys and values are <em>strings</em>;</li>
- * <li>The client sends messages as <em>requests</em> to a server;</li>
- * <li>A server dispatches each incoming request to an appropriate <em>handler</em> that takes
- * appropriate action and responds to the client with one or more messages; and</li>
- * <li>Many implementations of the <em>transport</em> are possible.</li>
- * </ul>
- * <p>
- * <strong>Compromises:</strong>
- * <p>
- * In order to get
- * <ol>
- * <li>A debugging session should start from this shell, but there is no machinery in place for
- * doing that; instead, an entry into the language implementation creates both the server and this
- * shell;</li>
- * <li>The current startup sequence is based on method calls, not messages;</li>
- * <li>Only a very few request types and keys are implemented, omitting for example request and
- * session ids;</li>
- * <li>Message passing is synchronous and "transported" via method calls;</li>
- * <li>Asynchrony is emulated by having each call to the server pass only a message, and by having
- * the server return only a list of messages.</li>
- * </ol>
- *
- * @see REPLServer
- * @see REPLMessage
- */
-public class SimpleREPLClient implements REPLClient {
-
-    private static final String REPLY_PREFIX = "==> ";
-    private static final String FAIL_PREFIX = "**> ";
-    private static final String WARNING_PREFIX = "!!> ";
-    private static final String TRACE_PREFIX = ">>> ";
-    private static final String[] NULL_ARGS = new String[0];
-
-    static final String INFO_LINE_FORMAT = "    %s\n";
-    static final String CODE_LINE_FORMAT = "    %3d  %s\n";
-    static final String CODE_LINE_BREAK_FORMAT = "--> %3d  %s\n";
-
-    private static final String STACK_FRAME_FORMAT = "    %3d: at %s in %s    line =\"%s\"\n";
-    private static final String STACK_FRAME_SELECTED_FORMAT = "==> %3d: at %s in %s    line =\"%s\"\n";
-
-    private final String languageName;
-
-    // Top level commands
-    private final Map<String, REPLCommand> commandMap = new HashMap<>();
-    private final Collection<String> commandNames = new TreeSet<>();
-
-    // Local options
-    private final Map<String, LocalOption> localOptions = new HashMap<>();
-    private final Collection<String> optionNames = new TreeSet<>();
-
-    // Current local context
-    ClientContextImpl clientContext;
-
-    // Cheating for the prototype; prototype startup now happens from the language server.
-    // So this isn't used.
-    public static void main(String[] args) {
-        final SimpleREPLClient repl = new SimpleREPLClient(null, null);
-        repl.start();
-    }
-
-    private final ConsoleReader reader;
-
-    private final PrintStream writer;
-
-    private final REPLServer replServer;
-
-    private final LocalOption astDepthOption = new IntegerOption(9, "astdepth", "default depth for AST display");
-
-    private final LocalOption autoWhereOption = new BooleanOption(true, "autowhere", "run the \"where\" command after each navigation");
-
-    private final LocalOption autoNodeOption = new BooleanOption(false, "autonode", "run the \"truffle node\" command after each navigation");
-
-    private final LocalOption autoSubtreeOption = new BooleanOption(false, "autosubtree", "run the \"truffle subtree\" command after each navigation");
-
-    private final LocalOption autoASTOption = new BooleanOption(false, "autoast", "run the \"truffle ast\" command after each navigation");
-
-    private final LocalOption listSizeOption = new IntegerOption(25, "listsize", "default number of lines to list");
-
-    private final LocalOption traceMessagesOption = new BooleanOption(false, "tracemessages", "trace REPL messages between client and server");
-
-    private final LocalOption verboseBreakpointInfoOption = new BooleanOption(true, "verbosebreakpointinfo", "\"info breakpoint\" displays more info");
-
-    private void addOption(LocalOption localOption) {
-        final String optionName = localOption.getName();
-        localOptions.put(optionName, localOption);
-        optionNames.add(optionName);
-    }
-
-    /**
-     * Non-null when the user has named a file other than where halted, providing context for
-     * commands such as "break"; if no explicit selection, then defaults to where halted. This is
-     * session state, so it persists across halting contexts.
-     */
-    private Source selectedSource = null;
-
-    public SimpleREPLClient(String languageName, REPLServer replServer) {
-        this.languageName = languageName;
-        this.replServer = replServer;
-        this.writer = System.out;
-        try {
-            this.reader = new ConsoleReader();
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to create console " + e);
-        }
-
-        addCommand(backtraceCommand);
-        addCommand(REPLRemoteCommand.BREAK_AT_LINE_CMD);
-        addCommand(REPLRemoteCommand.BREAK_AT_LINE_ONCE_CMD);
-        addCommand(REPLRemoteCommand.BREAK_AT_THROW_CMD);
-        addCommand(REPLRemoteCommand.BREAK_AT_THROW_ONCE_CMD);
-        addCommand(REPLRemoteCommand.CLEAR_BREAK_CMD);
-        addCommand(REPLRemoteCommand.CONDITION_BREAK_CMD);
-        addCommand(REPLRemoteCommand.CONTINUE_CMD);
-        addCommand(REPLRemoteCommand.DELETE_CMD);
-        addCommand(REPLRemoteCommand.DISABLE_CMD);
-        addCommand(REPLRemoteCommand.DOWN_CMD);
-        addCommand(REPLRemoteCommand.ENABLE_CMD);
-        addCommand(evalCommand);
-        addCommand(fileCommand);
-        addCommand(REPLRemoteCommand.FRAME_CMD);
-        addCommand(helpCommand);
-        addCommand(infoCommand);
-        addCommand(REPLRemoteCommand.KILL_CMD);
-        addCommand(listCommand);
-        addCommand(REPLRemoteCommand.LOAD_RUN_CMD);
-        addCommand(REPLRemoteCommand.LOAD_STEP_CMD);
-        addCommand(quitCommand);
-        addCommand(setCommand);
-        addCommand(REPLRemoteCommand.STEP_INTO_CMD);
-        addCommand(REPLRemoteCommand.STEP_OUT_CMD);
-        addCommand(REPLRemoteCommand.STEP_OVER_CMD);
-        addCommand(truffleCommand);
-        addCommand(REPLRemoteCommand.UP_CMD);
-        addCommand(whereCommand);
-
-        infoCommand.addCommand(infoBreakCommand);
-        infoCommand.addCommand(infoLanguageCommand);
-        infoCommand.addCommand(infoSetCommand);
-
-        truffleCommand.addCommand(truffleASTCommand);
-        truffleCommand.addCommand(truffleNodeCommand);
-        truffleCommand.addCommand(truffleSubtreeCommand);
-
-        addOption(astDepthOption);
-        addOption(autoASTOption);
-        addOption(autoNodeOption);
-        addOption(autoSubtreeOption);
-        addOption(autoWhereOption);
-        addOption(listSizeOption);
-        addOption(traceMessagesOption);
-        addOption(verboseBreakpointInfoOption);
-    }
-
-    public void start() {
-
-        REPLMessage startReply = replServer.start();
-
-        if (startReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-            clientContext.displayFailReply(startReply.get(REPLMessage.DISPLAY_MSG));
-            throw new RuntimeException("Can't start REPL server");
-        }
-
-        this.clientContext = new ClientContextImpl(null, null);
-
-        try {
-            clientContext.startSession();
-        } finally {
-            clientContext.displayReply("Goodbye from " + languageName + "/REPL");
-        }
-
-    }
-
-    public void addCommand(REPLCommand replCommand) {
-        final String commandName = replCommand.getCommand();
-        final String abbreviation = replCommand.getAbbreviation();
-
-        commandNames.add(commandName);
-        commandMap.put(commandName, replCommand);
-        if (abbreviation != null) {
-            commandMap.put(abbreviation, replCommand);
-        }
-    }
-
-    private class ClientContextImpl implements REPLClientContext {
-
-        private final ClientContextImpl predecessor;
-        private final int level;
-
-        // Information about where the execution is halted
-        /** The source where execution, if any, is halted; null if none. */
-        private Source haltedSource = null;
-        /** The line number where execution, if any, is halted; 0 if none. */
-        private int haltedLineNumber = 0;
-        /** The stack where execution, if any, is halted; null if none. Evaluated lazily. */
-        private List<REPLFrame> frames = null;
-
-        /** The frame number currently selected by user. */
-        private int selectedFrameNumber = 0;
-
-        private String currentPrompt;
-
-        /**
-         * Create a new context on the occasion of an execution halting.
-         */
-        public ClientContextImpl(ClientContextImpl predecessor, REPLMessage message) {
-            this.predecessor = predecessor;
-            this.level = predecessor == null ? 0 : predecessor.level + 1;
-
-            if (message != null) {
-                try {
-                    this.haltedSource = Source.fromFileName(message.get(REPLMessage.SOURCE_NAME));
-                    selectedSource = this.haltedSource;
-                    try {
-                        haltedLineNumber = Integer.parseInt(message.get(REPLMessage.LINE_NUMBER));
-                    } catch (NumberFormatException e) {
-                        haltedLineNumber = 0;
-                    }
-                } catch (IOException e1) {
-                    this.haltedSource = null;
-                    this.haltedLineNumber = 0;
-                }
-            }
-            updatePrompt();
-        }
-
-        private void selectSource(String fileName) {
-            try {
-                selectedSource = Source.fromFileName(fileName);
-            } catch (IOException e1) {
-                selectedSource = null;
-            }
-            updatePrompt();
-        }
-
-        private void updatePrompt() {
-            if (level == 0) {
-                // 0-level context; no executions halted.
-                if (selectedSource == null) {
-                    currentPrompt = languageName == null ? "() " : "( " + languageName + " ) ";
-                } else {
-                    currentPrompt = "(" + selectedSource.getShortName() + ") ";
-                }
-            } else if (selectedSource != null && selectedSource != haltedSource) {
-                // User is focusing somewhere else than the current locn; show no line number.
-                final StringBuilder sb = new StringBuilder();
-                sb.append("(<" + Integer.toString(level) + "> ");
-                sb.append(selectedSource.getShortName());
-                sb.append(") ");
-                currentPrompt = sb.toString();
-            } else {
-                // Prompt reveals where currently halted.
-                final StringBuilder sb = new StringBuilder();
-                sb.append("(<" + Integer.toString(level) + "> ");
-                sb.append(haltedSource == null ? "??" : haltedSource.getShortName());
-                if (haltedLineNumber > 0) {
-                    sb.append(":" + Integer.toString(haltedLineNumber));
-                }
-                sb.append(") ");
-                currentPrompt = sb.toString();
-            }
-
-        }
-
-        public Source source() {
-            return haltedSource;
-        }
-
-        public int lineNumber() {
-            return haltedLineNumber;
-        }
-
-        public List<REPLFrame> frames() {
-            if (frames == null) {
-                final REPLMessage request = new REPLMessage(REPLMessage.OP, REPLMessage.BACKTRACE);
-                final REPLMessage[] replies = sendToServer(request);
-                if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                    return null;
-                }
-                frames = new ArrayList<>();
-                for (REPLMessage reply : replies) {
-                    final int index = reply.getIntValue(REPLMessage.FRAME_NUMBER);
-                    final String locationFilePath = reply.get(REPLMessage.FILE_PATH);
-                    final Integer locationLineNumber = reply.getIntValue(REPLMessage.LINE_NUMBER);
-                    final String locationDescription = reply.get(REPLMessage.SOURCE_LOCATION);
-                    final String name = reply.get(REPLMessage.METHOD_NAME);
-                    final String sourceLineText = reply.get(REPLMessage.SOURCE_LINE_TEXT);
-                    frames.add(new REPLFrameImpl(index, locationFilePath, locationLineNumber, locationDescription, name, sourceLineText));
-                }
-                frames = Collections.unmodifiableList(frames);
-            }
-            return frames;
-        }
-
-        public int level() {
-            return this.level;
-        }
-
-        public Source getSelectedSource() {
-            return selectedSource == null ? haltedSource : selectedSource;
-        }
-
-        public int getSelectedFrameNumber() {
-            return selectedFrameNumber;
-        }
-
-        public String stringQuery(String op) {
-            assert op != null;
-            REPLMessage request = null;
-            switch (op) {
-                case REPLMessage.TRUFFLE_AST:
-                    request = truffleASTCommand.createRequest(clientContext, NULL_ARGS);
-                    break;
-                case REPLMessage.TRUFFLE_SUBTREE:
-                    request = truffleSubtreeCommand.createRequest(clientContext, NULL_ARGS);
-                    break;
-                default:
-                    request = new REPLMessage();
-                    request.put(REPLMessage.OP, op);
-            }
-            if (request == null) {
-                return null;
-            }
-            final REPLMessage[] replies = sendToServer(request);
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                return null;
-            }
-            return replies[0].get(REPLMessage.DISPLAY_MSG);
-        }
-
-        public void selectFrameNumber(int frameNumber) {
-            this.selectedFrameNumber = frameNumber;
-        }
-
-        void displayWhere() {
-            if (level == 0) {
-                displayFailReply("no active execution");
-                return;
-            }
-
-            Source whereSource = null;
-            int whereLineNumber = 0;
-
-            if (selectedFrameNumber == 0) {
-                whereSource = haltedSource;
-                whereLineNumber = haltedLineNumber;
-            } else {
-                final REPLFrame frame = frames().get(selectedFrameNumber);
-                final String locationFileName = frame.locationFilePath();
-                if (locationFileName != null) {
-                    try {
-                        whereSource = Source.fromFileName(locationFileName);
-                    } catch (IOException e) {
-                    }
-                }
-                whereLineNumber = frame.locationLineNumber();
-            }
-            if (whereSource == null) {
-                displayFailReply("Frame " + selectedFrameNumber + ": source unavailable");
-                return;
-            }
-            final int listSize = listSizeOption.getInt();
-
-            final int fileLineCount = whereSource.getLineCount();
-            final String code = whereSource.getCode();
-
-            writer.println("Frame " + selectedFrameNumber + ": " + whereSource.getShortName() + "\n");
-            final int halfListSize = listSize / 2;
-            final int startLineNumber = Math.max(1, whereLineNumber - halfListSize);
-            final int lastLineNumber = Math.min(startLineNumber + listSize - 1, fileLineCount);
-            for (int line = startLineNumber; line <= lastLineNumber; line++) {
-                final int offset = whereSource.getLineStartOffset(line);
-                final String lineText = code.substring(offset, offset + whereSource.getLineLength(line));
-                if (line == whereLineNumber) {
-                    writer.format(CODE_LINE_BREAK_FORMAT, line, lineText);
-                } else {
-                    writer.format(CODE_LINE_FORMAT, line, lineText);
-                }
-            }
-        }
-
-        public void displayStack() {
-            final List<REPLFrame> frameList = frames();
-            if (frameList == null) {
-                writer.println("<empty stack>");
-            } else {
-                for (REPLFrame frame : frameList) {
-                    String sourceLineText = frame.sourceLineText();
-                    if (sourceLineText == null) {
-                        sourceLineText = "<??>";
-                    }
-                    if (frame.index() == selectedFrameNumber) {
-                        writer.format(STACK_FRAME_SELECTED_FORMAT, frame.index(), frame.locationDescription(), frame.name(), sourceLineText);
-                    } else {
-                        writer.format(STACK_FRAME_FORMAT, frame.index(), frame.locationDescription(), frame.name(), sourceLineText);
-                    }
-                }
-            }
-        }
-
-        public void displayInfo(String message) {
-            writer.format(INFO_LINE_FORMAT, message);
-        }
-
-        public void displayReply(String message) {
-            writer.println(REPLY_PREFIX + message);
-        }
-
-        public void displayFailReply(String message) {
-            writer.println(FAIL_PREFIX + message);
-        }
-
-        public void displayWarnings(String warnings) {
-            for (String warning : warnings.split("\\n")) {
-                writer.println(WARNING_PREFIX + warning);
-            }
-        }
-
-        public void traceMessage(String message) {
-            writer.println(TRACE_PREFIX + message);
-        }
-
-        public void startSession() {
-
-            while (true) {
-                try {
-                    String[] args;
-                    String line = reader.readLine(currentPrompt).trim();
-                    if (line.startsWith("eval ")) {
-                        args = new String[]{"eval", line.substring(5)};
-                    } else {
-                        args = line.split("[ \t]+");
-                    }
-                    if (args.length == 0) {
-                        break;
-                    }
-                    final String cmd = args[0];
-
-                    if (cmd.isEmpty()) {
-                        continue;
-                    }
-
-                    REPLCommand command = commandMap.get(cmd);
-                    while (command instanceof REPLIndirectCommand) {
-                        if (traceMessagesOption.getBool()) {
-                            traceMessage("Executing indirect: " + command.getCommand());
-                        }
-                        command = ((REPLIndirectCommand) command).getCommand(args);
-                    }
-                    if (command == null) {
-                        clientContext.displayFailReply("Unrecognized command \"" + cmd + "\"");
-                        continue;
-                    }
-                    if (command instanceof REPLLocalCommand) {
-                        if (traceMessagesOption.getBool()) {
-                            traceMessage("Executing local: " + command.getCommand());
-                        }
-                        ((REPLLocalCommand) command).execute(args);
-
-                    } else if (command instanceof REPLRemoteCommand) {
-                        final REPLRemoteCommand remoteCommand = (REPLRemoteCommand) command;
-
-                        final REPLMessage request = remoteCommand.createRequest(clientContext, args);
-                        if (request == null) {
-                            continue;
-                        }
-
-                        REPLMessage[] replies = sendToServer(request);
-
-                        remoteCommand.processReply(clientContext, replies);
-                    } else {
-                        assert false; // Should not happen.
-                    }
-
-                } catch (REPLContinueException ex) {
-                    break;
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
-
-        }
-
-        private REPLMessage[] sendToServer(REPLMessage request) {
-            if (traceMessagesOption.getBool()) {
-                clientContext.traceMessage("Sever request:");
-                request.print(writer, "  ");
-            }
-
-            REPLMessage[] replies = replServer.receive(request);
-
-            assert replies != null && replies.length > 0;
-            if (traceMessagesOption.getBool()) {
-                if (replies.length > 1) {
-                    clientContext.traceMessage("Received " + replies.length + " server replies");
-                    int replyCount = 0;
-                    for (REPLMessage reply : replies) {
-                        clientContext.traceMessage("Server Reply " + replyCount++ + ":");
-                        reply.print(writer, "  ");
-                    }
-                } else {
-                    clientContext.traceMessage("Received reply:");
-                    replies[0].print(writer, "  ");
-                }
-            }
-            return replies;
-        }
-
-        private final class REPLFrameImpl implements REPLFrame {
-
-            private final int index;
-            private final String locationFilePath;
-            private final Integer locationLineNumber;
-            private final String locationDescription;
-            private final String name;
-            private final String sourceLineText;
-
-            REPLFrameImpl(int index, String locationFilePath, Integer locationLineNumber, String locationDescription, String name, String sourceLineText) {
-                this.index = index;
-                this.locationFilePath = locationFilePath;
-                this.locationLineNumber = locationLineNumber;
-                this.locationDescription = locationDescription;
-                this.name = name;
-                this.sourceLineText = sourceLineText;
-            }
-
-            public int index() {
-                return index;
-            }
-
-            public String locationFilePath() {
-                return locationFilePath;
-            }
-
-            public Integer locationLineNumber() {
-                return locationLineNumber;
-            }
-
-            public String locationDescription() {
-                return locationDescription;
-            }
-
-            public String name() {
-                return name;
-            }
-
-            public String sourceLineText() {
-                return sourceLineText;
-            }
-
-        }
-
-    }
-
-    // Cheating with synchrony: asynchronous replies should arrive here, but don't.
-    @Override
-    public REPLMessage receive(REPLMessage request) {
-        final String result = request.get("result");
-        clientContext.displayReply(result != null ? result : request.toString());
-        return null;
-    }
-
-    /**
-     * Cheating with synchrony: take a direct call from the server that execution has halted and
-     * we've entered a nested debugging context.
-     */
-    public void halted(REPLMessage message) {
-
-        // Push a new context for where we've stopped.
-        clientContext = new ClientContextImpl(clientContext, message);
-        final String warnings = message.get(REPLMessage.WARNINGS);
-        if (warnings != null) {
-            clientContext.displayWarnings(warnings);
-        }
-        if (autoWhereOption.getBool()) {
-            clientContext.displayWhere();
-        }
-        if (autoNodeOption.getBool()) {
-            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_NODE);
-            if (result != null) {
-                displayTruffleNode(result);
-            }
-        }
-        if (autoASTOption.getBool()) {
-            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_AST);
-            if (result != null) {
-                displayTruffleAST(result);
-            }
-        }
-        if (autoSubtreeOption.getBool()) {
-            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_SUBTREE);
-            if (result != null) {
-                displayTruffleSubtree(result);
-            }
-        }
-
-        try {
-            clientContext.startSession();
-        } finally {
-
-            // To continue execution, pop the context and return
-            this.clientContext = clientContext.predecessor;
-        }
-    }
-
-    /**
-     * A command that can be executed without (direct) communication with the server; it may rely on
-     * some other method that goes to the server for information.
-     */
-    private abstract class REPLLocalCommand extends REPLCommand {
-
-        public REPLLocalCommand(String command, String abbreviation, String description) {
-            super(command, abbreviation, description);
-        }
-
-        abstract void execute(String[] args);
-    }
-
-    /**
-     * A command that redirects to other commands, based on arguments.
-     */
-    private abstract class REPLIndirectCommand extends REPLCommand {
-
-        public REPLIndirectCommand(String command, String abbreviation, String description) {
-            super(command, abbreviation, description);
-        }
-
-        abstract void addCommand(REPLCommand command);
-
-        abstract REPLCommand getCommand(String[] args);
-    }
-
-    private final REPLCommand backtraceCommand = new REPLLocalCommand("backtrace", "bt", "Display current stack") {
-
-        @Override
-        void execute(String[] args) {
-            if (clientContext.level == 0) {
-                clientContext.displayFailReply("no active execution");
-            } else {
-                clientContext.displayStack();
-            }
-        }
-    };
-
-    private final REPLCommand evalCommand = new REPLRemoteCommand("eval", null, "Evaluate a string, in context of the current frame if any") {
-
-        private int evalCounter = 0;
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length > 1) {
-                final String code = args[1];
-                if (!code.isEmpty()) {
-                    // Create a fake entry in the file maps and cache, based on this unique name
-                    final String fakeFileName = "<eval" + ++evalCounter + ">";
-                    Source.fromNamedText(fakeFileName, code);
-                    final REPLMessage request = new REPLMessage();
-                    request.put(REPLMessage.OP, REPLMessage.EVAL);
-                    request.put(REPLMessage.CODE, code);
-                    request.put(REPLMessage.SOURCE_NAME, fakeFileName);
-                    if (clientContext.level > 0) {
-                        // Specify a requested execution context, if one exists; otherwise top level
-                        request.put(REPLMessage.FRAME_NUMBER, Integer.toString(context.getSelectedFrameNumber()));
-                    }
-                    return request;
-                }
-            }
-            return null;
-        }
-    };
-
-    private final REPLCommand fileCommand = new REPLRemoteCommand("file", null, "Set/display current file for viewing") {
-
-        final String[] help = {"file:  display current file path", "file <filename>: Set file to be current file for viewing"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (args.length == 1) {
-                final Source source = clientContext.getSelectedSource();
-                if (source == null) {
-                    clientContext.displayFailReply("no file currently selected");
-                } else {
-                    clientContext.displayReply(source.getPath());
-                }
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.FILE);
-            request.put(REPLMessage.SOURCE_NAME, args[1]);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            REPLMessage firstReply = replies[0];
-
-            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
-                clientContext.displayFailReply(result != null ? result : firstReply.toString());
-                return;
-            }
-            final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
-            final String path = firstReply.get(REPLMessage.FILE_PATH);
-            clientContext.selectSource(path == null ? fileName : path);
-            clientContext.displayReply(clientContext.getSelectedSource().getPath());
-
-            for (int i = 1; i < replies.length; i++) {
-                REPLMessage reply = replies[i];
-                final String result = reply.get(REPLMessage.DISPLAY_MSG);
-                clientContext.displayInfo(result != null ? result : reply.toString());
-            }
-        }
-
-    };
-
-    private final REPLCommand helpCommand = new REPLLocalCommand("help", null, "Describe commands") {
-
-        final String[] help = {"help:  list available commands", "help <command>: additional information about <command>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public void execute(String[] args) {
-
-            if (args.length == 1) {
-                clientContext.displayReply("Available commands:");
-                for (String commandName : commandNames) {
-                    final REPLCommand command = commandMap.get(commandName);
-                    if (command == null) {
-                        clientContext.displayInfo(commandName + ": Error, no implementation for command");
-                    } else {
-                        final String abbrev = command.getAbbreviation();
-                        if (abbrev == null) {
-                            clientContext.displayInfo(commandName + ": " + command.getDescription());
-                        } else {
-                            clientContext.displayInfo(commandName + "(" + abbrev + "): " + command.getDescription());
-                        }
-                    }
-                }
-            } else {
-                final String cmdName = args[1];
-                final REPLCommand cmd = commandMap.get(cmdName);
-                if (cmd == null) {
-                    clientContext.displayReply("command \"" + cmdName + "\" not recognized");
-                } else {
-                    final String[] helpLines = cmd.getHelp();
-                    if (helpLines == null) {
-                        clientContext.displayReply("\"" + cmdName + "\":");
-                    } else if (helpLines.length == 1) {
-                        clientContext.displayInfo(helpLines[0]);
-                    } else {
-                        clientContext.displayReply("\"" + cmdName + "\":");
-                        for (String line : helpLines) {
-                            clientContext.displayInfo(line);
-                        }
-                    }
-                }
-            }
-        }
-    };
-
-    private final REPLIndirectCommand infoCommand = new REPLIndirectCommand(REPLMessage.INFO, null, "Additional information on topics") {
-
-        // "Info" commands
-        private final Map<String, REPLCommand> infoCommandMap = new HashMap<>();
-        private final Collection<String> infoCommandNames = new TreeSet<>();
-
-        @Override
-        public String[] getHelp() {
-            final ArrayList<String> lines = new ArrayList<>();
-            for (String infoCommandName : infoCommandNames) {
-                final REPLCommand cmd = infoCommandMap.get(infoCommandName);
-                if (cmd == null) {
-                    lines.add("\"" + REPLMessage.INFO + " " + infoCommandName + "\" not implemented");
-                } else {
-                    lines.add("\"" + REPLMessage.INFO + " " + infoCommandName + "\": " + cmd.getDescription());
-                }
-            }
-            return lines.toArray(new String[0]);
-        }
-
-        @Override
-        void addCommand(REPLCommand replCommand) {
-            final String commandName = replCommand.getCommand();
-            final String abbreviation = replCommand.getAbbreviation();
-
-            infoCommandNames.add(commandName);
-            infoCommandMap.put(commandName, replCommand);
-            if (abbreviation != null) {
-                infoCommandMap.put(abbreviation, replCommand);
-            }
-        }
-
-        @Override
-        REPLCommand getCommand(String[] args) {
-            if (args.length == 1) {
-                clientContext.displayFailReply("info topic not specified; try \"help info\"");
-                return null;
-            }
-            final String topic = args[1];
-            REPLCommand command = infoCommandMap.get(topic);
-            if (command == null) {
-                clientContext.displayFailReply("topic \"" + topic + "\" not recognized");
-                return null;
-            }
-
-            return command;
-        }
-
-    };
-
-    private final REPLCommand infoBreakCommand = new REPLRemoteCommand("breakpoint", "break", "info about breakpoints") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.BREAKPOINT_INFO);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                Arrays.sort(replies, new Comparator<REPLMessage>() {
-
-                    public int compare(REPLMessage o1, REPLMessage o2) {
-                        try {
-                            final int n1 = Integer.parseInt(o1.get(REPLMessage.BREAKPOINT_ID));
-                            final int n2 = Integer.parseInt(o2.get(REPLMessage.BREAKPOINT_ID));
-                            return Integer.compare(n1, n2);
-                        } catch (Exception ex) {
-                        }
-                        return 0;
-                    }
-
-                });
-                clientContext.displayReply("Breakpoints set:");
-                for (REPLMessage message : replies) {
-                    final StringBuilder sb = new StringBuilder();
-
-                    sb.append(Integer.parseInt(message.get(REPLMessage.BREAKPOINT_ID)) + ": ");
-                    sb.append("@" + message.get(REPLMessage.INFO_VALUE));
-                    sb.append(" (state=" + message.get(REPLMessage.BREAKPOINT_STATE));
-                    if (verboseBreakpointInfoOption.getBool()) {
-                        sb.append(", group=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_GROUP_ID)));
-                        sb.append(", hits=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_HIT_COUNT)));
-                        sb.append(", ignore=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_IGNORE_COUNT)));
-                    }
-                    final String condition = message.get(REPLMessage.BREAKPOINT_CONDITION);
-                    if (condition != null) {
-                        sb.append(", condition=\"" + condition + "\"");
-                    }
-                    sb.append(")");
-                    clientContext.displayInfo(sb.toString());
-                }
-            }
-        }
-    };
-
-    private final REPLCommand infoLanguageCommand = new REPLRemoteCommand("language", "lang", "language and implementation details") {
-
-        final String[] help = {"info language:  list details about the language implementation"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.INFO);
-            request.put(REPLMessage.TOPIC, REPLMessage.LANGUAGE);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                clientContext.displayReply("Language info:");
-                for (REPLMessage message : replies) {
-                    final StringBuilder sb = new StringBuilder();
-                    sb.append(message.get(REPLMessage.INFO_KEY));
-                    sb.append(": ");
-                    sb.append(message.get(REPLMessage.INFO_VALUE));
-                    clientContext.displayInfo(sb.toString());
-                }
-            }
-        }
-    };
-
-    private final REPLCommand infoSetCommand = new REPLLocalCommand("set", null, "info about settings") {
-
-        final String[] help = {"info sets:  list local options that can be set"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public void execute(String[] args) {
-
-            clientContext.displayReply("Settable options:");
-
-            for (String optionName : optionNames) {
-                final LocalOption localOption = localOptions.get(optionName);
-                if (localOption == null) {
-                    clientContext.displayInfo(localOption + ": Error, no implementation for option");
-                } else {
-                    clientContext.displayInfo(optionName + "=" + localOption.getValue() + ": " + localOption.getDescription());
-                }
-            }
-        }
-    };
-
-    private final REPLCommand listCommand = new REPLLocalCommand("list", null, "Display selected source file") {
-
-        final String[] help = {"list:  list <listsize> lines of selected file (see option \"listsize\")", "list all: list all lines", "list <n>: list <listsize> lines centered around line <n>"};
-
-        private Source lastListedSource = null;
-
-        private int nextLineToList = 1;
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public void execute(String[] args) {
-            final Source source = clientContext.getSelectedSource();
-            if (source == null) {
-                clientContext.displayFailReply("No selected file");
-                reset();
-                return;
-            }
-            final int listSize = listSizeOption.getInt();
-
-            if (args.length == 1) {
-                if (!source.equals(lastListedSource)) {
-                    reset();
-                } else if (nextLineToList > source.getLineCount()) {
-                    reset();
-                }
-                final int lastListedLine = printLines(source, nextLineToList, listSize);
-                lastListedSource = source;
-                nextLineToList = lastListedLine > source.getLineCount() ? 1 : lastListedLine + 1;
-            } else if (args.length == 2) {
-                reset();
-                if (args[1].equals("all")) {
-                    printLines(source, 1, source.getLineCount());
-                } else {
-                    try {
-                        final int line = Integer.parseInt(args[1]);
-                        final int halfListSize = listSize / 2;
-                        final int start = Math.max(1, line - halfListSize);
-                        final int count = Math.min(source.getLineCount() + 1 - start, listSize);
-                        printLines(source, start, count);
-                    } catch (NumberFormatException e) {
-                        clientContext.displayFailReply("\"" + args[1] + "\" not recognized");
-                    }
-
-                }
-            }
-        }
-
-        private int printLines(Source printSource, int start, int listSize) {
-
-            clientContext.displayReply(printSource.getShortName() + ":");
-            final int lastLineNumber = Math.min(start + listSize - 1, printSource.getLineCount());
-            for (int line = start; line <= lastLineNumber; line++) {
-                writer.format(CODE_LINE_FORMAT, line, printSource.getCode(line));
-            }
-            return lastLineNumber;
-        }
-
-        /**
-         * Forget where we were in a sequence of list commands with no arguments
-         */
-        private void reset() {
-            lastListedSource = clientContext.getSelectedSource();
-            nextLineToList = 1;
-        }
-    };
-
-    private final REPLCommand quitCommand = new REPLRemoteCommand("quit", "q", "Quit execution and REPL") {
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.QUIT);
-            return request;
-        }
-
-    };
-
-    private final REPLCommand setCommand = new REPLLocalCommand("set", null, "set <option>=<value>") {
-
-        @Override
-        public String[] getHelp() {
-            return new String[]{"Sets an option \"set <option-name>=<value>\";  see also \"info set\""};
-        }
-
-        @Override
-        public void execute(String[] args) {
-            REPLMessage request = null;
-            if (args.length == 1) {
-                clientContext.displayFailReply("No option specified, try \"help set\"");
-            } else if (args.length == 2) {
-                String[] split = new String[0];
-                try {
-                    split = args[1].split("=");
-                } catch (Exception ex) {
-                }
-                if (split.length == 0) {
-                    clientContext.displayFailReply("Arguments not understood, try \"help set\"");
-                } else if (split.length == 1) {
-                    clientContext.displayFailReply("No option value specified, try \"help set\"");
-                } else if (split.length > 2) {
-                    clientContext.displayFailReply("Arguments not understood, try \"help set\"");
-                } else {
-                    final String optionName = split[0];
-                    final String newValue = split[1];
-                    final LocalOption localOption = localOptions.get(optionName);
-                    if (localOption != null) {
-                        if (!localOption.setValue(newValue)) {
-                            clientContext.displayFailReply("Invalid option value \"" + newValue + "\"");
-                        }
-                        clientContext.displayInfo(localOption.name + " = " + localOption.getValue());
-                    } else {
-                        request = new REPLMessage();
-                        request.put(REPLMessage.OP, REPLMessage.SET);
-                        request.put(REPLMessage.OPTION, optionName);
-                        request.put(REPLMessage.VALUE, newValue);
-                    }
-                }
-            } else {
-                clientContext.displayFailReply("Arguments not understood, try \"help set\"");
-            }
-        }
-    };
-
-    private final REPLIndirectCommand truffleCommand = new REPLIndirectCommand(REPLMessage.TRUFFLE, "t", "Access to Truffle internals") {
-
-        // "Truffle" commands
-        private final Map<String, REPLCommand> truffleCommandMap = new HashMap<>();
-        private final Collection<String> truffleCommandNames = new TreeSet<>();
-
-        @Override
-        public String[] getHelp() {
-            final ArrayList<String> lines = new ArrayList<>();
-            for (String truffleCommandName : truffleCommandNames) {
-                final REPLCommand cmd = truffleCommandMap.get(truffleCommandName);
-                if (cmd == null) {
-                    lines.add("\"" + REPLMessage.TRUFFLE + " " + truffleCommandName + "\" not implemented");
-                } else {
-                    for (String line : cmd.getHelp()) {
-                        lines.add(line);
-                    }
-                }
-            }
-            return lines.toArray(new String[0]);
-        }
-
-        @Override
-        void addCommand(REPLCommand replCommand) {
-            final String commandName = replCommand.getCommand();
-            final String abbreviation = replCommand.getAbbreviation();
-
-            truffleCommandNames.add(commandName);
-            truffleCommandMap.put(commandName, replCommand);
-            if (abbreviation != null) {
-                truffleCommandMap.put(abbreviation, replCommand);
-            }
-        }
-
-        @Override
-        REPLCommand getCommand(String[] args) {
-            if (args.length == 1) {
-                clientContext.displayFailReply("truffle request not specified; try \"help truffle\"");
-                return null;
-            }
-            final String topic = args[1];
-            REPLCommand command = truffleCommandMap.get(topic);
-            if (command == null) {
-                clientContext.displayFailReply("truffle request \"" + topic + "\" not recognized");
-                return null;
-            }
-            return command;
-        }
-    };
-
-    private final REPLRemoteCommand truffleASTCommand = new REPLRemoteCommand("ast", null, "print the AST that contains the current node") {
-
-        final String[] help = {"truffle ast:  print the AST subtree that contains current node (see \"set treedepth\")",
-                        "truffle ast <n>:  print the AST subtree that contains current node to a maximum depth of <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (clientContext.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.TRUFFLE);
-            request.put(REPLMessage.TOPIC, REPLMessage.AST);
-
-            int astDepth = astDepthOption.getInt();
-            if (args.length > 2) {
-                final String depthText = args[2];
-                try {
-                    astDepth = Integer.parseInt(depthText);
-                } catch (NumberFormatException e) {
-                }
-            }
-            request.put(REPLMessage.AST_DEPTH, Integer.toString(astDepth));
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                clientContext.displayReply("AST containing the Current Node:");
-                for (REPLMessage message : replies) {
-                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
-                        clientContext.displayInfo(line);
-                    }
-                }
-            }
-        }
-    };
-
-    private void displayTruffleAST(String text) {
-        clientContext.displayReply("AST containing Current Node:");
-        for (String line : text.split("\n")) {
-            clientContext.displayInfo(line);
-        }
-    }
-
-    private final REPLRemoteCommand truffleNodeCommand = new REPLRemoteCommand("node", null, "describe current AST node") {
-
-        final String[] help = {"truffle node:  describe the AST node at the current execution context"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (clientContext.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.TRUFFLE_NODE);
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                displayTruffleNode(replies[0].get(REPLMessage.DISPLAY_MSG));
-            }
-        }
-    };
-
-    private void displayTruffleNode(String nodeString) {
-        clientContext.displayReply("Current Node: " + nodeString);
-    }
-
-    private final REPLRemoteCommand truffleSubtreeCommand = new REPLRemoteCommand("subtree", "sub", "print the AST subtree rooted at the current node") {
-
-        final String[] help = {"truffle sub:  print the AST subtree at the current node (see \"set treedepth\")", "truffle sub <n>:  print the AST subtree at the current node to maximum depth <n>",
-                        "truffle subtree:   print the AST subtree at the current node (see \"set treedepth\")", "truffle sub <n>:  print the AST subtree at the current node to maximum depth <n>"};
-
-        @Override
-        public String[] getHelp() {
-            return help;
-        }
-
-        @Override
-        public REPLMessage createRequest(REPLClientContext context, String[] args) {
-            if (clientContext.level() == 0) {
-                context.displayFailReply("no active execution");
-                return null;
-            }
-
-            final REPLMessage request = new REPLMessage();
-            request.put(REPLMessage.OP, REPLMessage.TRUFFLE);
-            request.put(REPLMessage.TOPIC, REPLMessage.SUBTREE);
-
-            int astDepth = astDepthOption.getInt();
-            if (args.length > 2) {
-                final String depthText = args[2];
-                try {
-                    astDepth = Integer.parseInt(depthText);
-                } catch (NumberFormatException e) {
-                }
-            }
-            request.put(REPLMessage.AST_DEPTH, Integer.toString(astDepth));
-            return request;
-        }
-
-        @Override
-        void processReply(REPLClientContext context, REPLMessage[] replies) {
-            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
-                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
-            } else {
-                clientContext.displayReply("AST subtree at Current Node:");
-                for (REPLMessage message : replies) {
-                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
-                        clientContext.displayInfo(line);
-                    }
-                }
-            }
-        }
-    };
-
-    private void displayTruffleSubtree(String text) {
-        clientContext.displayReply("AST subtree at Current Node:");
-        for (String line : text.split("\n")) {
-            clientContext.displayInfo(line);
-        }
-    }
-
-    private final REPLCommand whereCommand = new REPLLocalCommand("where", null, "Show code around current break location") {
-
-        @Override
-        public void execute(String[] args) {
-            clientContext.displayWhere();
-        }
-    };
-
-    private abstract static class LocalOption {
-        private final String name;
-        private final String description;
-
-        protected LocalOption(String name, String description) {
-            this.name = name;
-            this.description = description;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-
-        public abstract boolean setValue(String newValue);
-
-        public boolean getBool() {
-            assert false;
-            return false;
-        }
-
-        public int getInt() {
-            assert false;
-            return 0;
-        }
-
-        public abstract String getValue();
-    }
-
-    private static final class BooleanOption extends LocalOption {
-
-        private Boolean value;
-
-        public BooleanOption(boolean value, String name, String description) {
-            super(name, description);
-            this.value = value;
-        }
-
-        @Override
-        public boolean setValue(String newValue) {
-            final Boolean valueOf = Boolean.valueOf(newValue);
-            if (valueOf == null) {
-                return false;
-            }
-            value = valueOf;
-            return true;
-        }
-
-        @Override
-        public boolean getBool() {
-            return value;
-        }
-
-        @Override
-        public String getValue() {
-            return value.toString();
-        }
-    }
-
-    private static final class IntegerOption extends LocalOption {
-
-        private Integer value;
-
-        public IntegerOption(int value, String name, String description) {
-            super(name, description);
-            this.value = value;
-        }
-
-        @Override
-        public boolean setValue(String newValue) {
-            Integer valueOf;
-            try {
-                valueOf = Integer.valueOf(newValue);
-            } catch (NumberFormatException e) {
-                return false;
-            }
-            value = valueOf;
-            return true;
-        }
-
-        @Override
-        public int getInt() {
-            return value;
-        }
-
-        @Override
-        public String getValue() {
-            return value.toString();
-        }
-
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/package-info.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * This package contains an experimental framework for building simple command-line oriented debuggers
- * that work with Truffle-implemented languages; it is used mainly for testing Truffle's built-in
- * {@link com.oracle.truffle.tools.debug.engine.DebugEngine}, which actually provides the debugging services.
- * <p>
- * Truffle debugging is made possible by the general purpose Instrumentation Framework built
- * into the Truffle platform.  Some online documentation for the Instrumentation Framework is available
- * online:
- * <quote>
- * <a href="https://wiki.openjdk.java.net/display/Graal/Instrumentation+API">https://wiki.openjdk.java.net/display/Graal/Instrumentation+API</a>
- * </quote>
- * <p>
- * Building one of these command line debuggers requires creating language-specific instances of:
- * <ol>
- * <li>{@link com.oracle.truffle.tools.debug.engine.DebugEngine},
- * noting that this instance also depends on related services provided by the language implementation,</li>
- * <li>{@link com.oracle.truffle.tools.debug.shell.REPLServer}, best accomplished by copying the implementation for
- * Truffle's demonstration language "Simple" (a.k.a. "SL").</li>
- * </ol>
- *
- * <strong>Disclaimer: </strong> although these command line debuggers are useful, they are
- * not intended, and will not be maintained as, fully functioning debuggers.  They should be
- * considered valuable tools for the maintainers of the {@link com.oracle.truffle.tools.debug.engine.DebugEngine},
- * as well as for Truffle language implementors for whom concurrent access to any kind debugging services can
- * be quite helpful.
- * <p>
- * <strong>Note:</strong> Both the functionality and API for this package are under active development.
- * <p>
- * @see com.oracle.truffle.api.instrument
- * @see com.oracle.truffle.tools.debug.engine
- */
-package com.oracle.truffle.tools.debug.shell;
-
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,601 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.server;
-
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-import com.oracle.truffle.tools.debug.engine.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-/**
- * Server-side REPL implementation of an {@linkplain REPLMessage "op"}.
- * <p>
- * The language-agnostic handlers are implemented here.
- */
-public abstract class REPLHandler {
-
-    // TODO (mlvdv) add support for setting/using ignore count
-    private static final int DEFAULT_IGNORE_COUNT = 0;
-
-    // TODO (mlvdv) add support for setting/using groupId
-    private static final int DEFAULT_GROUP_ID = 0;
-
-    private final String op;
-
-    protected REPLHandler(String op) {
-        this.op = op;
-    }
-
-    /**
-     * Gets the "op" implemented by this handler.
-     */
-    public final String getOp() {
-        return op;
-    }
-
-    /**
-     * Passes a request to this handler.
-     */
-    public abstract REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext);
-
-    /**
-     * Creates skeleton for a reply message that identifies the operation currently being handled.
-     */
-    protected final REPLMessage createReply() {
-        return new REPLMessage(REPLMessage.OP, op);
-    }
-
-    /**
-     * Creates skeleton for a reply message that identifies a specified operation.
-     */
-    protected static final REPLMessage createReply(String opString) {
-        return new REPLMessage(REPLMessage.OP, opString);
-    }
-
-    /**
-     * Completes a reply, reporting and explaining successful handling.
-     */
-    protected static final REPLMessage[] finishReplySucceeded(REPLMessage reply, String explanation) {
-        reply.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-        reply.put(REPLMessage.DISPLAY_MSG, explanation);
-        final REPLMessage[] replies = new REPLMessage[]{reply};
-        return replies;
-    }
-
-    /**
-     * Completes a reply, reporting and explaining failed handling.
-     */
-    protected static final REPLMessage[] finishReplyFailed(REPLMessage reply, String explanation) {
-        reply.put(REPLMessage.STATUS, REPLMessage.FAILED);
-        reply.put(REPLMessage.DISPLAY_MSG, explanation);
-        final REPLMessage[] replies = new REPLMessage[]{reply};
-        return replies;
-    }
-
-    protected static REPLMessage createBreakpointInfoMessage(Breakpoint breakpoint) {
-        final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.BREAKPOINT_INFO);
-        infoMessage.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpoint.getId()));
-        infoMessage.put(REPLMessage.BREAKPOINT_GROUP_ID, Integer.toString(breakpoint.getGroupId()));
-        infoMessage.put(REPLMessage.BREAKPOINT_STATE, breakpoint.getState().toString());
-        infoMessage.put(REPLMessage.BREAKPOINT_HIT_COUNT, Integer.toString(breakpoint.getHitCount()));
-        infoMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(breakpoint.getIgnoreCount()));
-        infoMessage.put(REPLMessage.INFO_VALUE, breakpoint.getLocationDescription().toString());
-        if (breakpoint.getCondition() != null) {
-            infoMessage.put(REPLMessage.BREAKPOINT_CONDITION, breakpoint.getCondition());
-        }
-        infoMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-        return infoMessage;
-    }
-
-    protected static REPLMessage createFrameInfoMessage(final REPLServerContext serverContext, FrameDebugDescription frame) {
-        final Visualizer visualizer = serverContext.getLanguage().getDebugSupport().getVisualizer();
-        final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.FRAME_INFO);
-        infoMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(frame.index()));
-        final Node node = frame.node();
-
-        infoMessage.put(REPLMessage.SOURCE_LOCATION, visualizer.displaySourceLocation(node));
-        infoMessage.put(REPLMessage.METHOD_NAME, visualizer.displayMethodName(node));
-
-        if (node != null) {
-            SourceSection section = node.getSourceSection();
-            if (section == null) {
-                section = node.getEncapsulatingSourceSection();
-                if (section != null) {
-                    infoMessage.put(REPLMessage.FILE_PATH, section.getSource().getPath());
-                    infoMessage.put(REPLMessage.LINE_NUMBER, Integer.toString(section.getStartLine()));
-                    infoMessage.put(REPLMessage.SOURCE_LINE_TEXT, section.getSource().getCode(section.getStartLine()));
-                }
-            }
-        }
-        infoMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
-        return infoMessage;
-    }
-
-    public static final REPLHandler BACKTRACE_HANDLER = new REPLHandler(REPLMessage.BACKTRACE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final ArrayList<REPLMessage> frameMessages = new ArrayList<>();
-            for (FrameDebugDescription frame : serverContext.getDebugEngine().getStack()) {
-                frameMessages.add(createFrameInfoMessage(serverContext, frame));
-            }
-            if (frameMessages.size() > 0) {
-                return frameMessages.toArray(new REPLMessage[0]);
-            }
-            return finishReplyFailed(reply, "No stack");
-        }
-    };
-
-    public static final REPLHandler BREAK_AT_LINE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_LINE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final String path = request.get(REPLMessage.FILE_PATH);
-            final String fileName = request.get(REPLMessage.SOURCE_NAME);
-            final String lookupFile = (path == null || path.isEmpty()) ? fileName : path;
-            Source source = null;
-            try {
-                source = Source.fromFileName(lookupFile, true);
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-            if (source == null) {
-                return finishReplyFailed(reply, fileName + " not found");
-            }
-            Integer lineNumber = request.getIntValue(REPLMessage.LINE_NUMBER);
-            if (lineNumber == null) {
-                return finishReplyFailed(reply, "missing line number");
-            }
-            Integer ignoreCount = request.getIntValue(REPLMessage.BREAKPOINT_IGNORE_COUNT);
-            if (ignoreCount == null) {
-                ignoreCount = 0;
-            }
-            LineBreakpoint breakpoint;
-            try {
-                breakpoint = serverContext.getDebugEngine().setLineBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, source.createLineLocation(lineNumber), false);
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-            reply.put(REPLMessage.SOURCE_NAME, fileName);
-            reply.put(REPLMessage.FILE_PATH, source.getPath());
-            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpoint.getId()));
-            reply.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
-            reply.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, ignoreCount.toString());
-            return finishReplySucceeded(reply, "Breakpoint set");
-        }
-    };
-
-    public static final REPLHandler BREAK_AT_LINE_ONCE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_LINE_ONCE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final String path = request.get(REPLMessage.FILE_PATH);
-            final String fileName = request.get(REPLMessage.SOURCE_NAME);
-            final String lookupFile = (path == null || path.isEmpty()) ? fileName : path;
-            Source source = null;
-            try {
-                source = Source.fromFileName(lookupFile, true);
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-            if (source == null) {
-                return finishReplyFailed(reply, fileName + " not found");
-            }
-            Integer lineNumber = request.getIntValue(REPLMessage.LINE_NUMBER);
-            if (lineNumber == null) {
-                return finishReplyFailed(reply, "missing line number");
-            }
-            try {
-                serverContext.getDebugEngine().setLineBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, source.createLineLocation(lineNumber), true);
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-            reply.put(REPLMessage.SOURCE_NAME, fileName);
-            reply.put(REPLMessage.FILE_PATH, source.getPath());
-            reply.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
-            return finishReplySucceeded(reply, "One-shot line breakpoint set");
-        }
-    };
-
-    public static final REPLHandler BREAK_AT_THROW_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_THROW) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            try {
-                serverContext.getDebugEngine().setTagBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, StandardSyntaxTag.THROW, false);
-                return finishReplySucceeded(reply, "Breakpoint at any throw set");
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-        }
-    };
-
-    public static final REPLHandler BREAK_AT_THROW_ONCE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_THROW_ONCE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            try {
-                serverContext.getDebugEngine().setTagBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, StandardSyntaxTag.THROW, true);
-                return finishReplySucceeded(reply, "One-shot breakpoint at any throw set");
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.getMessage());
-            }
-        }
-    };
-
-    public static final REPLHandler BREAKPOINT_INFO_HANDLER = new REPLHandler(REPLMessage.BREAKPOINT_INFO) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final ArrayList<REPLMessage> infoMessages = new ArrayList<>();
-            for (Breakpoint breakpoint : serverContext.getDebugEngine().getBreakpoints()) {
-                infoMessages.add(createBreakpointInfoMessage(breakpoint));
-            }
-            if (infoMessages.size() > 0) {
-                return infoMessages.toArray(new REPLMessage[0]);
-            }
-            return finishReplyFailed(reply, "No breakpoints");
-        }
-    };
-
-    public static final REPLHandler CLEAR_BREAK_HANDLER = new REPLHandler(REPLMessage.CLEAR_BREAK) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
-            if (breakpointNumber == null) {
-                return finishReplyFailed(reply, "missing breakpoint number");
-            }
-            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
-            if (breakpoint == null) {
-                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
-            }
-            breakpoint.dispose();
-            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " cleared");
-        }
-    };
-
-    public static final REPLHandler CONTINUE_HANDLER = new REPLHandler(REPLMessage.CONTINUE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            serverContext.getDebugEngine().prepareContinue();
-            return finishReplySucceeded(reply, "Continue mode entered");
-        }
-    };
-
-    public static final REPLHandler DELETE_HANDLER = new REPLHandler(REPLMessage.DELETE_BREAK) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            int deleteCount = 0;
-            for (Breakpoint breakpoint : serverContext.getDebugEngine().getBreakpoints()) {
-                breakpoint.dispose();
-                deleteCount++;
-            }
-            if (deleteCount == 0) {
-                return finishReplyFailed(reply, "no breakpoints to delete");
-            }
-            return finishReplySucceeded(reply, Integer.toString(deleteCount) + " breakpoints deleted");
-        }
-    };
-
-    public static final REPLHandler DISABLE_BREAK_HANDLER = new REPLHandler(REPLMessage.DISABLE_BREAK) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
-            if (breakpointNumber == null) {
-                return finishReplyFailed(reply, "missing breakpoint number");
-            }
-            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
-            if (breakpoint == null) {
-                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
-            }
-            breakpoint.setEnabled(false);
-            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " disabled");
-        }
-    };
-
-    public static final REPLHandler ENABLE_BREAK_HANDLER = new REPLHandler(REPLMessage.ENABLE_BREAK) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
-            if (breakpointNumber == null) {
-                return finishReplyFailed(reply, "missing breakpoint number");
-            }
-            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
-            if (breakpoint == null) {
-                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
-            }
-            breakpoint.setEnabled(true);
-            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " enabled");
-        }
-    };
-
-    public static final REPLHandler FILE_HANDLER = new REPLHandler(REPLMessage.FILE) {
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final String fileName = request.get(REPLMessage.SOURCE_NAME);
-            if (fileName == null) {
-                return finishReplyFailed(reply, "no file specified");
-            }
-            try {
-                Source source = Source.fromFileName(fileName);
-                if (source == null) {
-                    reply.put(REPLMessage.SOURCE_NAME, fileName);
-                    return finishReplyFailed(reply, " not found");
-                } else {
-                    reply.put(REPLMessage.SOURCE_NAME, fileName);
-                    reply.put(REPLMessage.FILE_PATH, source.getPath());
-                    reply.put(REPLMessage.CODE, source.getCode());
-                    return finishReplySucceeded(reply, "file found");
-                }
-            } catch (Exception ex) {
-                reply.put(REPLMessage.SOURCE_NAME, fileName);
-                return finishReplyFailed(reply, "file \"" + fileName + "\" not found");
-            }
-        }
-    };
-
-    // TODO (mlvdv) deal with slot locals explicitly
-    /**
-     * Returns a general description of the frame, plus a textual summary of the slot values: one
-     * per line.
-     */
-    public static final REPLHandler FRAME_HANDLER = new REPLHandler(REPLMessage.FRAME) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final Integer frameNumber = request.getIntValue(REPLMessage.FRAME_NUMBER);
-            if (frameNumber == null) {
-                return finishReplyFailed(reply, "no frame number specified");
-            }
-            final List<FrameDebugDescription> stack = serverContext.getDebugEngine().getStack();
-            if (frameNumber < 0 || frameNumber >= stack.size()) {
-                return finishReplyFailed(reply, "frame number " + frameNumber + " out of range");
-            }
-            final FrameDebugDescription frameDescription = stack.get(frameNumber);
-            final REPLMessage frameMessage = createFrameInfoMessage(serverContext, frameDescription);
-            final Frame frame = frameDescription.frameInstance().getFrame(FrameInstance.FrameAccess.READ_ONLY, true);
-            final Language language = serverContext.getLanguage();
-            final Visualizer visualizer = language.getDebugSupport().getVisualizer();
-            final FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-            try {
-                final StringBuilder sb = new StringBuilder();
-                for (FrameSlot slot : frameDescriptor.getSlots()) {
-                    sb.append(Integer.toString(slot.getIndex()) + ": " + visualizer.displayIdentifier(slot) + " = ");
-                    try {
-                        final Object value = frame.getValue(slot);
-                        sb.append(visualizer.displayValue(value, 0));
-                    } catch (Exception ex) {
-                        sb.append("???");
-                    }
-                    sb.append("\n");
-                }
-                return finishReplySucceeded(frameMessage, sb.toString());
-            } catch (Exception ex) {
-                return finishReplyFailed(frameMessage, ex.toString());
-            }
-        }
-    };
-
-    public static final REPLHandler KILL_HANDLER = new REPLHandler(REPLMessage.KILL) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            if (serverContext.getLevel() == 0) {
-                return finishReplyFailed(createReply(), "nothing to kill");
-            }
-            throw new KillException();
-        }
-    };
-
-    public static final REPLHandler QUIT_HANDLER = new REPLHandler(REPLMessage.QUIT) {
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            throw new QuitException();
-        }
-    };
-
-    public static final REPLHandler SET_BREAK_CONDITION_HANDLER = new REPLHandler(REPLMessage.SET_BREAK_CONDITION) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.SET_BREAK_CONDITION);
-            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
-            if (breakpointNumber == null) {
-                return finishReplyFailed(message, "missing breakpoint number");
-            }
-            message.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
-            if (breakpoint == null) {
-                return finishReplyFailed(message, "no breakpoint number " + breakpointNumber);
-            }
-            final String expr = request.get(REPLMessage.BREAKPOINT_CONDITION);
-            if (expr == null || expr.isEmpty()) {
-                return finishReplyFailed(message, "missing condition for " + breakpointNumber);
-            }
-            try {
-                breakpoint.setCondition(expr);
-            } catch (DebugException ex) {
-                return finishReplyFailed(message, "invalid condition for " + breakpointNumber);
-            } catch (UnsupportedOperationException ex) {
-                return finishReplyFailed(message, "conditions not unsupported by breakpoint " + breakpointNumber);
-            }
-            message.put(REPLMessage.BREAKPOINT_CONDITION, expr);
-            return finishReplySucceeded(message, "Breakpoint " + breakpointNumber + " condition=\"" + expr + "\"");
-        }
-    };
-
-    public static final REPLHandler STEP_INTO_HANDLER = new REPLHandler(REPLMessage.STEP_INTO) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            Integer repeat = request.getIntValue(REPLMessage.REPEAT);
-            if (repeat == null) {
-                repeat = 1;
-            }
-            serverContext.getDebugEngine().prepareStepInto(repeat);
-            return finishReplySucceeded(reply, "StepInto <" + repeat + "> enabled");
-        }
-    };
-
-    public static final REPLHandler STEP_OUT_HANDLER = new REPLHandler(REPLMessage.STEP_OUT) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            serverContext.getDebugEngine().prepareStepOut();
-            return finishReplySucceeded(createReply(), "StepOut enabled");
-        }
-    };
-
-    public static final REPLHandler STEP_OVER_HANDLER = new REPLHandler(REPLMessage.STEP_OVER) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext debugServerContextFrame) {
-            final REPLMessage reply = createReply();
-            Integer repeat = request.getIntValue(REPLMessage.REPEAT);
-            if (repeat == null) {
-                repeat = 1;
-            }
-            debugServerContextFrame.getDebugEngine().prepareStepOver(repeat);
-            return finishReplySucceeded(reply, "StepOver <" + repeat + "> enabled");
-        }
-    };
-
-    public static final REPLHandler TRUFFLE_HANDLER = new REPLHandler(REPLMessage.TRUFFLE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter();
-            final String topic = request.get(REPLMessage.TOPIC);
-            reply.put(REPLMessage.TOPIC, topic);
-            Node node = serverContext.getNode();
-            if (node == null) {
-                return finishReplyFailed(reply, "no current AST node");
-            }
-            final Integer depth = request.getIntValue(REPLMessage.AST_DEPTH);
-            if (depth == null) {
-                return finishReplyFailed(reply, "missing AST depth");
-            }
-            try {
-                switch (topic) {
-                    case REPLMessage.AST:
-                        while (node.getParent() != null) {
-                            node = node.getParent();
-                        }
-                        final String astText = astPrinter.printTreeToString(node, depth, serverContext.getNode());
-                        return finishReplySucceeded(reply, astText);
-                    case REPLMessage.SUBTREE:
-                    case REPLMessage.SUB:
-                        final String subTreeText = astPrinter.printTreeToString(node, depth);
-                        return finishReplySucceeded(reply, subTreeText);
-                    default:
-                        return finishReplyFailed(reply, "Unknown \"" + REPLMessage.TRUFFLE.toString() + "\" topic");
-                }
-
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.toString());
-            }
-        }
-    };
-
-    public static final REPLHandler UNSET_BREAK_CONDITION_HANDLER = new REPLHandler(REPLMessage.UNSET_BREAK_CONDITION) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.UNSET_BREAK_CONDITION);
-            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
-            if (breakpointNumber == null) {
-                return finishReplyFailed(message, "missing breakpoint number");
-            }
-            message.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
-            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
-            if (breakpoint == null) {
-                return finishReplyFailed(message, "no breakpoint number " + breakpointNumber);
-            }
-            try {
-                breakpoint.setCondition(null);
-            } catch (DebugException e) {
-                return finishReplyFailed(message, e.getMessage());
-            }
-            return finishReplyFailed(message, "Breakpoint " + breakpointNumber + " condition cleared");
-        }
-    };
-
-    public static final REPLHandler TRUFFLE_NODE_HANDLER = new REPLHandler(REPLMessage.TRUFFLE_NODE) {
-
-        @Override
-        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
-            final REPLMessage reply = createReply();
-            final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter();
-            final Node node = serverContext.getNode();
-            if (node == null) {
-                return finishReplyFailed(reply, "no current AST node");
-            }
-
-            try {
-                final StringBuilder sb = new StringBuilder();
-                sb.append(astPrinter.printNodeWithInstrumentation(node));
-
-                final SourceSection sourceSection = node.getSourceSection();
-                if (sourceSection != null) {
-                    final String code = sourceSection.getCode();
-                    sb.append(" \"");
-                    sb.append(code.substring(0, Math.min(code.length(), 15)));
-                    sb.append("...\"");
-                }
-                return finishReplySucceeded(reply, sb.toString());
-            } catch (Exception ex) {
-                return finishReplyFailed(reply, ex.toString());
-            }
-        }
-    };
-}
--- a/graal/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.debug.shell.server;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.vm.TruffleVM.Language;
-import com.oracle.truffle.tools.debug.engine.*;
-import com.oracle.truffle.tools.debug.shell.*;
-
-public abstract class REPLServerContext {
-
-    private final int level;
-    private final Node astNode;
-    private final MaterializedFrame mFrame;
-
-    protected REPLServerContext(int level, Node astNode, MaterializedFrame mFrame) {
-        this.level = level;
-        this.astNode = astNode;
-        this.mFrame = mFrame;
-    }
-
-    /**
-     * The nesting depth of this context in the current session.
-     */
-    public int getLevel() {
-        return level;
-    }
-
-    /**
-     * The AST node where execution is halted in this context.
-     */
-    public Node getNode() {
-        return astNode;
-    }
-
-    /**
-     * The frame where execution is halted in this context.
-     */
-    public MaterializedFrame getFrame() {
-        return mFrame;
-    }
-
-    public abstract Language getLanguage();
-
-    public abstract DebugEngine getDebugEngine();
-
-    /**
-     * Dispatches a REPL request to the appropriate handler.
-     */
-    public abstract REPLMessage[] receive(REPLMessage request);
-
-}
--- a/graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.test;
-
-import static com.oracle.truffle.tools.test.TestNodes.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.tools.*;
-
-public class CoverageTrackerTest {
-
-    @Test
-    public void testNoExecution() {
-        final CoverageTracker tool = new CoverageTracker();
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-        tool.install();
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-        tool.setEnabled(false);
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-        tool.setEnabled(true);
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-        tool.reset();
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-        tool.dispose();
-        assertEquals(tool.getCounts().entrySet().size(), 0);
-    }
-
-    @Test
-    public void testToolCreatedTooLate() {
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-        final CoverageTracker tool = new CoverageTracker();
-        tool.install();
-        assertEquals(13, expr13rootNode.execute(null));
-        assertTrue(tool.getCounts().isEmpty());
-        tool.dispose();
-    }
-
-    @Test
-    public void testToolInstalledcTooLate() {
-        final CoverageTracker tool = new CoverageTracker();
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-        tool.install();
-        assertEquals(13, expr13rootNode.execute(null));
-        assertTrue(tool.getCounts().isEmpty());
-        tool.dispose();
-    }
-
-    @Test
-    public void testCountingCoverage() {
-        final CoverageTracker tool = new CoverageTracker();
-        tool.install();
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-
-        // Not probed yet.
-        assertEquals(13, expr13rootNode.execute(null));
-        assertTrue(tool.getCounts().isEmpty());
-
-        final Node addNode = expr13rootNode.getChildren().iterator().next();
-        final Probe probe = addNode.probe();
-
-        // Probed but not tagged yet.
-        assertEquals(13, expr13rootNode.execute(null));
-        assertTrue(tool.getCounts().isEmpty());
-
-        probe.tagAs(StandardSyntaxTag.STATEMENT, "fake statement for testing");
-
-        // Counting now; execute once
-        assertEquals(13, expr13rootNode.execute(null));
-
-        final Long[] longs1 = tool.getCounts().get(addNode.getSourceSection().getSource());
-        assertNotNull(longs1);
-        assertEquals(longs1.length, 2);
-        assertNull(longs1[0]);  // Line 1 is empty (text lines are 1-based)
-        assertEquals(1L, longs1[1].longValue());  // Expression is on line 2
-
-        // Execute 99 more times
-        for (int i = 0; i < 99; i++) {
-            assertEquals(13, expr13rootNode.execute(null));
-        }
-
-        final Long[] longs100 = tool.getCounts().get(addNode.getSourceSection().getSource());
-        assertNotNull(longs100);
-        assertEquals(longs100.length, 2);
-        assertNull(longs100[0]);
-        assertEquals(100L, longs100[1].longValue());
-
-        tool.dispose();
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.test;
-
-import static com.oracle.truffle.tools.test.TestNodes.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.tools.*;
-
-public class LineToProbesMapTest {
-
-    @Test
-    public void testToolCreatedTooLate() {
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-        final Node addNode = expr13rootNode.getChildren().iterator().next();
-        final Probe probe = addNode.probe();
-        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
-        assertEquals(lineLocation, expr13Line2);
-
-        final LineToProbesMap tool = new LineToProbesMap();
-        tool.install();
-
-        assertNull(tool.findFirstProbe(expr13Line1));
-        assertNull(tool.findFirstProbe(expr13Line2));
-        tool.dispose();
-    }
-
-    @Test
-    public void testToolInstalledTooLate() {
-        final LineToProbesMap tool = new LineToProbesMap();
-
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-        final Node addNode = expr13rootNode.getChildren().iterator().next();
-        final Probe probe = addNode.probe();
-        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
-        assertEquals(lineLocation, expr13Line2);
-
-        tool.install();
-
-        assertNull(tool.findFirstProbe(expr13Line1));
-        assertNull(tool.findFirstProbe(expr13Line2));
-        tool.dispose();
-    }
-
-    @Test
-    public void testMapping() {
-        final LineToProbesMap tool = new LineToProbesMap();
-        tool.install();
-
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-        final Node addNode = expr13rootNode.getChildren().iterator().next();
-        final Probe probe = addNode.probe();
-        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
-        assertEquals(lineLocation, expr13Line2);
-
-        assertNull(tool.findFirstProbe(expr13Line1));
-        assertEquals(tool.findFirstProbe(expr13Line2), probe);
-        tool.dispose();
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.test;
-
-import static com.oracle.truffle.tools.test.TestNodes.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.tools.*;
-import com.oracle.truffle.tools.NodeExecCounter.NodeExecutionCount;
-import com.oracle.truffle.tools.test.TestNodes.TestAddNode;
-import com.oracle.truffle.tools.test.TestNodes.TestValueNode;
-
-public class NodeExecCounterTest {
-
-    @Test
-    public void testNoExecution() {
-        final NodeExecCounter tool = new NodeExecCounter();
-        assertEquals(tool.getCounts().length, 0);
-        tool.install();
-        assertEquals(tool.getCounts().length, 0);
-        tool.setEnabled(false);
-        assertEquals(tool.getCounts().length, 0);
-        tool.setEnabled(true);
-        assertEquals(tool.getCounts().length, 0);
-        tool.reset();
-        assertEquals(tool.getCounts().length, 0);
-        tool.dispose();
-        assertEquals(tool.getCounts().length, 0);
-    }
-
-    @Test
-    public void testToolCreatedTooLate() {
-        final CallTarget expr13callTarget = createExpr13TestCallTarget();
-        final NodeExecCounter tool = new NodeExecCounter();
-        tool.install();
-        assertEquals(13, expr13callTarget.call());
-        assertEquals(tool.getCounts().length, 0);
-        tool.dispose();
-    }
-
-    @Test
-    public void testToolInstalledcTooLate() {
-        final NodeExecCounter tool = new NodeExecCounter();
-        final CallTarget expr13callTarget = createExpr13TestCallTarget();
-        tool.install();
-        assertEquals(13, expr13callTarget.call());
-        assertEquals(tool.getCounts().length, 0);
-        tool.dispose();
-    }
-
-    @Test
-    public void testCountingAll() {
-        final NodeExecCounter tool = new NodeExecCounter();
-        tool.install();
-        final CallTarget expr13callTarget = createExpr13TestCallTarget();
-
-        // execute once
-        assertEquals(13, expr13callTarget.call());
-        final NodeExecutionCount[] count1 = tool.getCounts();
-        assertNotNull(count1);
-        assertEquals(count1.length, 2);
-        for (NodeExecutionCount count : count1) {
-            final Class<?> class1 = count.nodeClass();
-            final long executionCount = count.executionCount();
-            if (class1 == TestAddNode.class) {
-                assertEquals(executionCount, 1);
-            } else if (class1 == TestValueNode.class) {
-                assertEquals(executionCount, 2);
-            } else {
-                fail();
-            }
-        }
-
-        // Execute 99 more times
-        for (int i = 0; i < 99; i++) {
-            assertEquals(13, expr13callTarget.call());
-        }
-        final NodeExecutionCount[] counts100 = tool.getCounts();
-        assertNotNull(counts100);
-        assertEquals(counts100.length, 2);
-        for (NodeExecutionCount count : counts100) {
-            final Class<?> class1 = count.nodeClass();
-            final long executionCount = count.executionCount();
-            if (class1 == TestAddNode.class) {
-                assertEquals(executionCount, 100);
-            } else if (class1 == TestValueNode.class) {
-                assertEquals(executionCount, 200);
-            } else {
-                fail();
-            }
-        }
-
-        tool.dispose();
-    }
-
-    @Test
-    public void testCountingTagged() {
-        final NodeExecCounter tool = new NodeExecCounter(StandardSyntaxTag.STATEMENT);
-        tool.install();
-        final RootNode expr13rootNode = createExpr13TestRootNode();
-
-        // Not probed yet.
-        assertEquals(13, expr13rootNode.execute(null));
-        assertEquals(tool.getCounts().length, 0);
-
-        final Node addNode = expr13rootNode.getChildren().iterator().next();
-        final Probe probe = addNode.probe();
-
-        // Probed but not tagged yet.
-        assertEquals(13, expr13rootNode.execute(null));
-        assertEquals(tool.getCounts().length, 0);
-
-        probe.tagAs(StandardSyntaxTag.STATEMENT, "fake statement for testing");
-
-        // Counting now; execute once
-        assertEquals(13, expr13rootNode.execute(null));
-        final NodeExecutionCount[] counts1 = tool.getCounts();
-        assertNotNull(counts1);
-        assertEquals(counts1.length, 1);
-        final NodeExecutionCount count1 = counts1[0];
-        assertNotNull(count1);
-        assertEquals(count1.nodeClass(), addNode.getClass());
-        assertEquals(count1.executionCount(), 1);
-
-        // Execute 99 more times
-        for (int i = 0; i < 99; i++) {
-            assertEquals(13, expr13rootNode.execute(null));
-        }
-
-        final NodeExecutionCount[] counts100 = tool.getCounts();
-        assertNotNull(counts100);
-        assertEquals(counts100.length, 1);
-        final NodeExecutionCount count100 = counts100[0];
-        assertNotNull(count100);
-        assertEquals(count100.nodeClass(), addNode.getClass());
-        assertEquals(count100.executionCount(), 100);
-
-        tool.dispose();
-    }
-}
--- a/graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TestNodes.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.test;
-
-import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * Nodes and an {@linkplain CallTarget executable ASTs} for testing.
- */
-class TestNodes {
-
-    /**
-     * A fake source used for testing: empty line 1, expression on line 2.
-     */
-    public static final Source expr13Source = Source.fromText("\n6+7\n", "Test Source: expression on line 2 that evaluates to 13");
-    public static final LineLocation expr13Line1 = expr13Source.createLineLocation(1);
-    public static final LineLocation expr13Line2 = expr13Source.createLineLocation(2);
-
-    /**
-     * An executable addition expression that evaluates to 13.
-     */
-    static CallTarget createExpr13TestCallTarget() {
-        final RootNode rootNode = createExpr13TestRootNode();
-        return Truffle.getRuntime().createCallTarget(rootNode);
-    }
-
-    /**
-     * Root holding an addition expression that evaluates to 13.
-     */
-    static RootNode createExpr13TestRootNode() {
-        final TestLanguageNode ast = createExpr13AST();
-        final TestRootNode rootNode = new TestRootNode(ast);
-        rootNode.adoptChildren();
-        return rootNode;
-    }
-
-    /**
-     * Addition expression that evaluates to 13, with faked source attribution.
-     */
-    static TestLanguageNode createExpr13AST() {
-        final SourceSection leftSourceSection = expr13Source.createSection("left", 1, 1);
-        final TestValueNode leftValueNode = new TestValueNode(6, leftSourceSection);
-        final SourceSection rightSourceSection = expr13Source.createSection("right", 3, 1);
-        final TestValueNode rightValueNode = new TestValueNode(7, rightSourceSection);
-        final SourceSection exprSourceSection = expr13Source.createSection("expr", 1, 3);
-        return new TestAddNode(leftValueNode, rightValueNode, exprSourceSection);
-    }
-
-    abstract static class TestLanguageNode extends Node {
-        public abstract Object execute(VirtualFrame frame);
-
-        public TestLanguageNode() {
-        }
-
-        public TestLanguageNode(SourceSection srcSection) {
-            super(srcSection);
-        }
-
-        @Override
-        public boolean isInstrumentable() {
-            return true;
-        }
-
-        @Override
-        public WrapperNode createWrapperNode() {
-            return new TestWrapperNode(this);
-        }
-    }
-
-    @NodeInfo(cost = NodeCost.NONE)
-    static class TestWrapperNode extends TestLanguageNode implements WrapperNode {
-        @Child private TestLanguageNode child;
-        @Child private ProbeNode probeNode;
-
-        public TestWrapperNode(TestLanguageNode child) {
-            assert !(child instanceof TestWrapperNode);
-            this.child = child;
-        }
-
-        @Override
-        public String instrumentationInfo() {
-            return "Wrapper node for testing";
-        }
-
-        @Override
-        public boolean isInstrumentable() {
-            return false;
-        }
-
-        @Override
-        public void insertProbe(ProbeNode newProbeNode) {
-            this.probeNode = newProbeNode;
-        }
-
-        @Override
-        public Probe getProbe() {
-            return probeNode.getProbe();
-        }
-
-        @Override
-        public Node getChild() {
-            return child;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            probeNode.enter(child, frame);
-            Object result;
-
-            try {
-                result = child.execute(frame);
-                probeNode.returnValue(child, frame, result);
-            } catch (KillException e) {
-                throw (e);
-            } catch (Exception e) {
-                probeNode.returnExceptional(child, frame, e);
-                throw (e);
-            }
-
-            return result;
-        }
-    }
-
-    /**
-     * Truffle requires that all guest languages to have a {@link RootNode} which sits atop any AST
-     * of the guest language. This is necessary since creating a {@link CallTarget} is how Truffle
-     * completes an AST. The root nodes serves as our entry point into a program.
-     */
-    static class TestRootNode extends RootNode {
-        @Child private TestLanguageNode body;
-
-        /**
-         * This constructor emulates the global machinery that applies registered probers to every
-         * newly created AST. Global registry is not used, since that would interfere with other
-         * tests run in the same environment.
-         */
-        public TestRootNode(TestLanguageNode body) {
-            super(null);
-            this.body = body;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return body.execute(frame);
-        }
-
-        @Override
-        public boolean isCloningAllowed() {
-            return true;
-        }
-
-        @Override
-        public void applyInstrumentation() {
-            Probe.applyASTProbers(body);
-        }
-    }
-
-    static class TestValueNode extends TestLanguageNode {
-        private final int value;
-
-        public TestValueNode(int value) {
-            this.value = value;
-        }
-
-        public TestValueNode(int value, SourceSection srcSection) {
-            super(srcSection);
-            this.value = value;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return new Integer(this.value);
-        }
-    }
-
-    static class TestAddNode extends TestLanguageNode {
-        @Child private TestLanguageNode leftChild;
-        @Child private TestLanguageNode rightChild;
-
-        public TestAddNode(TestValueNode leftChild, TestValueNode rightChild, SourceSection sourceSection) {
-            super(sourceSection);
-            this.leftChild = insert(leftChild);
-            this.rightChild = insert(rightChild);
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            return new Integer(((Integer) leftChild.execute(frame)).intValue() + ((Integer) rightChild.execute(frame)).intValue());
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools.test;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.truffle.api.instrument.*;
-
-/**
- * Test the basic life cycle properties shared by all instances of {@link InstrumentationTool}.
- */
-public class TruffleToolTest {
-
-    @Test
-    public void testEmptyLifeCycle() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        assertFalse(tool.isEnabled());
-        tool.install();
-        assertTrue(tool.isEnabled());
-        tool.reset();
-        assertTrue(tool.isEnabled());
-        tool.setEnabled(false);
-        assertFalse(tool.isEnabled());
-        tool.reset();
-        assertFalse(tool.isEnabled());
-        tool.setEnabled(true);
-        assertTrue(tool.isEnabled());
-        tool.reset();
-        assertTrue(tool.isEnabled());
-        tool.dispose();
-        assertFalse(tool.isEnabled());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNotYetInstalled1() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.reset();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNotYetInstalled2() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.setEnabled(true);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNotYetInstalled3() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.dispose();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testAlreadyInstalled() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.install();
-        tool.install();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testAlreadyDisposed1() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.install();
-        tool.dispose();
-        tool.install();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testAlreadyDisposed2() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.install();
-        tool.dispose();
-        tool.reset();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testAlreadyDisposed3() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.install();
-        tool.dispose();
-        tool.setEnabled(true);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testAlreadyDisposed4() {
-        final DummyTruffleTool tool = new DummyTruffleTool();
-        tool.install();
-        tool.dispose();
-        tool.dispose();
-    }
-
-    private static final class DummyTruffleTool extends InstrumentationTool {
-
-        @Override
-        protected boolean internalInstall() {
-            return true;
-        }
-
-        @Override
-        protected void internalReset() {
-        }
-
-        @Override
-        protected void internalDispose() {
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools;
-
-import java.io.*;
-import java.util.*;
-import java.util.Map.Entry;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * An {@link InstrumentationTool} that counts interpreter <em>execution calls</em> to AST nodes that
- * hold a specified {@linkplain SyntaxTag syntax tag}, tabulated by source and line number
- * associated with each node. Syntax tags are presumed to be applied external to the tool. If no tag
- * is specified, {@linkplain StandardSyntaxTag#STATEMENT STATEMENT} is used, corresponding to
- * conventional behavior for code coverage tools.
- * <p>
- * No counts will be kept for execution in sources that hold the {@link SourceTag}
- * {@link Tags#NO_COVERAGE}.
- * <p>
- * <b>Tool Life Cycle</b>
- * <p>
- * See {@link InstrumentationTool} for the life cycle common to all such tools.
- * <p>
- * <b>Execution Counts</b>
- * <p>
- * <ul>
- * <li>"Execution call" on a node is is defined as invocation of a node method that is instrumented
- * to produce the event {@link SimpleInstrumentListener#enter(Probe)};</li>
- * <li>Execution calls are tabulated only at <em>instrumented</em> nodes, i.e. those for which
- * {@linkplain Node#isInstrumentable() isInstrumentable() == true};</li>
- * <li>Execution calls are tabulated only at nodes present in the AST when originally created;
- * dynamically added nodes will not be instrumented.</li>
- * </ul>
- * </p>
- * <b>Results</b>
- * <p>
- * A modification-safe copy of the {@linkplain #getCounts() counts} can be retrieved at any time,
- * without effect on the state of the tool.
- * </p>
- * <p>
- * A "default" {@linkplain #print(PrintStream) print()} method can summarizes the current counts at
- * any time in a simple textual format, with no other effect on the state of the tool.
- * </p>
- *
- * @see Instrument
- * @see SyntaxTag
- */
-public final class CoverageTracker extends InstrumentationTool {
-
-    public enum Tags implements SourceTag {
-
-        /**
-         * Report no counts for sources holding this tag.
-         */
-        NO_COVERAGE("No Coverage", "Coverage Tracker will igore");
-
-        private final String name;
-        private final String description;
-
-        private Tags(String name, String description) {
-            this.name = name;
-            this.description = description;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public String getDescription() {
-            return description;
-        }
-    }
-
-    /** Counting data. */
-    private final Map<LineLocation, CoverageRecord> coverageMap = new HashMap<>();
-
-    /** Needed for disposal. */
-    private final List<Instrument> instruments = new ArrayList<>();
-
-    /**
-     * Coverage counting is restricted to nodes holding this tag.
-     */
-    private final SyntaxTag countingTag;
-
-    private final ProbeListener probeListener;
-
-    /**
-     * Create a per-line coverage tool for nodes tagged as {@linkplain StandardSyntaxTag#STATEMENT
-     * statements} in subsequently created ASTs.
-     */
-    public CoverageTracker() {
-        this(StandardSyntaxTag.STATEMENT);
-    }
-
-    /**
-     * Create a per-line coverage tool for nodes tagged as specified, presuming that tags applied
-     * outside this tool.
-     */
-    public CoverageTracker(SyntaxTag tag) {
-        this.probeListener = new CoverageProbeListener();
-        this.countingTag = tag;
-    }
-
-    @Override
-    protected boolean internalInstall() {
-        Probe.addProbeListener(probeListener);
-        return true;
-    }
-
-    @Override
-    protected void internalReset() {
-        coverageMap.clear();
-    }
-
-    @Override
-    protected void internalDispose() {
-        Probe.removeProbeListener(probeListener);
-        for (Instrument instrument : instruments) {
-            instrument.dispose();
-        }
-    }
-
-    /**
-     * Gets a modification-safe summary of the current per-type node execution counts; does not
-     * affect the counts.
-     * <p>
-     * The map holds an array for each source, and elements of the a array corresponding to the
-     * textual lines of that source. An array entry contains null if the corresponding line of
-     * source is associated with no nodes of the relevant type, i.e. where no count was made. A
-     * numeric entry represents the execution count at the corresponding line of source.
-     * <p>
-     * <b>Note:</b> source line numbers are 1-based, so array index {@code i} corresponds to source
-     * line number {@code i + 1}
-     */
-    public Map<Source, Long[]> getCounts() {
-
-        /**
-         * Counters for every {Source, line number} for which a counter was installed, i.e. for
-         * every line associated with an appropriately tagged AST node; iterable in order of source
-         * name, then line number.
-         */
-        final TreeSet<Entry<LineLocation, CoverageRecord>> entries = new TreeSet<>(new LineLocationEntryComparator());
-
-        for (Entry<LineLocation, CoverageRecord> entry : coverageMap.entrySet()) {
-            entries.add(entry);
-        }
-        final Map<Source, Long[]> result = new HashMap<>();
-        Source curSource = null;
-        Long[] curLineTable = null;
-        for (Entry<LineLocation, CoverageRecord> entry : entries) {
-            final LineLocation key = entry.getKey();
-            final Source source = key.getSource();
-            final int lineNo = key.getLineNumber();
-            if (source != curSource) {
-                if (curSource != null) {
-                    result.put(curSource, curLineTable);
-                }
-                curSource = source;
-                curLineTable = new Long[source.getLineCount()];
-            }
-            curLineTable[lineNo - 1] = entry.getValue().count;
-        }
-        if (curSource != null) {
-            result.put(curSource, curLineTable);
-        }
-        return result;
-    }
-
-    /**
-     * A default printer for the current line counts, producing lines of the form " (<count>) <line
-     * number> : <text of line>", grouped by source.
-     */
-    public void print(PrintStream out) {
-        out.println();
-        out.println(countingTag.name() + " coverage:");
-
-        /**
-         * Counters for every {Source, line number} for which a counter was installed, i.e. for
-         * every line associated with an appropriately tagged AST node; iterable in order of source
-         * name, then line number.
-         */
-        final TreeSet<Entry<LineLocation, CoverageRecord>> entries = new TreeSet<>(new LineLocationEntryComparator());
-
-        for (Entry<LineLocation, CoverageRecord> entry : coverageMap.entrySet()) {
-            entries.add(entry);
-        }
-        Source curSource = null;
-        int curLineNo = 1;
-        for (Entry<LineLocation, CoverageRecord> entry : entries) {
-            final LineLocation key = entry.getKey();
-            final Source source = key.getSource();
-            final int lineNo = key.getLineNumber();
-            if (source != curSource) {
-                if (curSource != null) {
-                    while (curLineNo <= curSource.getLineCount()) {
-                        displayLine(out, null, curSource, curLineNo++);
-                    }
-                }
-                curSource = source;
-                curLineNo = 1;
-                out.println();
-                out.println(source.getPath());
-            }
-            while (curLineNo < lineNo) {
-                displayLine(out, null, curSource, curLineNo++);
-            }
-            displayLine(out, entry.getValue(), curSource, curLineNo++);
-        }
-        if (curSource != null) {
-            while (curLineNo <= curSource.getLineCount()) {
-                displayLine(out, null, curSource, curLineNo++);
-            }
-        }
-    }
-
-    private static void displayLine(PrintStream out, CoverageRecord record, Source source, int lineNo) {
-        if (record == null) {
-            out.format("%14s", " ");
-        } else {
-            out.format("(%12d)", record.count);
-        }
-        out.format(" %3d: ", lineNo);
-        out.println(source.getCode(lineNo));
-    }
-
-    /**
-     * A listener for events at each instrumented AST location. This listener counts
-     * "execution calls" to the instrumented node.
-     */
-    private final class CoverageRecord extends DefaultSimpleInstrumentListener {
-
-        private final SourceSection srcSection; // The text of the code being counted
-        private Instrument instrument;  // The attached Instrument, in case need to remove.
-        private long count = 0;
-
-        CoverageRecord(SourceSection srcSection) {
-            this.srcSection = srcSection;
-        }
-
-        @Override
-        public void enter(Probe probe) {
-            if (isEnabled()) {
-                count++;
-            }
-        }
-
-    }
-
-    private static final class LineLocationEntryComparator implements Comparator<Entry<LineLocation, CoverageRecord>> {
-
-        public int compare(Entry<LineLocation, CoverageRecord> e1, Entry<LineLocation, CoverageRecord> e2) {
-            return LineLocation.COMPARATOR.compare(e1.getKey(), e2.getKey());
-        }
-    }
-
-    /**
-     * Attach a counting instrument to each node that is assigned a specified tag.
-     */
-    private class CoverageProbeListener extends DefaultProbeListener {
-
-        @Override
-        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-            if (countingTag == tag) {
-
-                final SourceSection srcSection = probe.getProbedSourceSection();
-                if (srcSection == null) {
-                    // TODO (mlvdv) report this?
-                } else if (!srcSection.getSource().isTaggedAs(Tags.NO_COVERAGE)) {
-                    // Get the source line where the
-                    final LineLocation lineLocation = srcSection.getLineLocation();
-                    CoverageRecord record = coverageMap.get(lineLocation);
-                    if (record != null) {
-                        // Another node starts on same line; count only the first (textually)
-                        if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) {
-                            // Existing record, corresponds to code earlier on line
-                            return;
-                        } else {
-                            // Existing record, corresponds to code at a later position; replace it
-                            record.instrument.dispose();
-                        }
-                    }
-
-                    final CoverageRecord coverage = new CoverageRecord(srcSection);
-                    final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName());
-                    coverage.instrument = instrument;
-                    instruments.add(instrument);
-                    probe.attach(instrument);
-                    coverageMap.put(lineLocation, coverage);
-                }
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools;
-
-import java.io.*;
-import java.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.source.*;
-
-/**
- * An {@link InstrumentationTool} that builds a map of every {@link Probe} attached to some AST,
- * indexed by {@link Source} and line number.
- */
-public final class LineToProbesMap extends InstrumentationTool {
-
-    private static final boolean TRACE = false;
-    private static final PrintStream OUT = System.out;
-
-    private static void trace(String msg) {
-        OUT.println("LineToProbesMap: " + msg);
-    }
-
-    /**
-     * Map: Source line ==> probes associated with source sections starting on the line.
-     */
-    private final Map<LineLocation, Collection<Probe>> lineToProbesMap = new HashMap<>();
-
-    private final ProbeListener probeListener;
-
-    /**
-     * Create a map of {@link Probe}s that collects information on all probes added to subsequently
-     * created ASTs (once installed).
-     */
-    public LineToProbesMap() {
-        this.probeListener = new LineToProbesListener();
-    }
-
-    @Override
-    protected boolean internalInstall() {
-        Probe.addProbeListener(probeListener);
-        return true;
-    }
-
-    @Override
-    protected void internalReset() {
-        lineToProbesMap.clear();
-    }
-
-    @Override
-    protected void internalDispose() {
-        Probe.removeProbeListener(probeListener);
-    }
-
-    /**
-     * Returns the {@link Probe}, if any, associated with a specific line of guest language code; if
-     * more than one, return the one with the first starting character location.
-     */
-    public Probe findFirstProbe(LineLocation lineLocation) {
-        Probe probe = null;
-        final Collection<Probe> probes = findProbes(lineLocation);
-        for (Probe probesOnLine : probes) {
-            if (probe == null) {
-                probe = probesOnLine;
-            } else if (probesOnLine.getProbedSourceSection().getCharIndex() < probe.getProbedSourceSection().getCharIndex()) {
-                probe = probesOnLine;
-            }
-        }
-        return probe;
-    }
-
-    /**
-     * Returns all {@link Probe}s whose associated source begins at the given {@link LineLocation},
-     * an empty list if none.
-     */
-    public Collection<Probe> findProbes(LineLocation line) {
-        final Collection<Probe> probes = lineToProbesMap.get(line);
-        if (probes == null) {
-            return Collections.emptyList();
-        }
-        return Collections.unmodifiableCollection(probes);
-    }
-
-    private class LineToProbesListener extends DefaultProbeListener {
-
-        @Override
-        public void newProbeInserted(Probe probe) {
-            final SourceSection sourceSection = probe.getProbedSourceSection();
-            if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) {
-                final LineLocation lineLocation = sourceSection.getLineLocation();
-                if (TRACE) {
-                    trace("ADD " + lineLocation.getShortDescription() + " ==> " + probe.getShortDescription());
-                }
-                Collection<Probe> probes = lineToProbesMap.get(lineLocation);
-                if (probes == null) {
-                    probes = new ArrayList<>(2);
-                    lineToProbesMap.put(lineLocation, probes);
-                } else {
-                    assert !probes.contains(probe);
-                }
-                probes.add(probe);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.tools;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.*;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.instrument.impl.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.Node.Child;
-
-/**
- * An {@link InstrumentationTool} that counts interpreter <em>execution calls</em> to AST nodes,
- * tabulated by the type of called nodes; counting can be enabled <em>all</em> nodes or restricted
- * to nodes with a specified {@linkplain SyntaxTag tag} that is presumed to be applied external to
- * the tool.
- * <p>
- * <b>Tool Life Cycle</b>
- * <p>
- * See {@link InstrumentationTool} for the life cycle common to all such tools.
- * </p>
- * <b>Execution Counts</b>
- * <p>
- * <ul>
- * <li>"Execution call" on a node is is defined as invocation of a node method that is instrumented
- * to produce the event {@link StandardInstrumentListener#enter(Probe, Node, VirtualFrame)};</li>
- * <li>Execution calls are tabulated only at <em>instrumented</em> nodes, i.e. those for which
- * {@linkplain Node#isInstrumentable() isInstrumentable() == true};</li>
- * <li>Execution calls are tabulated only at nodes present in the AST when originally created;
- * dynamically added nodes will not be instrumented.</li>
- * </ul>
- * </p>
- * <b>Failure Log</b>
- * <p>
- * For the benefit of language implementors, the tool maintains a log describing failed attempts to
- * probe AST nodes. Most failures occur when the type of the wrapper created by
- * {@link Node#createWrapperNode()} is not assignable to the relevant {@link Child} field in the
- * node's parent.
- * </p>
- * <p>
- * {@linkplain #reset() Resetting} the counts has no effect on the failure log.
- * </p>
- * <b>Results</b>
- * <p>
- * A modification-safe copy of the {@linkplain #getCounts() counts} can be retrieved at any time,
- * without effect on the state of the tool.
- * </p>
- * <p>
- * A "default" {@linkplain #print(PrintStream) print()} method can summarizes the current counts at
- * any time in a simple textual format, without effect on the state of the tool.
- * </p>
- *
- * @see Instrument
- * @see SyntaxTag
- * @see ProbeFailure
- */
-public final class NodeExecCounter extends InstrumentationTool {
-
-    /**
-     * Execution count for AST nodes of a particular type.
-     */
-    public interface NodeExecutionCount {
-        Class<?> nodeClass();
-
-        long executionCount();
-    }
-
-    /**
-     * Listener for events at instrumented nodes. Counts are maintained in a shared table, so the
-     * listener is stateless and can be shared by every {@link Instrument}.
-     */
-    private final StandardInstrumentListener instrumentListener = new DefaultStandardInstrumentListener() {
-        @Override
-        public void enter(Probe probe, Node node, VirtualFrame vFrame) {
-            if (isEnabled()) {
-                final Class<?> nodeClass = node.getClass();
-                /*
-                 * Everything up to here is inlined by Truffle compilation. Delegate the next part
-                 * to a method behind an inlining boundary.
-                 * 
-                 * Note that it is not permitted to pass a {@link VirtualFrame} across an inlining
-                 * boundary; they are truly virtual in inlined code.
-                 */
-                AtomicLong nodeCounter = getCounter(nodeClass);
-                nodeCounter.getAndIncrement();
-            }
-        }
-
-        /**
-         * Mark this method as a boundary that will stop Truffle inlining, which should not be
-         * allowed to inline the hash table method or any other complex library code.
-         */
-        @TruffleBoundary
-        private AtomicLong getCounter(Class<?> nodeClass) {
-            AtomicLong nodeCounter = counters.get(nodeClass);
-            if (nodeCounter == null) {
-                nodeCounter = new AtomicLong();
-                counters.put(nodeClass, nodeCounter);
-            }
-            return nodeCounter;
-        }
-    };
-
-    /** Counting data. */
-    private final Map<Class<?>, AtomicLong> counters = new HashMap<>();
-
-    /** Failure log. */
-    private final List<ProbeFailure> failures = new ArrayList<>();
-
-    /** For disposal. */
-    private final List<Instrument> instruments = new ArrayList<>();
-
-    /**
-     * If non-null, counting is restricted to nodes holding this tag.
-     */
-    private final SyntaxTag countingTag;
-
-    /**
-     * Prober used only when instrumenting every node.
-     */
-    private ASTProber astProber;
-
-    /**
-     * Listener used only when restricting counting to a specific tag.
-     */
-    private ProbeListener probeListener;
-
-    /**
-     * Create a per node-type execution counting tool for all nodes in subsequently created ASTs.
-     */
-    public NodeExecCounter() {
-        this.countingTag = null;
-    }
-
-    /**
-     * Creates a per-type execution counting for nodes tagged as specified in subsequently created
-     * ASTs.
-     */
-    public NodeExecCounter(SyntaxTag tag) {
-        this.countingTag = tag;
-    }
-
-    @Override
-    protected boolean internalInstall() {
-        if (countingTag == null) {
-            astProber = new ExecCounterASTProber();
-            Probe.registerASTProber(astProber);
-        } else {
-            probeListener = new NodeExecCounterProbeListener();
-            Probe.addProbeListener(probeListener);
-        }
-        return true;
-    }
-
-    @Override
-    protected void internalReset() {
-        counters.clear();
-        failures.clear();
-    }
-
-    @Override
-    protected void internalDispose() {
-        if (astProber != null) {
-            Probe.unregisterASTProber(astProber);
-        }
-        if (probeListener != null) {
-            Probe.removeProbeListener(probeListener);
-        }
-        for (Instrument instrument : instruments) {
-            instrument.dispose();
-        }
-    }
-
-    /**
-     * Gets a modification-safe summary of the current per-type node execution counts; does not
-     * affect the counts.
-     */
-    public NodeExecutionCount[] getCounts() {
-        final Collection<Map.Entry<Class<?>, AtomicLong>> entrySet = counters.entrySet();
-        final NodeExecutionCount[] result = new NodeExecCountImpl[entrySet.size()];
-        int i = 0;
-        for (Map.Entry<Class<?>, AtomicLong> entry : entrySet) {
-            result[i++] = new NodeExecCountImpl(entry.getKey(), entry.getValue().longValue());
-        }
-        return result;
-    }
-
-    /**
-     * Gets a log containing a report of every failed attempt to instrument a node.
-     */
-    public ProbeFailure[] getFailures() {
-        return failures.toArray(new ProbeFailure[failures.size()]);
-    }
-
-    /**
-     * A default printer for the current counts, producing lines of the form
-     * " <count> : <node type>" in descending order of count.
-     */
-    public void print(PrintStream out) {
-        print(out, false);
-    }
-
-    /**
-     * A default printer for the current counts, producing lines of the form
-     * " <count> : <node type>" in descending order of count.
-     *
-     * @param out
-     * @param verbose whether to describe nodes on which instrumentation failed
-     */
-    public void print(PrintStream out, boolean verbose) {
-
-        final long missedNodes = failures.size();
-        out.println();
-        if (countingTag == null) {
-            out.println("Execution counts by node type:");
-        } else {
-            out.println("\"" + countingTag.name() + "\"-tagged execution counts by node type:");
-        }
-        final StringBuilder disclaim = new StringBuilder("(");
-        if (missedNodes > 0) {
-            disclaim.append(Long.toString(missedNodes) + " original AST nodes not instrumented, ");
-        }
-        disclaim.append("dynamically added nodes not instrumented)");
-        out.println(disclaim.toString());
-        NodeExecutionCount[] execCounts = getCounts();
-        // Sort in descending order
-        Arrays.sort(execCounts, new Comparator<NodeExecutionCount>() {
-
-            public int compare(NodeExecutionCount o1, NodeExecutionCount o2) {
-                return Long.compare(o2.executionCount(), o1.executionCount());
-            }
-
-        });
-        for (NodeExecutionCount nodeCount : execCounts) {
-            out.format("%12d", nodeCount.executionCount());
-            out.println(" : " + nodeCount.nodeClass().getName());
-        }
-
-        if (verbose && missedNodes > 0) {
-            out.println("Instrumentation failures for execution counts:");
-
-            for (ProbeFailure failure : failures) {
-                out.println("\t" + failure.getMessage());
-            }
-        }
-    }
-
-    /**
-     * A prober that attempts to probe and instrument every node.
-     */
-    private class ExecCounterASTProber implements ASTProber, NodeVisitor {
-
-        public boolean visit(Node node) {
-
-            if (node.isInstrumentable()) {
-                try {
-                    final Instrument instrument = Instrument.create(instrumentListener, "NodeExecCounter");
-                    instruments.add(instrument);
-                    node.probe().attach(instrument);
-                } catch (ProbeException ex) {
-                    failures.add(ex.getFailure());
-                }
-            }
-            return true;
-        }
-
-        public void probeAST(Node node) {
-            node.accept(this);
-        }
-    }
-
-    /**
-     * A listener that assumes ASTs have been tagged external to this tool, and which instruments
-     * nodes holding a specified tag.
-     */
-    private class NodeExecCounterProbeListener extends DefaultProbeListener {
-
-        @Override
-        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
-            if (countingTag == tag) {
-                final Instrument instrument = Instrument.create(instrumentListener, NodeExecCounter.class.getSimpleName());
-                instruments.add(instrument);
-                probe.attach(instrument);
-            }
-        }
-    }
-
-    private static class NodeExecCountImpl implements NodeExecutionCount {
-
-        private final Class<?> nodeClass;
-        private final long count;
-
-        public NodeExecCountImpl(Class<?> nodeClass, long count) {
-            this.nodeClass = nodeClass;
-            this.count = count;
-        }
-
-        public Class<?> nodeClass() {
-            return nodeClass;
-        }
-
-        public long executionCount() {
-            return count;
-        }
-    }
-}
--- a/graal/overview.html	Wed Jun 17 10:01:47 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 2 only, as
-published by the Free Software Foundation.  Oracle designates this
-particular file as subject to the "Classpath" exception as provided
-by Oracle in the LICENSE file that accompanied this code.
-
-This code is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-version 2 for more details (a copy is included in the LICENSE file that
-accompanied this code).
-
-You should have received a copy of the GNU General Public License version
-2 along with this work; if not, write to the Free Software Foundation,
-Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-or visit www.oracle.com if you need additional information or have any
-questions.
--->
-
-</head>
-<body>
-
-<a href="projects.html" title="Click to enlarge"><img src="projects.jpg" width="400"/></a>
-<p>
-This document is the unified Javadoc for the Graal code base.
-The project dependency graph is shown above.
-Each node in the diagram is a link to the standalone Javadoc for the denoted project.
-<p>
-<a target="_top" href="http://openjdk.java.net/projects/graal/"><b>[go to the OpenJDK Graal project site]</b></a>
-
-</body>
-</html>
--- a/mx/suite.py	Wed Jun 17 10:01:47 2015 +0200
+++ b/mx/suite.py	Wed Jun 17 10:58:08 2015 +0200
@@ -159,14 +159,14 @@
     # ------------- Truffle -------------
 
     "com.oracle.truffle.api" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "javaCompliance" : "1.7",
       "workingSets" : "API,Truffle",
     },
 
     "com.oracle.truffle.api.test" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.api",
@@ -180,7 +180,7 @@
     },
 
     "com.oracle.truffle.api.dsl" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api"],
       "checkstyle" : "com.oracle.truffle.api",
@@ -189,7 +189,7 @@
     },
 
     "com.oracle.truffle.api.dsl.test" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.dsl.processor",
@@ -203,7 +203,7 @@
     },
 
     "com.oracle.truffle.dsl.processor" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api.dsl"],
       "checkstyle" : "com.oracle.truffle.dsl.processor",
@@ -212,7 +212,7 @@
     },
 
     "com.oracle.truffle.api.interop" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api"],
       "checkstyle" : "com.oracle.truffle.api",
@@ -221,7 +221,7 @@
     },
 
     "com.oracle.truffle.api.object" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api.interop"],
       "checkstyle" : "com.oracle.truffle.api",
@@ -230,7 +230,7 @@
     },
 
     "com.oracle.truffle.object" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api.object"],
       "checkstyle" : "com.oracle.truffle.dsl.processor",
@@ -239,7 +239,7 @@
     },
 
     "com.oracle.truffle.object.basic" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.object"],
       "checkstyle" : "com.oracle.truffle.dsl.processor",
@@ -248,7 +248,7 @@
     },
 
     "com.oracle.truffle.tck" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.api",
@@ -260,7 +260,7 @@
     },
 
     "com.oracle.truffle.tools" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.api"],
       "checkstyle" : "com.oracle.truffle.api",
@@ -269,7 +269,7 @@
     },
 
     "com.oracle.truffle.tools.test" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
           "com.oracle.truffle.tools",
@@ -281,7 +281,7 @@
     },
 
     "com.oracle.truffle.tools.debug.engine" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.tools"],
       "checkstyle" : "com.oracle.truffle.api",
@@ -290,7 +290,7 @@
     },
 
     "com.oracle.truffle.tools.debug.shell" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.tools.debug.engine",
                         "JLINE"],
@@ -300,7 +300,7 @@
     },
 
     "com.oracle.truffle.sl" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.api.dsl",
@@ -315,7 +315,7 @@
     },
 
     "com.oracle.truffle.sl.test" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.tck",
@@ -327,7 +327,7 @@
     },
 
      "com.oracle.truffle.sl.tools" : {
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourceDirs" : ["src"],
       "dependencies" : ["com.oracle.truffle.tools.debug.shell",
                         "com.oracle.truffle.sl"],
@@ -343,7 +343,7 @@
 
     "TRUFFLE" : {
       "path" : "build/truffle.jar",
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourcesPath" : "build/truffle.src.zip",
       "javaCompliance" : "1.7",
       "dependencies" : [
@@ -357,7 +357,7 @@
 
     "TRUFFLE_TCK" : {
       "path" : "build/truffle-tck.jar",
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourcesPath" : "build/truffle-tck.src.zip",
       "javaCompliance" : "1.7",
       "dependencies" : [
@@ -368,7 +368,7 @@
 
     "TRUFFLE_DSL_PROCESSOR" : {
       "path" : "build/truffle-dsl-processor.jar",
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourcesPath" : "build/truffle-dsl-processor.src.zip",
       "javaCompliance" : "1.7",
       "dependencies" : ["com.oracle.truffle.dsl.processor"],
@@ -377,7 +377,7 @@
 
     "TRUFFLE_SL" : {
       "path" : "build/truffle-sl.jar",
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourcesPath" : "build/truffle-sl.src.zip",
       "javaCompliance" : "1.7",
       "dependencies" : [
@@ -393,7 +393,7 @@
 
      "TRUFFLE_DEBUG" : {
       "path" : "build/truffle-debug.jar",
-      "subDir" : "graal",
+      "subDir" : "truffle",
       "sourcesPath" : "build/truffle-debug.src.zip",
       "javaCompliance" : "1.8",
       "dependencies" : [
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ArrayTestFactory.TestNode1NodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class ArrayTest {
+
+    @Test
+    public void testNode1() {
+        final TestNode1 node = TestNode1NodeGen.create(null);
+        RootNode root = new RootNode() {
+            @Child TestNode1 test = node;
+
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return test.executeWith(frame, frame.getArguments()[0]);
+            }
+        };
+        CallTarget target = Truffle.getRuntime().createCallTarget(root);
+
+        Assert.assertEquals(1, (int) target.call(1));
+        Assert.assertArrayEquals(new double[0], (double[]) target.call(new int[0]), 0.0d);
+        Assert.assertArrayEquals(new double[0], (double[]) target.call(new double[0]), 0.0d);
+        Assert.assertArrayEquals(new String[0], (String[]) target.call((Object) new String[0]));
+    }
+
+    @TypeSystemReference(ArrayTypeSystem.class)
+    abstract static class BaseNode extends Node {
+
+        abstract Object execute(VirtualFrame frame);
+
+        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            return ArrayTypeSystemGen.expectInteger(execute(frame));
+        }
+
+        int[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException {
+            return ArrayTypeSystemGen.expectIntArray(execute(frame));
+        }
+
+        String[] executeStringArray(VirtualFrame frame) throws UnexpectedResultException {
+            return ArrayTypeSystemGen.expectStringArray(execute(frame));
+        }
+
+        double[] executeDoubleArray(VirtualFrame frame) throws UnexpectedResultException {
+            return ArrayTypeSystemGen.expectDoubleArray(execute(frame));
+        }
+    }
+
+    @NodeChild
+    abstract static class TestNode1 extends BaseNode {
+
+        abstract Object executeWith(VirtualFrame frame, Object operand);
+
+        @Specialization
+        int doInt(int value) {
+            return value;
+        }
+
+        @Specialization
+        double[] doDoubleArray(double[] value) {
+            return value;
+        }
+
+        @Specialization
+        String[] doStringArray(String[] value) {
+            return value;
+        }
+
+    }
+
+    @TypeSystem({int.class, int[].class, double[].class, String[].class, Object[].class})
+    public static class ArrayTypeSystem {
+
+        @ImplicitCast
+        public static double[] castFromInt(int[] array) {
+            double[] newArray = new double[array.length];
+            for (int i = 0; i < array.length; i++) {
+                newArray[i] = array[i];
+            }
+            return newArray;
+        }
+
+        @TypeCheck(int[].class)
+        public static boolean isIntArray2(Object array) {
+            return array instanceof int[];
+        }
+
+        @TypeCast(int[].class)
+        public static int[] asIntArray(Object array) {
+            return (int[]) array;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/AssumptionsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.AssumptionArrayTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.CacheAssumptionTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.FieldTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.MethodTestFactory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.NodeFieldTest2Factory;
+import com.oracle.truffle.api.dsl.test.AssumptionsTestFactory.StaticFieldTestFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class AssumptionsTest {
+
+    @Test
+    public void testField() {
+        CallTarget root = createCallTarget(FieldTestFactory.getInstance());
+        FieldTest node = getNode(root);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        node.field.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class FieldTest extends ValueNode {
+
+        protected final Assumption field = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "field")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testNodeField() {
+        Assumption assumption = Truffle.getRuntime().createAssumption();
+        CallTarget root = createCallTarget(NodeFieldTest2Factory.getInstance(), assumption);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        assumption.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    @NodeField(name = "field", type = Assumption.class)
+    static class NodeFieldTest2 extends ValueNode {
+
+        @Specialization(assumptions = "field")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testStaticField() {
+        CallTarget root = createCallTarget(StaticFieldTestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        StaticFieldTest.FIELD.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class StaticFieldTest extends ValueNode {
+
+        static final Assumption FIELD = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "FIELD")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @Test
+    public void testMethod() {
+        CallTarget root = createCallTarget(MethodTestFactory.getInstance());
+        MethodTest node = getNode(root);
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(42));
+        node.hiddenAssumption.invalidate();
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class MethodTest extends ValueNode {
+
+        private final Assumption hiddenAssumption = Truffle.getRuntime().createAssumption();
+
+        @Specialization(assumptions = "getAssumption()")
+        static int do1(int value) {
+            return value;
+        }
+
+        Assumption getAssumption() {
+            return hiddenAssumption;
+        }
+    }
+
+    @Test
+    public void testCacheAssumption() {
+        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
+        CacheAssumptionTest node = getNode(root);
+        assertEquals("do1", root.call(42));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+        node.assumptions.get(42).invalidate();
+        node.assumptions.put(42, null); // clear 42
+        node.assumptions.get(43).invalidate();
+        node.assumptions.get(44).invalidate();
+        assertEquals("do1", root.call(42)); // recreates 42
+        assertEquals("do2", root.call(43)); // invalid 43 -> remove -> insert do2
+        assertEquals("do2", root.call(46)); // no more lines can be created.
+    }
+
+    @Test
+    public void testCacheAssumptionLimit() {
+        CallTarget root = createCallTarget(CacheAssumptionTestFactory.getInstance());
+        assertEquals("do1", root.call(42));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+        assertEquals("do2", root.call(45));
+        assertEquals("do1", root.call(43));
+        assertEquals("do1", root.call(44));
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    static class CacheAssumptionTest extends ValueNode {
+
+        private final Map<Integer, Assumption> assumptions = new HashMap<>();
+
+        @Specialization(guards = "value == cachedValue", assumptions = "getAssumption(cachedValue)")
+        static String do1(int value, @Cached("value") int cachedValue) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        Assumption getAssumption(int value) {
+            Assumption assumption = assumptions.get(value);
+            if (assumption == null) {
+                assumption = Truffle.getRuntime().createAssumption();
+                assumptions.put(value, assumption);
+            }
+            return assumption;
+        }
+    }
+
+    @Test
+    public void testAssumptionArrays() {
+        CallTarget root = createCallTarget(AssumptionArrayTestFactory.getInstance());
+        AssumptionArrayTest node = getNode(root);
+
+        Assumption a1 = Truffle.getRuntime().createAssumption();
+        Assumption a2 = Truffle.getRuntime().createAssumption();
+
+        node.assumptions = new Assumption[]{a1, a2};
+
+        assertEquals("do1", root.call(42));
+
+        a2.invalidate();
+
+        assertEquals("do2", root.call(42));
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    static class AssumptionArrayTest extends ValueNode {
+
+        Assumption[] assumptions;
+
+        @Specialization(assumptions = "assumptions")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+    }
+
+    @NodeChild
+    static class ErrorIncompatibleReturnType extends ValueNode {
+        @ExpectError("Incompatible return type int. Assumptions must be assignable to Assumption or Assumption[].")
+        @Specialization(assumptions = "3")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @NodeChild
+    static class ErrorBoundDynamicValue extends ValueNode {
+
+        @ExpectError("Assumption expressions must not bind dynamic parameter values.")
+        @Specialization(assumptions = "createAssumption(value)")
+        static int do1(int value) {
+            return value;
+        }
+
+        Assumption createAssumption(int value) {
+            return Truffle.getRuntime().createAssumption(String.valueOf(value));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BadLongOverflowSpecializationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BadLongOverflowSpecializationTestFactory.ImplicitCastExclusionFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class BadLongOverflowSpecializationTest {
+
+    /* Regression test for */
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    abstract static class ImplicitCastExclusion extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        String f1(long a) {
+            return "triggered1";
+        }
+
+        @Specialization
+        String f2(long a) {
+            return "triggered2";
+        }
+    }
+
+    @Test
+    public void testAdd() {
+        TestRootNode<ImplicitCastExclusion> node = createRoot(ImplicitCastExclusionFactory.getInstance());
+        assertEquals("triggered1", executeWith(node, -1));
+        assertEquals("triggered1", executeWith(node, 5000L));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BinaryNodeTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BinaryNodeTestFactory.AddNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class BinaryNodeTest {
+
+    @Test
+    public void testAdd() {
+        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
+        assertEquals(42, executeWith(node, 19, 23));
+        assertEquals(42d, executeWith(node, 19d, 23d));
+        assertEquals(42d, executeWith(node, "19", "23"));
+        assertEquals(42, executeWith(node, 19, 23));
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testAddUnsupported() {
+        TestRootNode<AddNode> node = createRoot(AddNodeFactory.getInstance());
+        executeWith(node, new Object(), new Object());
+    }
+
+    @NodeChildren({@NodeChild("left"), @NodeChild("right")})
+    abstract static class BinaryNode extends ValueNode {
+    }
+
+    abstract static class AddNode extends BinaryNode {
+
+        @Specialization
+        int add(int left, int right) {
+            return left + right;
+        }
+
+        @Fallback
+        Object add(Object left, Object right) {
+            return convertDouble(left) + convertDouble(right);
+        }
+
+        static double convertDouble(Object value) {
+            if (value instanceof Number) {
+                return ((Number) value).doubleValue();
+            } else if (value instanceof String) {
+                return Double.parseDouble((String) value);
+            }
+            throw new RuntimeException("Invalid datatype");
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/BoxedString.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+public class BoxedString {
+
+    private final String delegate;
+
+    public BoxedString(String delegate) {
+        this.delegate = delegate;
+    }
+
+    public String getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public String toString() {
+        return getDelegate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.BoundCacheOverflowFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestBoundCacheOverflowContainsFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheFieldFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheMethodFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestCacheNodeFieldFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithCachedAndDynamicParameterFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestGuardWithJustCachedParameterFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.TestMultipleCachesFactory;
+import com.oracle.truffle.api.dsl.test.CachedTestFactory.UnboundCacheFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+@SuppressWarnings("unused")
+public class CachedTest {
+
+    @Test
+    public void testUnboundCache() {
+        CallTarget root = createCallTarget(UnboundCacheFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(43));
+        assertEquals(42, root.call(44));
+    }
+
+    @NodeChild
+    static class UnboundCache extends ValueNode {
+        @Specialization
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+    }
+
+    @Test
+    public void testBoundCache() {
+        CallTarget root = createCallTarget(BoundCacheFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        assertEquals(44, root.call(44));
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class BoundCache extends ValueNode {
+
+        @Specialization(guards = "value == cachedValue", limit = "3")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+    }
+
+    @Test
+    public void testBoundCacheOverflow() {
+        CallTarget root = createCallTarget(BoundCacheOverflowFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        assertEquals(-1, root.call(44));
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        assertEquals(-1, root.call(44));
+    }
+
+    @NodeChild
+    static class BoundCacheOverflow extends ValueNode {
+
+        @Specialization(guards = "value == cachedValue", limit = "2")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+        @Specialization
+        static int do2(int value) {
+            return -1;
+        }
+
+    }
+
+    @Test
+    public void testBoundCacheOverflowContains() {
+        CallTarget root = createCallTarget(TestBoundCacheOverflowContainsFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        assertEquals(-1, root.call(44));
+        assertEquals(-1, root.call(42));
+        assertEquals(-1, root.call(43));
+        assertEquals(-1, root.call(44));
+    }
+
+    @NodeChild
+    static class TestBoundCacheOverflowContains extends ValueNode {
+
+        @Specialization(guards = "value == cachedValue", limit = "2")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+        @Specialization(contains = "do1")
+        static int do2(int value) {
+            return -1;
+        }
+
+    }
+
+    @Test
+    public void testCacheField() {
+        CallTarget root = createCallTarget(TestCacheFieldFactory.getInstance());
+        assertEquals(3, root.call(42));
+        assertEquals(3, root.call(43));
+    }
+
+    @NodeChild
+    static class TestCacheField extends ValueNode {
+
+        protected int field = 3;
+
+        @Specialization()
+        static int do1(int value, @Cached("field") int cachedValue) {
+            return cachedValue;
+        }
+
+    }
+
+    @Test
+    public void testCacheNodeField() {
+        CallTarget root = createCallTarget(TestCacheNodeFieldFactory.getInstance(), 21);
+        assertEquals(21, root.call(42));
+        assertEquals(21, root.call(43));
+    }
+
+    @NodeChild
+    @NodeField(name = "field", type = int.class)
+    static class TestCacheNodeField extends ValueNode {
+
+        @Specialization
+        static int do1(int value, @Cached("field") int cachedValue) {
+            return cachedValue;
+        }
+
+    }
+
+    @Test
+    public void testCacheMethod() {
+        TestCacheMethod.invocations = 0;
+        CallTarget root = createCallTarget(TestCacheMethodFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(43));
+        assertEquals(42, root.call(44));
+        assertEquals(1, TestCacheMethod.invocations);
+    }
+
+    @NodeChild
+    static class TestCacheMethod extends ValueNode {
+
+        static int invocations = 0;
+
+        @Specialization
+        static int do1(int value, @Cached("someMethod(value)") int cachedValue) {
+            return cachedValue;
+        }
+
+        static int someMethod(int value) {
+            invocations++;
+            return value;
+        }
+
+    }
+
+    @Test
+    public void testGuardWithJustCachedParameter() {
+        TestGuardWithJustCachedParameter.invocations = 0;
+        CallTarget root = createCallTarget(TestGuardWithJustCachedParameterFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(43));
+        assertEquals(42, root.call(44));
+        // guards with just cached parameters are just invoked on the slow path
+        assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithJustCachedParameter.invocations);
+    }
+
+    @NodeChild
+    static class TestGuardWithJustCachedParameter extends ValueNode {
+
+        static int invocations = 0;
+
+        @Specialization(guards = "someMethod(cachedValue)")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+        static boolean someMethod(int value) {
+            invocations++;
+            return true;
+        }
+
+    }
+
+    @Test
+    public void testGuardWithCachedAndDynamicParameter() {
+        TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations = 0;
+        TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations = 0;
+        CallTarget root = createCallTarget(TestGuardWithCachedAndDynamicParameterFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(42, root.call(43));
+        assertEquals(42, root.call(44));
+        // guards with just cached parameters are just invoked on the slow path
+        assertEquals(assertionsEnabled() ? 4 : 1, TestGuardWithCachedAndDynamicParameter.cachedMethodInvocations);
+        assertEquals(4, TestGuardWithCachedAndDynamicParameter.dynamicMethodInvocations);
+    }
+
+    @NodeChild
+    static class TestGuardWithCachedAndDynamicParameter extends ValueNode {
+
+        static int cachedMethodInvocations = 0;
+        static int dynamicMethodInvocations = 0;
+
+        @Specialization(guards = {"dynamicMethod(value)", "cachedMethod(cachedValue)"})
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+        static boolean cachedMethod(int value) {
+            cachedMethodInvocations++;
+            return true;
+        }
+
+        static boolean dynamicMethod(int value) {
+            dynamicMethodInvocations++;
+            return true;
+        }
+
+    }
+
+    /*
+     * Node should not produce any warnings in isIdentical of the generated code. Unnecessary casts
+     * were generated for isIdentical on the fast path.
+     */
+    @NodeChildren({@NodeChild, @NodeChild})
+    static class RegressionTestWarningInIsIdentical extends ValueNode {
+
+        @Specialization(guards = {"cachedName == name"})
+        protected Object directAccess(String receiver, String name, //
+                        @Cached("name") String cachedName, //
+                        @Cached("create(receiver, name)") Object callHandle) {
+            return receiver;
+        }
+
+        protected static Object create(String receiver, String name) {
+            return receiver;
+        }
+
+    }
+
+    @NodeChild
+    static class TestMultipleCaches extends ValueNode {
+
+        @Specialization
+        static int do1(int value, @Cached("value") int cachedValue1, @Cached("value") int cachedValue2) {
+            return cachedValue1 + cachedValue2;
+        }
+
+    }
+
+    @Test
+    public void testMultipleCaches() {
+        CallTarget root = createCallTarget(TestMultipleCachesFactory.getInstance());
+        assertEquals(42, root.call(21));
+        assertEquals(42, root.call(22));
+        assertEquals(42, root.call(23));
+    }
+
+    @NodeChild
+    static class CachedError1 extends ValueNode {
+        @Specialization
+        static int do1(int value, @ExpectError("Incompatible return type int. The expression type must be equal to the parameter type double.")//
+                        @Cached("value") double cachedValue) {
+            return value;
+        }
+    }
+
+    @NodeChild
+    static class CachedError2 extends ValueNode {
+
+        // caches are not allowed to make backward references
+
+        @Specialization
+        static int do1(int value,
+                        @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1,
+                        @Cached("value") int cachedValue2) {
+            return cachedValue1 + cachedValue2;
+        }
+
+    }
+
+    @NodeChild
+    static class CachedError3 extends ValueNode {
+
+        // cyclic dependency between cached expressions
+        @Specialization
+        static int do1(int value,
+                        @ExpectError("The initializer expression of parameter 'cachedValue1' binds unitialized parameter 'cachedValue2. Reorder the parameters to resolve the problem.") @Cached("cachedValue2") int cachedValue1,
+                        @Cached("cachedValue1") int cachedValue2) {
+            return cachedValue1 + cachedValue2;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CodeFormatTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.CodeFormatTestFactory.LineWrappingTestFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+/**
+ * Tests the generated code compiles without warnings for unusual large guard names.
+ */
+public class CodeFormatTest {
+
+    @Test
+    public void test() {
+        Assert.assertEquals(42, TestHelper.createCallTarget(LineWrappingTestFactory.create()).call());
+    }
+
+    abstract static class LineWrappingTest extends ValueNode {
+
+        public LineWrappingTest() {
+        }
+
+        protected static boolean guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1() {
+            return true;
+        }
+
+        protected static boolean guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2() {
+            return true;
+        }
+
+        @Specialization(guards = {"guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName2()",
+                        "guardWithaReeeeeeeeaaaaaaaaaaalllllllllyyyyyyyyLLLLLLLLLLLLLoooooooonnnnnnngggggggName1()"})
+        public int execute() {
+            return 42;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CompilerErrorTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class CompilerErrorTest {
+
+    abstract static class Visiblity01 extends ValueNode {
+
+        @Specialization
+        @SuppressWarnings("static-method")
+        @ExpectError("Method annotated with @Specialization must not be private.")
+        private Object s() {
+            return null;
+        }
+
+    }
+
+    @ExpectError("Classes containing a @Specialization annotation must not be private.")
+    private abstract static class Visiblity02 extends ValueNode {
+
+        @Specialization
+        public Object s() {
+            return null;
+        }
+
+    }
+
+    // assert no error
+    @ExpectError({})
+    private abstract static class Visiblity03 extends ValueNode {
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains1Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains2Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains3Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.Contains4Factory;
+import com.oracle.truffle.api.dsl.test.ContainsTestFactory.PolymorphicToMonomorphic0Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+@SuppressWarnings("unused")
+public class ContainsTest {
+
+    /*
+     * Tests a simple monomorphic inclusion.
+     */
+    @Test
+    public void testContains1() {
+        assertRuns(Contains1Factory.getInstance(), //
+                        array(1, "a", 2, "b"), //
+                        array(2, "aa", 3, "ba"), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (value instanceof String) {
+                                    if (node.getNode() instanceof DSLNode) {
+                                        // assert that the final specialization is always Object
+                                        Assert.assertEquals(Object.class, ((DSLNode) node.getNode()).getMetadata0().getSpecializedTypes()[0]);
+                                    } else {
+                                        Assert.assertTrue(((SpecializedNode) node.getNode()).getSpecializationNode().toString().startsWith("F2Node_"));
+                                    }
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains1 extends ValueNode {
+
+        @Specialization
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        Object f2(Object a) {
+            if (a instanceof Integer) {
+                return ((Integer) a) + 1;
+            }
+            return a + "a";
+        }
+    }
+
+    /*
+     * Tests an inclusion in within a polymorphic chain.
+     */
+    @Test
+    public void testContains2() {
+        assertRuns(Contains2Factory.getInstance(), //
+                        array(true, 1, 0, false), //
+                        array(false, -1, 1, true) //
+        );
+    }
+
+    @NodeChild("a")
+    abstract static class Contains2 extends ValueNode {
+
+        static boolean isZero(int a) {
+            return a == 0;
+        }
+
+        @Specialization(guards = "isZero(a)")
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1")
+        int f2(int a) {
+            if (a == 0) {
+                return a + 1;
+            }
+            return -a;
+        }
+
+        @Specialization
+        boolean f3(boolean a) {
+            return !a;
+        }
+    }
+
+    /*
+     * Tests transitive monomorphic inclusion.
+     */
+    @Test
+    public void testContains3() {
+        assertRuns(Contains3Factory.getInstance(), //
+                        array(2, 1, 2, -3, -4), //
+                        array(-2, 2, -2, -3, -4), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                // assert that we are always monomorphic
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains3 extends ValueNode {
+
+        static boolean isGreaterZero(int a) {
+            return a > 0;
+        }
+
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = {"isOne(a)"})
+        int f1(int a) {
+            return a + 1;
+        }
+
+        @Specialization(contains = "f1", guards = {"isGreaterZero(a)"})
+        int f2(int a) {
+            if (a == 1) {
+                return 2;
+            }
+            return -a;
+        }
+
+        @Specialization(contains = "f2")
+        int f3(int a) {
+            if (a > 0) {
+                return a == 1 ? 2 : -a;
+            } else {
+                return a;
+            }
+        }
+
+    }
+
+    /*
+     * Tests that if it can be derived that two specializations actually a as powerful as the latter
+     * we can combine them. Therefore operation should always become monomorphic in the end.
+     */
+    @Test
+    public void testContains4() {
+        assertRuns(Contains4Factory.getInstance(), //
+                        array(-1, 0, 1, 2), //
+                        array(1, 0, 1, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Assert.assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Contains4 extends ValueNode {
+
+        static boolean isOne(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "isOne(a)")
+        int f0(int a) {
+            return 1;
+        }
+
+        @Specialization(contains = "f0", guards = "a >= 0")
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(contains = {"f1"})
+        int f2(int a) {
+            return Math.abs(a);
+        }
+
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError1 extends ValueNode {
+        @ExpectError("The contained specialization 'f1' must be declared before the containing specialization.")
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object f1(String a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError2 extends ValueNode {
+
+        @ExpectError("The referenced specialization 'does not exist' could not be found.")
+        @Specialization(contains = "does not exist")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError3 extends ValueNode {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Duplicate contains declaration 'f0'.")
+        @Specialization(contains = {"f0", "f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError4 extends ValueNode {
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f1"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsError5 extends ValueNode {
+
+        @ExpectError({"Circular contained specialization 'f0(int)' found.", "Circular contained specialization 'f1(double)' found.",
+                        "The contained specialization 'f1' must be declared before the containing specialization."})
+        @Specialization(contains = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Circular contained specialization 'f1(double)' found.")
+        @Specialization(contains = {"f0"})
+        Object f1(double a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType1 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by f0(int).")
+        @Specialization(contains = "f0")
+        Object f1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType2 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(Object a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType3 extends ValueNode {
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(double a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class ContainsType4 extends ValueNode {
+        @Specialization
+        double f0(double a) {
+            return a;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0(double)."})
+        @Specialization(contains = "f0")
+        int f1(int a) { // implicit type
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType5 extends ValueNode {
+        @Specialization
+        Object f0(Object a, int b) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(int a, Object b) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class ContainsType6 extends ValueNode {
+        @Specialization
+        Object f0(double a, int b) {
+            return a;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1(int a, double b) { // implicit type
+            return a;
+        }
+    }
+
+    abstract static class ContainsGuard1 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1()")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard2 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization
+        Object f0() {
+            return null;
+        }
+
+        @ExpectError({"Specialization is not reachable. It is shadowed by f0()."})
+        @Specialization(guards = "g1()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard3 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        @Specialization(guards = "g1()")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "!g1()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard4 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1()")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard5 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1()")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard6 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = "g1()")
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "!g2()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsGuard7 extends ValueNode {
+
+        boolean g1() {
+            return true;
+        }
+
+        boolean g2() {
+            return true;
+        }
+
+        @Specialization(guards = {"g1()", "g2()"})
+        Object f0() {
+            return null;
+        }
+
+        @Specialization(guards = "g2()", contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsThrowable1 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0")
+        Object f1() {
+            return null;
+        }
+    }
+
+    abstract static class ContainsThrowable2 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        Object f0() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f0", rewriteOn = RuntimeException.class)
+        Object f1() throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "f1")
+        Object f2() {
+            return null;
+        }
+    }
+
+    @Test
+    public void testPolymorphicToMonomorphic0() {
+        TestRootNode<PolymorphicToMonomorphic0> root = createRoot(PolymorphicToMonomorphic0Factory.getInstance());
+        assertThat((int) executeWith(root, 1), is(1));
+        assertThat((int) executeWith(root, 2), is(2));
+        assertThat((int) executeWith(root, 3), is(3));
+        assertThat(root.getNode().getCost(), is(NodeCost.MONOMORPHIC));
+    }
+
+    @NodeChild("a")
+    static class PolymorphicToMonomorphic0 extends ValueNode {
+
+        @Specialization(guards = "a == 1")
+        int do1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "a == 2")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(contains = {"do1", "do2"})
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CreateCastTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode1Factory;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode2Factory;
+import com.oracle.truffle.api.dsl.test.CreateCastTestFactory.CreateCastNode3Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+@SuppressWarnings("unused")
+public class CreateCastTest {
+
+    @Test
+    public void testCastNode1() {
+        TestRootNode<CreateCastNode1> root = TestHelper.createRoot(CreateCastNode1Factory.getInstance());
+        Assert.assertEquals(1, root.getNode().invocations);
+    }
+
+    @Test
+    public void testCastNode2() {
+        TestRootNode<CreateCastNode2> root = TestHelper.createRoot(CreateCastNode2Factory.getInstance());
+        Assert.assertEquals(2, root.getNode().invocations);
+    }
+
+    @Test
+    public void testCastNode3() {
+        TestRootNode<CreateCastNode3> root = TestHelper.createRoot(CreateCastNode3Factory.getInstance());
+        Assert.assertEquals(1, root.getNode().invocations);
+    }
+
+    @NodeChild("a")
+    abstract static class CreateCastNode1 extends ValueNode {
+
+        int invocations = 0;
+
+        @CreateCast({"a"})
+        public ValueNode createCast(ValueNode node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class CreateCastNode2 extends ValueNode {
+
+        int invocations = 0;
+
+        @CreateCast({"a", "b"})
+        public ValueNode createCast(ValueNode node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a, int b) {
+            throw new AssertionError();
+        }
+    }
+
+    abstract static class CreateCastNode3 extends ChildrenNode {
+
+        int invocations = 0;
+
+        @CreateCast("children")
+        public ValueNode[] createCast(ValueNode[] node) {
+            invocations++;
+            return node;
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class CreateCastFailNode1 extends ValueNode {
+
+        @ExpectError({"Specified child '' not found."})
+        @CreateCast({""})
+        public ValueNode createCast(Node child) {
+            throw new AssertionError();
+        }
+
+        @Specialization
+        public int doInteger(int a) {
+            throw new AssertionError();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteEvaluatedTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.DoubleEvaluatedNodeFactory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.EvaluatedNodeFactory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedGenerationFactory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs0Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs1Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs2Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs3Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs4Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.TestEvaluatedVarArgs5Factory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated1NodeFactory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseDoubleEvaluated2NodeFactory;
+import com.oracle.truffle.api.dsl.test.ExecuteEvaluatedTestFactory.UseEvaluatedNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class ExecuteEvaluatedTest {
+
+    @Test
+    public void testSingleEvaluated() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(UseEvaluatedNodeFactory.create(arg0, EvaluatedNodeFactory.create(null)));
+
+        Assert.assertEquals(43, callTarget.call(new Object[]{42}));
+        Assert.assertEquals(1, arg0.getInvocationCount());
+    }
+
+    @NodeChild("exp")
+    abstract static class EvaluatedNode extends ValueNode {
+
+        @Specialization
+        int doExecuteWith(int exp) {
+            return exp + 1;
+        }
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object targetValue);
+
+        public abstract int executeIntEvaluated(VirtualFrame frame, Object targetValue) throws UnexpectedResultException;
+    }
+
+    @NodeChildren({@NodeChild("exp0"), @NodeChild(value = "exp1", type = EvaluatedNode.class, executeWith = "exp0")})
+    abstract static class UseEvaluatedNode extends ValueNode {
+
+        @Specialization
+        int call(int exp0, int exp1) {
+            Assert.assertEquals(exp0 + 1, exp1);
+            return exp1;
+        }
+    }
+
+    @Test
+    public void testDoubleEvaluated1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated1NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null)));
+
+        Assert.assertEquals(42, callTarget.call(new Object[]{43, 1}));
+        Assert.assertEquals(1, arg0.getInvocationCount());
+        Assert.assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1")})
+    abstract static class DoubleEvaluatedNode extends ValueNode {
+
+        @Specialization
+        int doExecuteWith(int exp0, int exp1) {
+            return exp0 - exp1;
+        }
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object exp0, Object exp1);
+
+        public abstract int executeIntEvaluated(VirtualFrame frame, Object exp0, Object exp1) throws UnexpectedResultException;
+    }
+
+    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp0", "exp1"})})
+    abstract static class UseDoubleEvaluated1Node extends ValueNode {
+
+        @Specialization
+        int call(int exp0, int exp1, int exp2) {
+            Assert.assertEquals(exp0 - exp1, exp2);
+            return exp2;
+        }
+    }
+
+    @Test
+    public void testDoubleEvaluated2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(UseDoubleEvaluated2NodeFactory.create(arg0, arg1, DoubleEvaluatedNodeFactory.create(null, null)));
+
+        Assert.assertEquals(42, callTarget.call(new Object[]{1, 43}));
+        Assert.assertEquals(1, arg0.getInvocationCount());
+        Assert.assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @NodeChildren({@NodeChild("exp0"), @NodeChild("exp1"), @NodeChild(value = "exp2", type = DoubleEvaluatedNode.class, executeWith = {"exp1", "exp0"})})
+    abstract static class UseDoubleEvaluated2Node extends ValueNode {
+
+        @Specialization
+        int call(int exp0, int exp1, int exp2) {
+            Assert.assertEquals(exp1 - exp0, exp2);
+            return exp2;
+        }
+    }
+
+    @Test
+    public void testEvaluatedGeneration() throws UnexpectedResultException {
+        TestRootNode<TestEvaluatedGeneration> root = TestHelper.createRoot(TestEvaluatedGenerationFactory.getInstance());
+
+        Assert.assertEquals(42, root.getNode().executeEvaluated1(null, 42));
+        Assert.assertEquals(42, root.getNode().executeEvaluated2(null, 42));
+        Assert.assertEquals(42, root.getNode().executeEvaluated3(null, 42));
+        Assert.assertEquals(42, root.getNode().executeEvaluated4(null, 42));
+    }
+
+    @NodeChildren({@NodeChild("exp0")})
+    abstract static class TestEvaluatedGeneration extends ValueNode {
+
+        public abstract Object executeEvaluated1(VirtualFrame frame, Object value);
+
+        public abstract Object executeEvaluated2(VirtualFrame frame, int value);
+
+        public abstract int executeEvaluated3(VirtualFrame frame, Object value) throws UnexpectedResultException;
+
+        public abstract int executeEvaluated4(VirtualFrame frame, int value) throws UnexpectedResultException;
+
+        @Specialization
+        int call(int exp0) {
+            return exp0;
+        }
+    }
+
+    @Test
+    public void test0VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs0> root = TestHelper.createRoot(TestEvaluatedVarArgs0Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null));
+    }
+
+    abstract static class TestEvaluatedVarArgs0 extends ChildrenNode {
+
+        @Override
+        public final Object execute(VirtualFrame frame) {
+            return execute1(frame);
+        }
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void test1VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs1> root = TestHelper.createRoot(TestEvaluatedVarArgs1Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null, 42));
+    }
+
+    @Test(expected = Throwable.class)
+    public void test1VarArgs2() {
+        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
+        root.getNode().execute1(null);
+    }
+
+    abstract static class TestEvaluatedVarArgs1 extends ChildrenNode {
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call(int exp0) {
+            return exp0;
+        }
+    }
+
+    @Test
+    public void test2VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null, 21, 21));
+    }
+
+    @Test(expected = Throwable.class)
+    public void test2VarArgs2() {
+        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
+        root.getNode().execute1(null, 42);
+    }
+
+    @Test(expected = Throwable.class)
+    public void test2VarArgs3() {
+        TestRootNode<TestEvaluatedVarArgs2> root = TestHelper.createRoot(TestEvaluatedVarArgs2Factory.getInstance());
+        root.getNode().execute1(null);
+    }
+
+    abstract static class TestEvaluatedVarArgs2 extends ChildrenNode {
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call(int exp0, int exp1) {
+            return exp0 + exp1;
+        }
+    }
+
+    @Test
+    public void test3VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs3> root = TestHelper.createRoot(TestEvaluatedVarArgs3Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null, 42));
+    }
+
+    @NodeChild
+    abstract static class TestEvaluatedVarArgs3 extends ValueNode {
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call(int exp0) {
+            return exp0;
+        }
+    }
+
+    @Test
+    public void test4VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs4> root = TestHelper.createRoot(TestEvaluatedVarArgs4Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null, 21, 21));
+    }
+
+    @NodeChildren({@NodeChild, @NodeChild})
+    abstract static class TestEvaluatedVarArgs4 extends ValueNode {
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call(int exp0, int exp1) {
+            return exp0 + exp1;
+        }
+    }
+
+    @Test
+    public void test5VarArgs1() {
+        TestRootNode<TestEvaluatedVarArgs5> root = TestHelper.createRoot(TestEvaluatedVarArgs5Factory.getInstance());
+        Assert.assertEquals(42, root.getNode().execute1(null));
+    }
+
+    abstract static class TestEvaluatedVarArgs5 extends ValueNode {
+
+        @Override
+        public final Object execute(VirtualFrame frame) {
+            return execute1(frame);
+        }
+
+        public abstract Object execute1(VirtualFrame frame, Object... value);
+
+        @Specialization
+        int call() {
+            return 42;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)})
+    abstract static class TestEvaluatedShortCircuit1 extends Node {
+
+        public abstract Object execute1(VirtualFrame frame, Object value);
+
+        public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB);
+
+        public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b);
+
+        @ShortCircuit("b")
+        public boolean needsB(Object a) {
+            return true;
+        }
+
+        @Specialization
+        int call(Object a, boolean hasB, Object b) {
+            return 42;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChildren({@NodeChild(value = "a", type = ValueNode.class), @NodeChild(value = "b", type = ValueNode.class)})
+    abstract static class TestEvaluatedShortCircuit2 extends Node {
+
+        public abstract Object execute1(VirtualFrame frame, Object value);
+
+        public abstract Object execute2(VirtualFrame frame, Object value, boolean hasB);
+
+        public abstract Object execute3(VirtualFrame frame, Object value, boolean hasB, Object b);
+
+        @ShortCircuit("b")
+        public boolean needsB(Object a) {
+            return true;
+        }
+
+        @Specialization
+        int call(int a, boolean hasB, int b) {
+            return 42;
+        }
+
+        @Specialization
+        int call(Object a, boolean hasB, Object b) {
+            return 42;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteGroupingTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ExecuteGroupingTestFactory.ExecuteGrouping1NodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/*
+ * This test aims to test the reuse of execute methods with evaluated parameters as much as possible.
+ */
+@RunWith(Theories.class)
+public class ExecuteGroupingTest {
+
+    @DataPoints public static final Object[] parameters = new Object[]{1, 2};
+
+    static final class ExecuteGroupingChild extends Node {
+
+        int invocationCount = 0;
+
+        private final Object returnValue;
+
+        public ExecuteGroupingChild(Object returnValue) {
+            this.returnValue = returnValue;
+        }
+
+        Object execute() {
+            invocationCount++;
+            return returnValue;
+        }
+
+    }
+
+    @Theory
+    public void testExecuteGrouping1Node(Object a, Object b, Object c) throws UnexpectedResultException {
+        ExecuteGroupingChild child0 = new ExecuteGroupingChild(a);
+        ExecuteGroupingChild child1 = new ExecuteGroupingChild(b);
+        ExecuteGroupingChild child2 = new ExecuteGroupingChild(c);
+
+        int result = ((int) a) + ((int) b) + ((int) c);
+
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute());
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(child0, child1, child2)).execute((VirtualFrame) null));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).execute(a));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, child1, child2)).executeInt(a));
+
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, b));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, b));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute(a, (int) b));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).execute((int) a, (int) b));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, child2)).executeInt((int) a, (int) b));
+
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute(a, b, c));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, c));
+        assertEquals(result, TestHelper.createRoot(ExecuteGrouping1NodeGen.create(null, null, null)).execute((int) a, (int) b, (int) c));
+
+    }
+
+    @NodeChildren({@NodeChild(type = ExecuteGroupingChild.class), @NodeChild(type = ExecuteGroupingChild.class), @NodeChild(type = ExecuteGroupingChild.class)})
+    abstract static class ExecuteGrouping1Node extends Node {
+
+        abstract Object execute();
+
+        int executeInt() throws UnexpectedResultException {
+            Object value = execute();
+            if (value instanceof Integer) {
+                return (int) value;
+            }
+            throw new UnexpectedResultException(value);
+        }
+
+        abstract double executeDouble() throws UnexpectedResultException;
+
+        abstract Object execute(VirtualFrame frame);
+
+        abstract Object execute(Object o1);
+
+        abstract int executeInt(Object o1) throws UnexpectedResultException;
+
+        abstract Object execute(Object o1, Object o2);
+
+        abstract Object execute(int o1, int o2);
+
+        abstract Object execute(int o1, int o2, Object o3);
+
+        abstract int executeInt(int o1, int o2) throws UnexpectedResultException;
+
+        abstract Object execute(Object o1, int o2);
+
+        abstract Object execute(int o1, Object o2);
+
+        abstract Object execute(Object o1, Object o2, Object o3);
+
+        abstract Object execute(int o1, int o2, int o3);
+
+        @Specialization
+        int s1(int a, int b, int c) {
+            return a + b + c;
+        }
+
+        @Specialization
+        int s2(Object a, Object b, Object c) {
+            return ((int) a) + ((int) b) + ((int) c);
+        }
+
+    }
+
+    abstract static class StrangeReturnCase extends Node {
+
+        // we don't know how to implement executeDouble
+        public abstract double executeDouble();
+
+        public int executeInt() {
+            return 42;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        double s1() {
+            return 42;
+        }
+
+        @Specialization
+        double s2() {
+            return 42;
+        }
+
+    }
+
+    @ExpectError("Incompatible abstract execute methods found %")
+    abstract static class IncompatibleAbstract1 extends Node {
+
+        // we don't know how to implement executeDouble
+        abstract double executeDouble();
+
+        abstract int executeInt();
+
+        @Specialization
+        double s1() {
+            return 42;
+        }
+
+    }
+
+    abstract static class IncompatibleAbstract2 extends Node {
+
+        abstract double executeDouble();
+
+        // we can resolve duplicate path errors by making an execute method final
+        @SuppressWarnings("static-method")
+        public final int executeInt() {
+            return 42;
+        }
+
+        @ExpectError("The provided return type \"int\" does not match expected return type \"double\".%")
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s1() {
+            return 42;
+        }
+
+        @Specialization
+        double s2() {
+            return 42;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExecuteMethodTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class ExecuteMethodTest {
+
+    private static final String ERROR_NO_EXECUTE = "No accessible and overridable generic execute method found. Generic execute methods usually have the signature 'public abstract {Type} "
+                    + "execute(VirtualFrame)' and must not throw any checked exceptions.";
+
+    @TypeSystem({int.class})
+    @DSLOptions(useNewLayout = true)
+    static class ExecuteMethodTypes {
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    abstract static class ChildNoFrame extends Node {
+        abstract Object execute();
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError(ERROR_NO_EXECUTE)
+    abstract static class ExecuteThis1 extends Node {
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError(ERROR_NO_EXECUTE)
+    abstract static class ExecuteThis2 extends Node {
+
+        abstract Object execute() throws UnexpectedResultException;
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError(ERROR_NO_EXECUTE)
+    abstract static class ExecuteThis3 extends Node {
+
+        abstract int execute() throws UnexpectedResultException;
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThis4 extends Node {
+
+        protected abstract Object execute();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThis5 extends Node {
+
+        public abstract Object execute();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError(ERROR_NO_EXECUTE)
+    abstract static class ExecuteThis6 extends Node {
+
+        @SuppressWarnings({"unused", "static-method"})
+        private Object execute() {
+            return 0;
+        }
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError(ERROR_NO_EXECUTE)
+    abstract static class ExecuteThis7 extends Node {
+
+        @SuppressWarnings("static-method")
+        public final int executeInt() {
+            return 0;
+        }
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThis8 extends Node {
+
+        abstract int executeInt();
+
+        abstract Object executeObject();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThis9 extends Node {
+
+        abstract int executeInt();
+
+        // disambiguate executeObject
+        final Object executeObject() {
+            return executeInt();
+        }
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThisVoid1 extends Node {
+
+        abstract void executeVoid();
+
+        @Specialization
+        void doInt(@SuppressWarnings("unused") int a) {
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThisVoid2 extends Node {
+
+        // allow one execute void
+        abstract void executeVoid();
+
+        abstract Object executeObject();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteThisVoid3 extends Node {
+
+        // allow only one execute void
+        abstract void executeVoid1();
+
+        abstract void executeVoid2();
+
+        abstract Object executeObject();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrame1 extends Node {
+
+        // no frame in execute. no parameter in specializations
+        abstract Object executeNoFrame();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrame2 extends Node {
+
+        // frame in execute also usable in specialization
+        abstract Object executeWithFrame(VirtualFrame frame);
+
+        @Specialization
+        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrame3 extends Node {
+
+        abstract Object executeWithFrame(Frame frame);
+
+        @Specialization
+        int doInt(@SuppressWarnings("unused") Frame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ExecuteWithFrame4.class)
+    abstract static class ExecuteWithFrame4 extends Node {
+
+        abstract Object executeWithFrame(MaterializedFrame frame);
+
+        @Specialization
+        int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrameError1 extends Node {
+
+        abstract Object executeNoFrame();
+
+        @Specialization
+        @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%")
+        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrameError2 extends Node {
+
+        abstract Object executeFrame(MaterializedFrame frame);
+
+        @Specialization
+        @ExpectError("Method signature (VirtualFrame, int) does not match to the expected signature:%")
+        int doInt(@SuppressWarnings("unused") VirtualFrame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrameError3 extends Node {
+
+        abstract Object executeFrame(VirtualFrame frame);
+
+        @Specialization
+        @ExpectError("Method signature (MaterializedFrame, int) does not match to the expected signature:%")
+        int doInt(@SuppressWarnings("unused") MaterializedFrame frame, int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    @ExpectError("Invalid inconsistent frame types [MaterializedFrame, VirtualFrame] found for the declared execute methods.%")
+    abstract static class ExecuteWithFrameError4 extends Node {
+
+        abstract Object execute(VirtualFrame frame);
+
+        abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException;
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteWithFrameError5 extends Node {
+
+        abstract Object execute();
+
+        abstract int executeInt(MaterializedFrame frame) throws UnexpectedResultException;
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    abstract static class ChildVirtualFrame extends Node {
+        abstract Object execute(VirtualFrame frame);
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    abstract static class ChildMaterializedFrame extends Node {
+        abstract Object execute(MaterializedFrame frame);
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    abstract static class ChildFrame extends Node {
+        abstract Object execute(Frame frame);
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildNoFrame.class)
+    abstract static class ExecuteChildFrame1 extends Node {
+
+        abstract Object execute(VirtualFrame frame);
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildFrame.class)
+    abstract static class ExecuteChildFrame2 extends Node {
+
+        abstract Object execute(VirtualFrame frame);
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildFrame.class)
+    abstract static class ExecuteChildFrame3 extends Node {
+
+        abstract Object execute(MaterializedFrame frame);
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildFrame.class)
+    abstract static class ExecuteChildFrame4 extends Node {
+
+        abstract Object execute(Frame frame);
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [com.oracle.truffle.api.frame.Frame].")
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildVirtualFrame.class)
+    abstract static class ExecuteChildFrameError1 extends Node {
+
+        abstract Object execute(Frame frame);
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildFrame and frame types [].")
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildFrame.class)
+    abstract static class ExecuteChildFrameError2 extends Node {
+
+        abstract Object execute();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+    @ExpectError("No generic execute method found with 0 evaluated arguments for node type ChildVirtualFrame and frame types [].")
+    @TypeSystemReference(ExecuteMethodTypes.class)
+    @NodeChild(value = "a", type = ChildVirtualFrame.class)
+    abstract static class ExecuteChildFrameError3 extends Node {
+
+        abstract Object execute();
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ExpectError.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation is internally known by the dsl processor and used to expect errors for testing
+ * purposes. This is not part of public API.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ExpectError {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/FallbackTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback1Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback2Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback3Factory;
+import com.oracle.truffle.api.dsl.test.FallbackTestFactory.Fallback4Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class FallbackTest {
+
+    private static final Object UNKNOWN_OBJECT = new Object() {
+    };
+
+    @Test
+    public void testFallback1() {
+        assertRuns(Fallback1Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", "(fallback)"));
+    }
+
+    /**
+     * Test with fallback handler defined.
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback1 extends ValueNode {
+
+        @Override
+        public abstract String executeString(VirtualFrame frame);
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Fallback
+        String f2(Object a) {
+            return "(fallback)";
+        }
+    }
+
+    @Test
+    public void testFallback2() {
+        assertRuns(Fallback2Factory.getInstance(), //
+                        array(42, UNKNOWN_OBJECT), //
+                        array("(int)", UnsupportedSpecializationException.class));
+    }
+
+    /**
+     * Test without fallback handler defined.
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback2 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+    }
+
+    @Test
+    public void testFallback3() {
+        assertRuns(Fallback3Factory.getInstance(), //
+                        array(42, 43, UNKNOWN_OBJECT, "somestring"), //
+                        array("(int)", "(int)", "(object)", "(object)"));
+    }
+
+    /**
+     * Test without fallback handler and unreachable.
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback3 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization(guards = "notInt(a)")
+        String f2(Object a) {
+            return "(object)";
+        }
+
+        boolean notInt(Object value) {
+            return !(value instanceof Integer);
+        }
+
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in polymorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback4() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        Assert.assertEquals("(boolean)", executeWith(node, true));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    /**
+     * Test without fallback handler and unreachable.
+     */
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback4 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+
+        @Specialization
+        String f2(boolean a) {
+            return "(boolean)";
+        }
+    }
+
+    /**
+     * Tests the contents of the {@link UnsupportedSpecializationException} contents in monomorphic
+     * nodes.
+     */
+    @Test
+    public void testFallback5() {
+        TestRootNode<Fallback4> node = createRoot(Fallback4Factory.getInstance());
+
+        Assert.assertEquals("(int)", executeWith(node, 1));
+        try {
+            executeWith(node, UNKNOWN_OBJECT);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertEquals(node.getNode(), e.getNode());
+            Assert.assertArrayEquals(NodeUtil.findNodeChildren(node.getNode()).subList(0, 1).toArray(new Node[0]), e.getSuppliedNodes());
+            Assert.assertArrayEquals(new Object[]{UNKNOWN_OBJECT}, e.getSuppliedValues());
+        }
+    }
+
+    // test without fallback handler and unreachable
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class Fallback5 extends ValueNode {
+
+        @Specialization
+        String f1(int a) {
+            return "(int)";
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImplicitCastTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast0NodeFactory;
+import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast1NodeFactory;
+import com.oracle.truffle.api.dsl.test.ImplicitCastTestFactory.ImplicitCast2NodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+
+public class ImplicitCastTest {
+
+    @TypeSystem({int.class, String.class, boolean.class})
+    static class ImplicitCast0Types {
+
+        @ImplicitCast
+        static boolean castInt(int intvalue) {
+            return intvalue == 1 ? true : false;
+        }
+
+        @ImplicitCast
+        static boolean castString(String strvalue) {
+            return strvalue.equals("1");
+        }
+
+    }
+
+    @TypeSystemReference(ImplicitCast0Types.class)
+    @NodeChild(value = "operand", type = ImplicitCast0Node.class)
+    abstract static class ImplicitCast0Node extends ValueNode {
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object value2);
+
+        @Specialization
+        public String op1(String value) {
+            return value;
+        }
+
+        @Specialization
+        public boolean op1(boolean value) {
+            return value;
+        }
+
+    }
+
+    @Test
+    public void testImplicitCast0() {
+        ImplicitCast0Node node = ImplicitCast0NodeFactory.create(null);
+        TestRootNode<ImplicitCast0Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
+        Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true));
+    }
+
+    @TypeSystemReference(ImplicitCast0Types.class)
+    @NodeChild(value = "operand", type = ImplicitCast1Node.class)
+    abstract static class ImplicitCast1Node extends ValueNode {
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object operand);
+
+        @Specialization
+        public String op0(String value) {
+            return value;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        public boolean op1(@SuppressWarnings("unused") boolean value) throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "op1")
+        public boolean op2(boolean value) {
+            return value;
+        }
+
+    }
+
+    @Test
+    public void testImplicitCast1() {
+        ImplicitCast1Node node = ImplicitCast1NodeFactory.create(null);
+        TestRootNode<ImplicitCast1Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
+        Assert.assertEquals("2", root.getNode().executeEvaluated(null, "2"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals("1", root.getNode().executeEvaluated(null, "1"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true));
+    }
+
+    @TypeSystemReference(ImplicitCast0Types.class)
+    @NodeChildren({@NodeChild(value = "operand0", type = ImplicitCast2Node.class), @NodeChild(value = "operand1", type = ImplicitCast2Node.class, executeWith = "operand0")})
+    // TODO temporary workaround
+    abstract static class ImplicitCast2Node extends ValueNode {
+
+        @Specialization
+        public String op0(String v0, String v1) {
+            return v0 + v1;
+        }
+
+        @SuppressWarnings("unused")
+        @Specialization(rewriteOn = RuntimeException.class)
+        public boolean op1(boolean v0, boolean v1) throws RuntimeException {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "op1")
+        public boolean op2(boolean v0, boolean v1) {
+            return v0 && v1;
+        }
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object v1);
+
+        public abstract Object executeEvaluated(VirtualFrame frame, Object v1, Object v2);
+
+        public abstract Object executeEvaluated(VirtualFrame frame, boolean v1, boolean v2);
+
+    }
+
+    @Test
+    public void testImplicitCast2() {
+        ImplicitCast2Node node = ImplicitCast2NodeFactory.create(null, null);
+        TestRootNode<ImplicitCast2Node> root = new TestRootNode<>(node);
+        root.adoptChildren();
+        Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1));
+        Assert.assertEquals("42", root.getNode().executeEvaluated(null, "4", "2"));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, 1, 1));
+        Assert.assertEquals(true, root.getNode().executeEvaluated(null, true, true));
+    }
+
+    @TypeSystem({String.class, boolean.class})
+    static class ImplicitCastError1 {
+
+        @ImplicitCast
+        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
+        static String castInvalid(@SuppressWarnings("unused") String value) {
+            throw new AssertionError();
+        }
+
+    }
+
+    @TypeSystem({String.class, boolean.class})
+    static class ImplicitCastError2 {
+
+        @ImplicitCast
+        @ExpectError("Target type and source type of an @ImplicitCast must not be the same type.")
+        static String castInvalid(@SuppressWarnings("unused") String value) {
+            throw new AssertionError();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ImportGuardsTestFactory.ImportGuards6Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ImportGuardsTest {
+
+    @ImportStatic(Imports0.class)
+    @NodeChild("a")
+    static class ImportGuards0 extends ValueNode {
+
+        @Specialization(guards = "staticGuard(a)")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+    @NodeChild("a")
+    @ImportStatic(Imports0.class)
+    static class ImportGuards1 extends ValueNode {
+
+        @ExpectError("Error parsing expression 'nonStaticGuard(a)': The method nonStaticGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "nonStaticGuard(a)")
+        int f1(int a) {
+            return a;
+        }
+
+        @ExpectError("Error parsing expression 'protectedGuard(a)': The method protectedGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "protectedGuard(a)")
+        int f2(int a) {
+            return a;
+        }
+
+        @ExpectError("Error parsing expression 'packageGuard(a)': The method packageGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "packageGuard(a)")
+        int f3(int a) {
+            return a;
+        }
+
+        @ExpectError("Error parsing expression 'privateGuard(a)': The method privateGuard is undefined for the enclosing scope.")
+        @Specialization(guards = "privateGuard(a)")
+        int f4(int a) {
+            return a;
+        }
+    }
+
+    public static class Imports0 {
+        public static boolean staticGuard(int a) {
+            return a == 0;
+        }
+
+        public boolean nonStaticGuard(int a) {
+            return a == 0;
+        }
+
+        protected static boolean protectedGuard(int a) {
+            return a == 0;
+        }
+
+        static boolean packageGuard(int a) {
+            return a == 0;
+        }
+
+        @SuppressWarnings("unused")
+        private static boolean privateGuard(int a) {
+            return a == 0;
+        }
+
+    }
+
+    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports1' must be public.")
+    @NodeChild("a")
+    @ImportStatic(Imports1.class)
+    static class ImportGuards2 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    static class Imports1 {
+
+    }
+
+    @ExpectError("The specified import guard class 'com.oracle.truffle.api.dsl.test.ImportGuardsTest.Imports2' must be public.")
+    @NodeChild("a")
+    @ImportStatic(Imports2.class)
+    static class ImportGuards3 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @ExpectError("The specified import guard class 'boolean' is not a declared type.")
+    @NodeChild("a")
+    @ImportStatic(boolean.class)
+    static class ImportGuards4 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    private static class Imports2 {
+
+    }
+
+    @ExpectError("At least import guard classes must be specified.")
+    @NodeChild("a")
+    @ImportStatic({})
+    static class ImportGuards5 extends ValueNode {
+
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testImportGuards6() {
+        // should use the guar declared in the node instead of the imported one.
+        assertRuns(ImportGuards6Factory.getInstance(), //
+                        array(1, 1), //
+                        array(1, 1));
+    }
+
+    @ImportStatic(Imports0.class)
+    @NodeChild("a")
+    static class ImportGuards6 extends ValueNode {
+
+        static boolean staticGuard(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "staticGuard(a)")
+        int f0(int a) {
+            return a;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/InsertBeforeTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class InsertBeforeTest {
+
+    @NodeChild("a")
+    static class InsertBefore1Base extends ValueNode {
+
+        @Specialization(guards = "a == 1")
+        int f1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "a == 2")
+        int f3(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T1 extends InsertBefore1Base {
+
+        @Specialization
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T2 extends InsertBefore1Base {
+
+        @Specialization(guards = "a == 0", insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T3 extends InsertBefore1Base {
+
+        @Specialization(guards = "a == 0", insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int).",
+                    "Method f1(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T4 extends InsertBefore1Base {
+
+        @Specialization(insertBefore = "f1")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    @ExpectError({"Method f3(int) at annotation @Specialization is erroneous: Specialization is not reachable. It is shadowed by f0(int)."})
+    static class InsertBefore1T5 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f3")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T6part1 extends InsertBefore1Base {
+
+        boolean g0(int a) {
+            return a == 0;
+        }
+
+        @Specialization(insertBefore = "f1", guards = "a == 0")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1T6part2 extends InsertBefore1T6part1 {
+
+        @Specialization(insertBefore = "f0", guards = "a == 3")
+        int f(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error1 extends InsertBefore1Base {
+
+        @ExpectError("Specializations can only be inserted before specializations in superclasses.")
+        @Specialization(insertBefore = "f0")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild("a")
+    static class InsertBefore1Error2 extends InsertBefore1Base {
+
+        @ExpectError("The referenced specialization 'asdf' could not be found.")
+        @Specialization(insertBefore = "asdf")
+        int f0(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/IntegerLiteralGuardsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.BinaryLiteralTestFactory;
+import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.DecimalLiteralTestFactory;
+import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.HexLiteralTestFactory;
+import com.oracle.truffle.api.dsl.test.IntegerLiteralGuardsTestFactory.OctalLiteralTestFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+@SuppressWarnings("unused")
+public class IntegerLiteralGuardsTest {
+
+    @Test
+    public void testDecimalLiteral() {
+        CallTarget root = createCallTarget(DecimalLiteralTestFactory.getInstance());
+        assertEquals("do1", root.call(14));
+    }
+
+    @NodeChild
+    static class DecimalLiteralTest extends ValueNode {
+        @Specialization(guards = "value == 14")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testHexLiteral() {
+        CallTarget root = createCallTarget(HexLiteralTestFactory.getInstance());
+        assertEquals("do1", root.call(20));
+    }
+
+    @NodeChild
+    static class HexLiteralTest extends ValueNode {
+        @Specialization(guards = "value == 0x14")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testOctalLiteral() {
+        CallTarget root = createCallTarget(OctalLiteralTestFactory.getInstance());
+        assertEquals("do1", root.call(12));
+    }
+
+    @NodeChild
+    static class OctalLiteralTest extends ValueNode {
+        @Specialization(guards = "value == 014")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testBinaryLiteral() {
+        CallTarget root = createCallTarget(BinaryLiteralTestFactory.getInstance());
+        assertEquals("do1", root.call(50));
+    }
+
+    @NodeChild
+    static class BinaryLiteralTest extends ValueNode {
+        @Specialization(guards = "value == 0b110010")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LazyClassLoadingTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.LazyClassLoadingTestFactory.TestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class LazyClassLoadingTest {
+    @Test
+    public void test() {
+        String factoryName = TestNodeFactory.class.getName();
+        String nodeName = factoryName + "$" + TestNode.class.getSimpleName() + "Gen";
+        Assert.assertTrue(isLoaded(factoryName));
+        Assert.assertFalse(isLoaded(nodeName));
+
+        NodeFactory<TestNode> factory = TestNodeFactory.getInstance();
+        Assert.assertTrue(isLoaded(factoryName));
+        Assert.assertTrue(isLoaded(nodeName));
+
+        Assert.assertFalse(isLoaded(nodeName + "$UninitializedNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$BaseNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$IntNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
+
+        TestRootNode<TestNode> root = TestHelper.createRoot(factory);
+
+        Assert.assertTrue(isLoaded(nodeName + "$UninitializedNode_"));
+        Assert.assertTrue(isLoaded(nodeName + "$BaseNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$IntNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
+
+        Assert.assertEquals(42, TestHelper.executeWith(root, 42));
+
+        Assert.assertTrue(isLoaded(nodeName + "$IntNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$BooleanNode_"));
+        Assert.assertFalse(isLoaded(nodeName + "$PolymorphicNode_"));
+
+        Assert.assertEquals(true, TestHelper.executeWith(root, true));
+
+        Assert.assertTrue(isLoaded(nodeName + "$IntNode_"));
+        Assert.assertTrue(isLoaded(nodeName + "$BooleanNode_"));
+        Assert.assertTrue(isLoaded(nodeName + "$PolymorphicNode_"));
+    }
+
+    private boolean isLoaded(String className) {
+        ClassLoader classLoader = getClass().getClassLoader();
+        Method m;
+        try {
+            m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
+            m.setAccessible(true);
+            return m.invoke(classLoader, className) != null;
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class TestNode extends ValueNode {
+
+        @Specialization
+        int doInt(int a) {
+            return a;
+        }
+
+        @Specialization
+        boolean doBoolean(boolean a) {
+            return a;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/LimitTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.LimitTestFactory.ConstantLimitTestFactory;
+import com.oracle.truffle.api.dsl.test.LimitTestFactory.DefaultLimit3TestFactory;
+import com.oracle.truffle.api.dsl.test.LimitTestFactory.LocalLimitTestFactory;
+import com.oracle.truffle.api.dsl.test.LimitTestFactory.MethodLimitTestFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+@SuppressWarnings("unused")
+public class LimitTest {
+
+    @Test
+    public void testDefaultLimit3() {
+        CallTarget root = createCallTarget(DefaultLimit3TestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        assertEquals(44, root.call(44));
+        try {
+            root.call(45);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class DefaultLimit3Test extends ValueNode {
+        @Specialization(guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+    }
+
+    @Test
+    public void testConstantLimit() {
+        CallTarget root = createCallTarget(ConstantLimitTestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        try {
+            root.call(44);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class ConstantLimitTest extends ValueNode {
+
+        public static final int LIMIT = 2;
+
+        @Specialization(limit = "LIMIT", guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+    }
+
+    @Test
+    public void testLocalLimit() {
+        CallTarget root = createCallTarget(LocalLimitTestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        try {
+            root.call(44);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+    }
+
+    @NodeChild
+    static class LocalLimitTest extends ValueNode {
+
+        protected int localLimit = 2;
+
+        @Specialization(limit = "localLimit", guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+    }
+
+    @Test
+    public void testMethodLimit() {
+        MethodLimitTest.invocations = 0;
+        CallTarget root = createCallTarget(MethodLimitTestFactory.getInstance());
+        assertEquals(42, root.call(42));
+        assertEquals(43, root.call(43));
+        try {
+            root.call(44);
+            fail();
+        } catch (UnsupportedSpecializationException e) {
+        }
+        assertEquals(3, MethodLimitTest.invocations);
+    }
+
+    @NodeChild
+    static class MethodLimitTest extends ValueNode {
+
+        static int invocations = 0;
+
+        @Specialization(limit = "calculateLimitFor(cachedValue, invocations)", guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return cachedValue;
+        }
+
+        int calculateLimitFor(int cachedValue, int boundField) {
+            invocations = boundField + 1;
+            return 2;
+        }
+
+    }
+
+    @NodeChild
+    static class LimitErrorTest1 extends ValueNode {
+        @ExpectError("The limit expression has no effect.%")
+        @Specialization(limit = "4")
+        static int do1(int value) {
+            return value;
+        }
+    }
+
+    @NodeChild
+    static class LimitErrorTest2 extends ValueNode {
+        public static final Object CONSTANT = new Object();
+
+        @ExpectError("Incompatible return type Object. Limit expressions must return int.")
+        @Specialization(limit = "CONSTANT", guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return value;
+        }
+    }
+
+    @NodeChild
+    static class LimitErrorTest3 extends ValueNode {
+
+        public static final Object CONSTANT = new Object();
+
+        @ExpectError("Limit expressions must not bind dynamic parameter values.")
+        @Specialization(limit = "value", guards = "value == cachedValue")
+        static int do1(int value, @Cached("value") int cachedValue) {
+            return value;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MergeSpecializationsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestCachedNodeFactory;
+import com.oracle.truffle.api.dsl.test.MergeSpecializationsTestFactory.TestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+public class MergeSpecializationsTest {
+
+    private static final int THREADS = 50;
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    abstract static class TestNode extends ValueNode {
+
+        @Specialization
+        int s1(int a) {
+            return 1;
+        }
+
+        @Specialization
+        int s2(long a) {
+            return 2;
+        }
+
+        @Specialization
+        int s3(double a) {
+            return 3;
+        }
+    }
+
+    @NodeChild
+    @SuppressWarnings("unused")
+    abstract static class TestCachedNode extends ValueNode {
+
+        @Specialization(guards = "a == cachedA", limit = "3")
+        int s1(int a, @Cached("a") int cachedA) {
+            return 1;
+        }
+
+        @Specialization
+        int s2(long a) {
+            return 2;
+        }
+
+        @Specialization
+        int s3(double a) {
+            return 3;
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeInOrder() {
+        for (int i = 0; i < 100; i++) {
+            multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeReverse() {
+        for (int i = 0; i < 100; i++) {
+            multithreadedMerge(TestNodeFactory.getInstance(), new Executions(1.0, 1L << 32, 1), 3, 2, 1);
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeCachedInOrder() {
+        for (int i = 0; i < 100; i++) {
+            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 1L << 32, 1.0), 1, 2, 3);
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeCachedTwoEntries() {
+        for (int i = 0; i < 100; i++) {
+            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 1.0), 1, 1, 3);
+        }
+    }
+
+    @Test
+    public void testMultithreadedMergeCachedThreeEntries() {
+        for (int i = 0; i < 100; i++) {
+            multithreadedMerge(TestCachedNodeFactory.getInstance(), new Executions(1, 2, 3), 1, 1, 1);
+        }
+    }
+
+    private static <T extends ValueNode> void multithreadedMerge(NodeFactory<T> factory, final Executions executions, int... order) {
+        assertEquals(3, order.length);
+        final TestRootNode<T> node = createRoot(factory);
+
+        final CountDownLatch threadsStarted = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeFirst = new CountDownLatch(1);
+        final CountDownLatch executedFirst = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeSecond = new CountDownLatch(1);
+        final CountDownLatch executedSecond = new CountDownLatch(THREADS);
+
+        final CountDownLatch beforeThird = new CountDownLatch(1);
+        final CountDownLatch executedThird = new CountDownLatch(THREADS);
+
+        Thread[] threads = new Thread[THREADS];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(new Runnable() {
+                public void run() {
+                    threadsStarted.countDown();
+
+                    MergeSpecializationsTest.await(beforeFirst);
+                    executeWith(node, executions.firstValue);
+                    executedFirst.countDown();
+
+                    MergeSpecializationsTest.await(beforeSecond);
+                    executeWith(node, executions.secondValue);
+                    executedSecond.countDown();
+
+                    MergeSpecializationsTest.await(beforeThird);
+                    executeWith(node, executions.thirdValue);
+                    executedThird.countDown();
+                }
+            });
+            threads[i].start();
+        }
+
+        final SpecializedNode gen = (SpecializedNode) node.getNode();
+
+        final SpecializationNode start0 = gen.getSpecializationNode();
+        assertEquals("UninitializedNode_", start0.getClass().getSimpleName());
+
+        await(threadsStarted);
+        beforeFirst.countDown();
+        await(executedFirst);
+
+        final SpecializationNode start1 = gen.getSpecializationNode();
+        assertEquals("S" + order[0] + "Node_", start1.getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(1, start1).getClass().getSimpleName());
+
+        beforeSecond.countDown();
+        await(executedSecond);
+
+        final SpecializationNode start2 = gen.getSpecializationNode();
+        Arrays.sort(order, 0, 2);
+        assertEquals("PolymorphicNode_", start2.getClass().getSimpleName());
+        assertEquals("S" + order[0] + "Node_", nthChild(1, start2).getClass().getSimpleName());
+        assertEquals("S" + order[1] + "Node_", nthChild(2, start2).getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(3, start2).getClass().getSimpleName());
+
+        beforeThird.countDown();
+        await(executedThird);
+
+        final SpecializationNode start3 = gen.getSpecializationNode();
+        Arrays.sort(order);
+        assertEquals("PolymorphicNode_", start3.getClass().getSimpleName());
+        assertEquals("S" + order[0] + "Node_", nthChild(1, start3).getClass().getSimpleName());
+        assertEquals("S" + order[1] + "Node_", nthChild(2, start3).getClass().getSimpleName());
+        assertEquals("S" + order[2] + "Node_", nthChild(3, start3).getClass().getSimpleName());
+        assertEquals("UninitializedNode_", nthChild(4, start3).getClass().getSimpleName());
+
+        for (Thread thread : threads) {
+            try {
+                thread.join();
+            } catch (InterruptedException e) {
+                fail("interrupted");
+            }
+        }
+    }
+
+    private static class Executions {
+        public final Object firstValue;
+        public final Object secondValue;
+        public final Object thirdValue;
+
+        public Executions(Object firstValue, Object secondValue, Object thirdValue) {
+            this.firstValue = firstValue;
+            this.secondValue = secondValue;
+            this.thirdValue = thirdValue;
+        }
+    }
+
+    private static void await(final CountDownLatch latch) {
+        try {
+            latch.await();
+        } catch (InterruptedException e) {
+            fail("interrupted");
+        }
+    }
+
+    private static Node firstChild(Node node) {
+        return node.getChildren().iterator().next();
+    }
+
+    private static Node nthChild(int n, Node node) {
+        if (n == 0) {
+            return node;
+        } else {
+            return nthChild(n - 1, firstChild(node));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardCompareWithFieldTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardComplexTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualByteIntTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualIntLongTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualLongIntTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualShortIntTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardEqualTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardFieldTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterEqualTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardGreaterTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessEqualTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardLessTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMethodTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleAndMethodTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardMultipleOrMethodTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardNotTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardOrTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardStaticFieldTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardStaticFinalFieldCompareTestFactory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsTestFactory.GuardUnboundMethodTestFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+@SuppressWarnings("unused")
+public class MethodGuardsTest {
+
+    @Test
+    public void testGuardEqual() {
+        CallTarget root = createCallTarget(GuardEqualTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(1));
+    }
+
+    @NodeChild
+    static class GuardEqualTest extends ValueNode {
+        @Specialization(guards = "value == 1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardEqualIntLong() {
+        CallTarget root = createCallTarget(GuardEqualIntLongTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(1));
+    }
+
+    @NodeChild
+    static class GuardEqualIntLongTest extends ValueNode {
+        @Specialization(guards = "1 == value")
+        static String do1(long value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(long value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardEqualByteInt() {
+        CallTarget root = createCallTarget(GuardEqualByteIntTestFactory.getInstance());
+        assertEquals("do1", root.call((byte) 1));
+        assertEquals("do2", root.call((byte) 2));
+        assertEquals("do1", root.call((byte) 1));
+    }
+
+    @NodeChild
+    static class GuardEqualByteIntTest extends ValueNode {
+        @Specialization(guards = "value == 1")
+        static String do1(byte value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(byte value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardEqualShortInt() {
+        CallTarget root = createCallTarget(GuardEqualShortIntTestFactory.getInstance());
+        assertEquals("do1", root.call((short) 1));
+        assertEquals("do2", root.call((short) 2));
+        assertEquals("do1", root.call((short) 1));
+    }
+
+    @NodeChild
+    static class GuardEqualShortIntTest extends ValueNode {
+        @Specialization(guards = "value == 1")
+        static String do1(short value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(short value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardEqualLongInt() {
+        CallTarget root = createCallTarget(GuardEqualLongIntTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(1));
+    }
+
+    @NodeChild
+    static class GuardEqualLongIntTest extends ValueNode {
+        @Specialization(guards = "value == 1")
+        static String do1(long value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(long value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardLessEqual() {
+        CallTarget root = createCallTarget(GuardLessEqualTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(0));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardLessEqualTest extends ValueNode {
+        @Specialization(guards = "value <= 1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardLess() {
+        CallTarget root = createCallTarget(GuardLessTestFactory.getInstance());
+        assertEquals("do1", root.call(0));
+        assertEquals("do2", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(-1));
+    }
+
+    @NodeChild
+    static class GuardLessTest extends ValueNode {
+        @Specialization(guards = "value < 1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardGreaterEqual() {
+        CallTarget root = createCallTarget(GuardGreaterEqualTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(0));
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardGreaterEqualTest extends ValueNode {
+        @Specialization(guards = "value >= 1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardGreater() {
+        CallTarget root = createCallTarget(GuardGreaterTestFactory.getInstance());
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(0));
+        assertEquals("do2", root.call(1));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardGreaterTest extends ValueNode {
+        @Specialization(guards = "value > 1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardOr() {
+        CallTarget root = createCallTarget(GuardOrTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(0));
+        assertEquals("do2", root.call(2));
+        assertEquals("do2", root.call(-1));
+    }
+
+    @NodeChild
+    static class GuardOrTest extends ValueNode {
+        @Specialization(guards = "value == 1 || value == 0")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardNot() {
+        CallTarget root = createCallTarget(GuardNotTestFactory.getInstance());
+        assertEquals("do1", root.call(0));
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(1));
+        assertEquals("do1", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardNotTest extends ValueNode {
+        @Specialization(guards = "!(value == 1)")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardField() {
+        CallTarget root = createCallTarget(GuardFieldTestFactory.getInstance());
+        GuardFieldTest node = getNode(root);
+        node.field = true;
+        assertEquals("do1", root.call(0));
+        assertEquals("do1", root.call(2));
+
+        node.field = false;
+        try {
+            root.call(2);
+            fail("expected Assertion failed");
+        } catch (AssertionError e) {
+        }
+    }
+
+    @NodeChild
+    static class GuardFieldTest extends ValueNode {
+
+        boolean field;
+
+        @Specialization(guards = "field")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardCompareWithField() {
+        CallTarget root = createCallTarget(GuardCompareWithFieldTestFactory.getInstance());
+        GuardCompareWithFieldTest node = getNode(root);
+        node.field = 1;
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+
+        node.field = 2;
+        assertEquals("do2", root.call(1));
+        assertEquals("do1", root.call(2));
+    }
+
+    @NodeChild
+    static class GuardCompareWithFieldTest extends ValueNode {
+
+        int field;
+
+        @Specialization(guards = "value == field")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardStaticField() {
+        CallTarget root = createCallTarget(GuardStaticFieldTestFactory.getInstance());
+        GuardStaticFieldTest.field = true;
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(2));
+        GuardStaticFieldTest.field = false;
+        try {
+            root.call(2);
+            fail("expected Assertion failed");
+        } catch (AssertionError e) {
+        }
+    }
+
+    @NodeChild
+    static class GuardStaticFieldTest extends ValueNode {
+
+        static boolean field;
+
+        @Specialization(guards = "field")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardStaticFinalFieldCompare() {
+        CallTarget root = createCallTarget(GuardStaticFinalFieldCompareTestFactory.getInstance());
+        GuardStaticFieldTest.field = true;
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+    }
+
+    @NodeChild
+    static class GuardStaticFinalFieldCompareTest extends ValueNode {
+
+        protected static final int FIELD = 1;
+
+        @Specialization(guards = "value == FIELD")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization(guards = "value != FIELD")
+        static String do2(int value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testGuardMethod() {
+        CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardMethodTest extends ValueNode {
+
+        @Specialization(guards = "method(value)")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        boolean method(int value) {
+            return value == 1;
+        }
+    }
+
+    @Test
+    public void testGuardUnboundMethodField() {
+        CallTarget root = createCallTarget(GuardUnboundMethodTestFactory.getInstance());
+        GuardUnboundMethodTest node = getNode(root);
+        node.hiddenValue = true;
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(2));
+        node.hiddenValue = false;
+        try {
+            root.call(2);
+            fail("expected Assertion failed");
+        } catch (AssertionError e) {
+        }
+    }
+
+    @NodeChild
+    static class GuardUnboundMethodTest extends ValueNode {
+
+        private boolean hiddenValue;
+
+        @Specialization(guards = "method()")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        boolean method() {
+            return hiddenValue;
+        }
+    }
+
+    @Test
+    public void testStaticGuardMethod() {
+        CallTarget root = createCallTarget(GuardMethodTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(2));
+        assertEquals("do1", root.call(1));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class StaticGuardMethodTest extends ValueNode {
+
+        @Specialization(guards = "method(value)")
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        static boolean method(int value) {
+            return value == 1;
+        }
+    }
+
+    @Test
+    public void testMultipleGuardAndMethod() {
+        CallTarget root = createCallTarget(GuardMultipleAndMethodTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(3));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardMultipleAndMethodTest extends ValueNode {
+
+        @Specialization(guards = {"method1(value)", "method2(value)"})
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        boolean method1(int value) {
+            return value >= 1;
+        }
+
+        boolean method2(int value) {
+            return value <= 2;
+        }
+    }
+
+    @Test
+    public void testMultipleGuardOrMethod() {
+        CallTarget root = createCallTarget(GuardMultipleOrMethodTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(3));
+        assertEquals("do2", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardMultipleOrMethodTest extends ValueNode {
+
+        @Specialization(guards = {"method1(value) || method2(value)"})
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        boolean method1(int value) {
+            return value == 1;
+        }
+
+        boolean method2(int value) {
+            return value == 2;
+        }
+    }
+
+    @Test
+    public void testComplexGuard() {
+        CallTarget root = createCallTarget(GuardComplexTestFactory.getInstance());
+        assertEquals("do1", root.call(1));
+        assertEquals("do1", root.call(2));
+        assertEquals("do2", root.call(3));
+        assertEquals("do1", root.call(0));
+    }
+
+    @NodeChild
+    static class GuardComplexTest extends ValueNode {
+
+        int field1 = 1;
+        static int field2 = 2;
+
+        @Specialization(guards = {"method2(method1(field1 == 1), value <= 2)", "field2 == 2"})
+        static String do1(int value) {
+            return "do1";
+        }
+
+        @Specialization
+        static String do2(int value) {
+            return "do2";
+        }
+
+        static boolean method1(boolean value) {
+            return value;
+        }
+
+        boolean method2(boolean value1, boolean value2) {
+            return value1 && value2;
+        }
+    }
+
+    @NodeChild
+    static class ErrorGuardNotTest extends ValueNode {
+        @ExpectError("Error parsing expression '!value == 1': The operator ! is undefined for the argument type int.")
+        @Specialization(guards = "!value == 1")
+        static String do1(int value) {
+            return "do1";
+        }
+    }
+
+    @NodeChild
+    static class ErrorIncompatibleReturnTypeTest extends ValueNode {
+
+        @ExpectError("Incompatible return type int. Guards must return boolean.")
+        @Specialization(guards = "1")
+        static String do1(int value) {
+            return "do1";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArguments1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble0Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble1Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble2Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsDouble3Factory;
+import com.oracle.truffle.api.dsl.test.MethodGuardsWithArgumentsTestFactory.MArgumentsSingle2Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class MethodGuardsWithArgumentsTest {
+
+    @Test
+    public void testMArguments0() {
+        TestRootNode<MArguments0> root = createRoot(MArguments0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArguments1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class MArguments1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle0() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "guard()")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle1() {
+        TestRootNode<MArguments1> root = createRoot(MArguments1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle1 extends ValueNode {
+
+        static boolean guard(int a) {
+            return a == 42;
+        }
+
+        @Specialization(guards = "guard(a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsSingle2() {
+        TestRootNode<MArgumentsSingle2> root = createRoot(MArgumentsSingle2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsSingle2 extends ValueNode {
+
+        static boolean guard(int a1, int a2) {
+            return a1 == 42 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble0() {
+        TestRootNode<MArgumentsDouble0> root = createRoot(MArgumentsDouble0Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 0));
+    }
+
+    @NodeChild("a")
+    abstract static class MArgumentsDouble0 extends ValueNode {
+
+        static boolean guard(int a1, Object a2) {
+            return a1 == 42 && a2.equals(new Integer(42));
+        }
+
+        @Specialization(guards = "guard(a,a)")
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble1() {
+        TestRootNode<MArgumentsDouble1> root = createRoot(MArgumentsDouble1Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble1 extends ValueNode {
+
+        static boolean guard(int a1, double a2) {
+            return a1 == 42 && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(a,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble2() {
+        TestRootNode<MArgumentsDouble2> root = createRoot(MArgumentsDouble2Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble2 extends ValueNode {
+
+        static boolean guard(double a1, int a2) {
+            return a1 == 41 && a2 == 42;
+        }
+
+        @Specialization(guards = "guard(b,a)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    @Test
+    public void testMArgumentsDouble3() {
+        TestRootNode<MArgumentsDouble3> root = createRoot(MArgumentsDouble3Factory.getInstance());
+        Assert.assertEquals(42, executeWith(root, 42, 41.0));
+    }
+
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class MArgumentsDouble3 extends ValueNode {
+
+        static boolean guard(Object a1, double a2) {
+            return new Double(41.0).equals(a1) && a2 == 41;
+        }
+
+        @Specialization(guards = "guard(b,b)")
+        int do1(int a, @SuppressWarnings("unused") double b) {
+            return a;
+        }
+    }
+
+    abstract static class MArgumentsError0 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Error parsing expression 'guard(': -- line 1 col 7: \")\" expected%")
+        @Specialization(guards = "guard(")
+        int do1() {
+            return 42;
+        }
+    }
+
+    abstract static class MArgumentsError1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Error parsing expression 'guard)': -- line 1 col 6: EOF expected%")
+        @Specialization(guards = "guard)")
+        int do1() {
+            return 42;
+        }
+
+    }
+
+    abstract static class MArgumentsError2 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
+        @Specialization(guards = "guard(a)")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @NodeChild("b")
+    abstract static class MArgumentsError3 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Error parsing expression 'guard(a)': a cannot be resolved.")
+        @Specialization(guards = "guard(a)")
+        int do1(int b) {
+            return b;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NameDuplicationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NameDuplicationTest {
+
+    @NodeChild
+    abstract static class Test0 extends ValueNode {
+
+        @Specialization
+        int base(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild
+    abstract static class Test1 extends ValueNode {
+
+        @Specialization
+        int generic(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild
+    abstract static class Test2 extends ValueNode {
+
+        @Specialization
+        int polymorphic(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChild
+    abstract static class Test3 extends ValueNode {
+
+        @Specialization
+        int uninitialized(int a) {
+            return a;
+        }
+
+    }
+
+    abstract static class AddNode extends ValueNode {
+
+        @Specialization
+        int add() {
+            return 0;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NegatedGuardsTestFactory.NegatedGuardNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NegatedGuardsTest {
+
+    @Test
+    public void testGuardGlobal() {
+        TestRootNode<NegatedGuardNode> root = createRoot(NegatedGuardNodeFactory.getInstance());
+        Assert.assertEquals(42, executeWith(root));
+    }
+
+    abstract static class NegatedGuardNode extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @Specialization(guards = "!guard()")
+        int do1() {
+            throw new AssertionError();
+        }
+
+        @Specialization
+        int do2() {
+            return 42; // the generic answer to all questions
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NoTypeSystemTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.JustFrameTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.NoParameterTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectInterfaceNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectPrimitiveTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.ObjectStringTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.PrimitiveTestNodeGen;
+import com.oracle.truffle.api.dsl.test.NoTypeSystemTestFactory.TypesNotInTypeSystemTestNodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class NoTypeSystemTest {
+
+    abstract static class DummyChild extends Node {
+        abstract Object execute();
+    }
+
+    abstract static class NoParameterTestNode extends Node {
+        abstract void execute();
+
+        @Specialization
+        void s1() {
+        }
+    }
+
+    @Test
+    public void testNoParameter() {
+        NoParameterTestNodeGen.create().execute();
+    }
+
+    abstract static class JustFrameTestNode extends Node {
+
+        abstract void execute(VirtualFrame frames);
+
+        @Specialization
+        void s1(@SuppressWarnings("unused") VirtualFrame frame) {
+        }
+    }
+
+    @Test
+    public void testJustFrame() {
+        JustFrameTestNodeGen.create().execute(null);
+    }
+
+    abstract static class PrimitiveTestNode extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+    }
+
+    @Test
+    public void testPrimitive() {
+        Assert.assertEquals(42, PrimitiveTestNodeGen.create().execute(42));
+    }
+
+    abstract static class ObjectInterfaceNode extends Node {
+
+        abstract CharSequence execute(Object operand);
+
+        @Specialization
+        CharSequence s1(CharSequence operandSpecial) {
+            return operandSpecial;
+        }
+    }
+
+    @Test
+    public void testObjectInterface() {
+        Assert.assertEquals("42", ObjectInterfaceNodeGen.create().execute("42"));
+    }
+
+    abstract static class ObjectPrimitiveTestNode extends Node {
+
+        abstract int execute(Object primitive);
+
+        @Specialization
+        int s1(int primitive) {
+            return primitive;
+        }
+
+    }
+
+    @Test
+    public void testObjectPrimitiveTest() {
+        Assert.assertEquals(42, ObjectPrimitiveTestNodeGen.create().execute(42));
+    }
+
+    abstract static class ObjectStringTestNode extends Node {
+
+        abstract String execute(Object operand);
+
+        @Specialization
+        String s1(String operand) {
+            return operand;
+        }
+    }
+
+    @Test
+    public void testObjectStringTest() {
+        Assert.assertEquals("42", ObjectStringTestNodeGen.create().execute("42"));
+    }
+
+    abstract static class TypesNotInTypeSystemTest extends Node {
+
+        abstract Object execute(Object primitive);
+
+        abstract int executeInt(Object primitive) throws UnexpectedResultException;
+
+        abstract double executeDouble(Object primitive) throws UnexpectedResultException;
+
+        abstract String executeString(Object primitive) throws UnexpectedResultException;
+
+        abstract int[] executeIntArray(Object primitive) throws UnexpectedResultException;
+
+        abstract void executeVoid(Object primitive);
+
+        abstract void executeChar(Object primitive);
+
+        abstract int executeInt(int primitive) throws UnexpectedResultException;
+
+        abstract double executeDouble(double primitive) throws UnexpectedResultException;
+
+        abstract String executeString(String primitive) throws UnexpectedResultException;
+
+        abstract int[] executeIntArray(int[] primitive) throws UnexpectedResultException;
+
+        abstract void executeChar(char primitive);
+
+        @Specialization
+        int s1(int primitive) {
+            return primitive;
+        }
+
+        @Specialization
+        double s2(double primitive) {
+            return (int) primitive;
+        }
+
+        @Specialization
+        String s3(String object) {
+            return object;
+        }
+
+        @Specialization
+        int[] s4(int[] object) {
+            return object;
+        }
+
+        @Specialization
+        void s5(@SuppressWarnings("unused") char object) {
+        }
+
+    }
+
+    @Test
+    public void testTypesNotInTypeSystem() throws UnexpectedResultException {
+        int[] someArray = {1, 2, 3};
+        Assert.assertEquals(42, createTypesNotInTypeSystem().execute(42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().execute(42d));
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().execute(someArray));
+        Assert.assertNull(createTypesNotInTypeSystem().execute((char) 42));
+
+        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt((Object) 42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble((Object) 42d), 0d);
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray((Object) someArray));
+        createTypesNotInTypeSystem().executeChar((Object) (char) 42);
+
+        Assert.assertEquals(42, createTypesNotInTypeSystem().executeInt(42));
+        Assert.assertEquals(42d, createTypesNotInTypeSystem().executeDouble(42d), 0d);
+        Assert.assertEquals(someArray, createTypesNotInTypeSystem().executeIntArray(someArray));
+        createTypesNotInTypeSystem().executeChar((char) 42);
+
+        try {
+            createTypesNotInTypeSystem().executeInt("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        try {
+            createTypesNotInTypeSystem().executeDouble("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        try {
+            createTypesNotInTypeSystem().executeIntArray("a");
+            Assert.fail();
+        } catch (UnexpectedResultException e) {
+        }
+
+        createTypesNotInTypeSystem().executeChar("a");
+
+    }
+
+    private static TypesNotInTypeSystemTest createTypesNotInTypeSystem() {
+        return TestHelper.createRoot(TypesNotInTypeSystemTestNodeGen.create());
+    }
+
+    abstract static class ErrorImpossibleTypes1 extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+        @ExpectError("The provided return type \"Object\" does not match expected return type \"int\".%")
+        @Specialization
+        Object s2(int arg0) {
+            return arg0;
+        }
+    }
+
+    abstract static class ErrorImpossibleTypes2 extends Node {
+
+        abstract int execute(int primitive);
+
+        @Specialization
+        int test(int primitive) {
+            return primitive;
+        }
+
+        @ExpectError("Method signature (Object) does not match to the expected signature: %")
+        @Specialization
+        int s2(Object arg0) {
+            return (int) arg0;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
+    abstract static class ErrorMissingNodeChild1 extends Node {
+
+        abstract int execute();
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
+    @NodeChild(type = DummyChild.class)
+    abstract static class ErrorMissingNodeChild2 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0, int arg1) {
+            return arg0 + arg1;
+        }
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 1: [execute()].")
+    abstract static class ErrorMissingNodeChild3 extends Node {
+
+        abstract int execute();
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+
+    }
+
+    @ExpectError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.")
+    @NodeChild(type = DummyChild.class)
+    abstract static class ErrorAdditionalNodeChild1 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0) {
+            return arg0;
+        }
+    }
+
+    @NodeChild(type = DummyChild.class)
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 2: [execute(int)].")
+    abstract static class ErrorAdditionalNodeChild2 extends Node {
+
+        abstract int execute(int arg0);
+
+        @Specialization
+        int s1(int arg0, int arg1) {
+            return arg0 + arg1;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildNoNameTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.OneArgNoNameFactory;
+import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.ThreeArgsNoNameFactory;
+import com.oracle.truffle.api.dsl.test.NodeChildNoNameTestFactory.TwoArgsNoNameFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+
+public class NodeChildNoNameTest {
+
+    @Test
+    public void testOneArg() {
+        ValueNode node = new ConstantNode();
+        OneArgNoName arg = OneArgNoNameFactory.create(node);
+        Assert.assertEquals(node, arg.getChild0());
+        Assert.assertEquals(43, TestHelper.createCallTarget(arg).call());
+    }
+
+    @Test
+    public void testTwoArg() {
+        ValueNode node1 = new ConstantNode();
+        ValueNode node2 = new ConstantNode();
+        TwoArgsNoName arg = TwoArgsNoNameFactory.create(node1, node2);
+        Assert.assertEquals(node1, arg.getChild0());
+        Assert.assertEquals(node2, arg.getChild1());
+        Assert.assertEquals(84, TestHelper.createCallTarget(arg).call());
+    }
+
+    @Test
+    public void testThreeArg() {
+        ValueNode node1 = new ConstantNode();
+        ValueNode node2 = new ConstantNode();
+        ValueNode node3 = new ConstantNode();
+        ThreeArgsNoName arg = ThreeArgsNoNameFactory.create(node1, node2, node3);
+        Assert.assertEquals(node1, arg.getChild0());
+        Assert.assertEquals(node2, arg.getChild1());
+        Assert.assertEquals(node3, arg.getChild2());
+        Assert.assertEquals(126, TestHelper.createCallTarget(arg).call());
+    }
+
+    private static class ConstantNode extends ValueNode {
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return 42;
+        }
+    }
+
+    @NodeChild
+    abstract static class OneArgNoName extends ValueNode {
+
+        public abstract ValueNode getChild0();
+
+        @Specialization
+        int doIt(int exp) {
+            return exp + 1;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild, @NodeChild})
+    abstract static class TwoArgsNoName extends ValueNode {
+
+        public abstract ValueNode getChild0();
+
+        public abstract ValueNode getChild1();
+
+        @Specialization
+        int doIt(int exp0, int exp1) {
+            return exp0 + exp1;
+        }
+    }
+
+    @NodeChildren({@NodeChild, @NodeChild, @NodeChild})
+    abstract static class ThreeArgsNoName extends ValueNode {
+
+        public abstract ValueNode getChild0();
+
+        public abstract ValueNode getChild1();
+
+        public abstract ValueNode getChild2();
+
+        @Specialization
+        int doIt(int exp0, int exp1, int exp2) {
+            return exp0 + exp1 + exp2;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NodeChildTest {
+
+    @Test
+    public void testIntField() {
+        assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call());
+    }
+
+    @NodeChild("child0")
+    abstract static class Base0Node extends ValueNode {
+
+    }
+
+    @NodeChild(value = "child1", type = ValueNode.class)
+    abstract static class Child0Node extends Base0Node {
+
+        @Specialization
+        int intField(int child0, int child1) {
+            return child0 + child1;
+        }
+    }
+
+    @NodeChildren({@NodeChild("child0")})
+    abstract static class Base1Node extends ValueNode {
+
+    }
+
+    @NodeChildren({@NodeChild(value = "child1", type = ValueNode.class)})
+    abstract static class Child1Node extends Base1Node {
+
+        @Specialization
+        int intField(int child0, int child1) {
+            return child0 + child1;
+        }
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    abstract static class Base2Node extends ValueNode {
+
+    }
+
+    @ExpectError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                    + "The following execute methods do not provide all evaluated values for the expected signature size 3:%")
+    @NodeChildren({@NodeChild(value = "child2", type = ValueNode.class)})
+    abstract static class Child2Node extends Base1Node {
+
+        @ExpectError("Method signature (int, int, int) does not match to the expected signature:%")
+        @Specialization
+        int intField(int child0, int child1, int child2) {
+            return child0 + child1 + child2;
+        }
+    }
+
+    @NodeChildren({@NodeChild(value = "receiver", type = ValueNode.class), @NodeChild(value = "arguments", type = ValueNode[].class)})
+    abstract static class BaseNode extends ValueNode {
+        public abstract ValueNode getReceiver();
+
+        public abstract ValueNode[] getArguments();
+    }
+
+    abstract static class UnaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value) {
+            return value;
+        }
+    }
+
+    abstract static class BinaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value0, int value1) {
+            return value0 + value1;
+        }
+    }
+
+    abstract static class TernaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value0, int value1, int value2) {
+            return value0 + value1 + value2;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NodeFieldTest {
+
+    @Test
+    public void testIntField() {
+        assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call());
+    }
+
+    @NodeField(name = "field", type = int.class)
+    abstract static class IntFieldTestNode extends ValueNode {
+
+        public abstract int getField();
+
+        @Specialization
+        int intField() {
+            return getField();
+        }
+
+    }
+
+    @Test
+    public void testIntFieldNoGetter() {
+        assertEquals(42, createCallTarget(IntFieldNoGetterTestNodeFactory.create(42)).call());
+    }
+
+    @NodeField(name = "field", type = int.class)
+    abstract static class IntFieldNoGetterTestNode extends ValueNode {
+
+        @Specialization
+        int intField(int field) {
+            return field;
+        }
+
+    }
+
+    @Test
+    public void testMultipleFields() {
+        assertEquals(42, createCallTarget(MultipleFieldsTestNodeFactory.create(21, 21)).call());
+    }
+
+    @NodeFields({@NodeField(name = "field0", type = int.class), @NodeField(name = "field1", type = int.class)})
+    abstract static class MultipleFieldsTestNode extends ValueNode {
+
+        public abstract int getField0();
+
+        public abstract int getField1();
+
+        @Specialization
+        int intField() {
+            return getField0() + getField1();
+        }
+
+    }
+
+    @Test
+    public void testStringField() {
+        assertEquals("42", createCallTarget(StringFieldTestNodeFactory.create("42")).call());
+    }
+
+    @NodeField(name = "field", type = String.class)
+    abstract static class StringFieldTestNode extends ValueNode {
+
+        public abstract String getField();
+
+        @Specialization
+        String stringField() {
+            return getField();
+        }
+
+    }
+
+    @Test
+    public void testRewrite() {
+        assertEquals("42", createCallTarget(RewriteTestNodeFactory.create("42")).call());
+    }
+
+    @NodeField(name = "field", type = String.class)
+    abstract static class RewriteTestNode extends ValueNode {
+
+        public abstract String getField();
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        String alwaysRewrite() {
+            throw new RuntimeException();
+        }
+
+        @Specialization(contains = "alwaysRewrite")
+        Object returnField() {
+            return getField();
+        }
+    }
+
+    @Test
+    public void testStringContainer() {
+        assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call());
+    }
+
+    @NodeField(name = "field", type = int.class)
+    abstract static class IntContainerNode extends ValueNode {
+
+        public abstract int getField();
+
+    }
+
+    @NodeField(name = "anotherField", type = String.class)
+    abstract static class TestContainer extends ValueNode {
+
+        @Specialization
+        int containerField(String field) {
+            return field.equals("42") ? 42 : -1;
+        }
+
+    }
+
+    @Test
+    public void testObjectContainer() {
+        assertEquals("42", createCallTarget(ObjectContainerNodeFactory.create("42")).call());
+    }
+
+    @NodeField(name = "object", type = Object.class)
+    abstract static class ObjectContainerNode extends ValueNode {
+
+        public abstract Object getObject();
+
+        @Specialization
+        Object containerField() {
+            return getObject();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullLiteralGuardsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareNotNullNodeFactory;
+import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareObjectsNullNodeFactory;
+import com.oracle.truffle.api.dsl.test.NullLiteralGuardsTestFactory.CompareStringNullNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
+
+@SuppressWarnings("unused")
+public class NullLiteralGuardsTest {
+
+    @Test
+    public void testCompareObjectsNull() {
+        CallTarget root = createCallTarget(CompareObjectsNullNodeFactory.getInstance());
+        assertEquals("do1", root.call((Object) null));
+        assertEquals("do2", root.call("42"));
+    }
+
+    abstract static class CompareObjectsNullNode extends ChildrenNode {
+        @Specialization(guards = "value == null")
+        String do1(Object value) {
+            return "do1";
+        }
+
+        @Specialization
+        String do2(Object value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testCompareStringNull() {
+        CallTarget root = createCallTarget(CompareStringNullNodeFactory.getInstance());
+        assertEquals("do1", root.call("42"));
+        assertEquals("do2", root.call((Object) null));
+    }
+
+    abstract static class CompareStringNullNode extends ChildrenNode {
+        @Specialization(guards = "value != null")
+        String do1(String value) {
+            return "do1";
+        }
+
+        @Specialization
+        String do2(Object value) {
+            return "do2";
+        }
+    }
+
+    @Test
+    public void testCompareNotNull() {
+        CallTarget root = createCallTarget(CompareNotNullNodeFactory.getInstance());
+        assertEquals("do1", root.call("42"));
+        assertEquals("do2", root.call((Object) null));
+    }
+
+    abstract static class CompareNotNullNode extends ChildrenNode {
+        @Specialization(guards = "value != null")
+        String do1(Object value) {
+            return "do1";
+        }
+
+        @Specialization
+        String do2(Object value) {
+            return "do2";
+        }
+    }
+
+    abstract static class ErrorNullIntComparison1 extends ChildrenNode {
+        @ExpectError("Error parsing expression 'value == null': Incompatible operand types int and null.")
+        @Specialization(guards = "value == null")
+        String do1(int value) {
+            return "do1";
+        }
+    }
+
+    abstract static class ErrorNullIntComparison2 extends ChildrenNode {
+        @ExpectError("Error parsing expression '1 == null': Incompatible operand types int and null.")
+        @Specialization(guards = "1 == null")
+        String do1(int value) {
+            return "do1";
+        }
+    }
+
+    abstract static class ErrorNullNullComparison extends ChildrenNode {
+        @ExpectError("Error parsing expression 'null == null': The operator == is undefined for the argument type(s) null null.")
+        @Specialization(guards = "null == null")
+        String do1(int value) {
+            return "do1";
+        }
+    }
+
+    abstract static class ErrorObjectVoidComparison extends ChildrenNode {
+        protected static void returnVoid() {
+        }
+
+        @ExpectError("Error parsing expression 'value == returnVoid()': Incompatible operand types Object and void.")
+        @Specialization(guards = "value == returnVoid()")
+        String do1(Object value) {
+            return "do1";
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NullTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NullTestFactory.NullTest1Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NullTest {
+
+    @Test
+    public void testGuardInvocations() {
+        TestRootNode<NullTest1> root = createRoot(NullTest1Factory.getInstance());
+
+        assertEquals("fallback", executeWith(root, (Object) null));
+        assertEquals(true, executeWith(root, true));
+        assertEquals(42L, executeWith(root, 42));
+        assertEquals("string", executeWith(root, "s"));
+        assertEquals("fallback", executeWith(root, (Object) null));
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChild("a")
+    abstract static class NullTest1 extends ValueNode {
+
+        @Specialization
+        long s(long a) {
+            return a;
+        }
+
+        @Specialization
+        boolean s(boolean a) {
+            return a;
+        }
+
+        @Specialization
+        String s(String a) {
+            return "string";
+        }
+
+        @Fallback
+        Object s(Object a) {
+            return "fallback";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic1Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic2Factory;
+import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Polymorphic3Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+public class PolymorphicTest {
+
+    private static void assertParent(Node expectedParent, Node child) {
+        Node parent = child.getParent();
+        while (parent != null && parent != expectedParent) {
+            parent = parent.getParent();
+        }
+
+        if (parent != expectedParent) {
+            assertEquals(expectedParent, parent);
+        }
+    }
+
+    public static void assertNoDuplicates(Node node, Node... ignored) {
+        assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet<Class<?>>(), node);
+    }
+
+    private static void assertNoDuplicatesRec(Set<Node> ignored, Set<Class<?>> seenClasses, Node current) {
+        if (!ignored.contains(current)) {
+            if (seenClasses.contains(current.getClass())) {
+                Assert.fail(String.format("Multiple occurences of the same class %s. %nTree: %s", current.getClass().getSimpleName(), NodeUtil.printCompactTreeToString(current.getRootNode())));
+            } else {
+                seenClasses.add(current.getClass());
+            }
+        }
+
+        for (Node child : current.getChildren()) {
+            if (child != null) {
+                assertNoDuplicatesRec(ignored, seenClasses, child);
+            }
+        }
+    }
+
+    @Test
+    public void testPolymorphic1() {
+        assertRuns(Polymorphic1Factory.getInstance(), //
+                        array(42, 43, true, false, "a", "b"), //
+                        array(42, 43, true, false, "a", "b"), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic1 polymorphic = ((Polymorphic1) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic1 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        int add(int a) {
+            return a;
+        }
+
+        @Specialization
+        boolean add(boolean a) {
+            return a;
+        }
+
+        @Specialization
+        String add(String a) {
+            return a;
+        }
+
+        @Fallback
+        String add(Object left) {
+            throw new AssertionError(left.toString());
+        }
+
+    }
+
+    @Test
+    public void testPolymorphic2() {
+        assertRuns(Polymorphic2Factory.getInstance(), //
+                        array(0, 1, 1, "1", "2", 2, 3), //
+                        array(0, 1, 1, "1", "2", 2, 3), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic2 polymorphic = ((Polymorphic2) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                                if (index == 0) {
+                                    assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost());
+                                }
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic2 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        String s2(String a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int s1(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testPolymorphic3() {
+        assertRuns(Polymorphic3Factory.getInstance(), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3), //
+                        array("0", "1", 1, 1, 2, 2, 3, 3), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                Polymorphic3 polymorphic = ((Polymorphic3) node.getNode());
+                                assertParent(node.getNode(), polymorphic.getA());
+                                assertNoDuplicates(polymorphic, polymorphic.getA());
+                            }
+                        });
+    }
+
+    @NodeChild("a")
+    abstract static class Polymorphic3 extends ValueNode {
+
+        public abstract ValueNode getA();
+
+        @Specialization
+        String s2(String a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s0(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
+        }
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int s1(int a) {
+            if (a == 1) {
+                throw new RuntimeException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int s2(int a) {
+            return a;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest2.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
+import com.oracle.truffle.api.dsl.test.PolymorphicTest2Factory.Polymorphic1Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.nodes.*;
+
+public class PolymorphicTest2 {
+
+    @Test
+    public void testMultipleTypes() {
+        /* Tests the unexpected polymorphic case. */
+        TestRootNode<Polymorphic1> node = TestHelper.createRoot(Polymorphic1Factory.getInstance());
+        assertEquals(21, executeWith(node, false, false));
+        assertEquals(42, executeWith(node, 21, 21));
+        assertEquals("(boolean,int)", executeWith(node, false, 42));
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
+    }
+
+    @SuppressWarnings("unused")
+    abstract static class Polymorphic1 extends BinaryNode {
+
+        @Specialization
+        int add(int left, int right) {
+            return 42;
+        }
+
+        @Specialization
+        int add(boolean left, boolean right) {
+            return 21;
+        }
+
+        @Specialization
+        String add(boolean left, int right) {
+            return "(boolean,int)";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ReachabilityTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.Abstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.BExtendsAbstract;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ReachabilityTest {
+
+    static class Reachability1 extends ValueNode {
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization
+        int do1() {
+            return 2;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType1 extends ValueNode {
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(int).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType2 extends ValueNode {
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BExtendsAbstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType3 extends ValueNode {
+        @Specialization
+        Abstract do2(Abstract a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Abstract).")
+        @Specialization
+        BExtendsAbstract do1(BExtendsAbstract a) {
+            return a;
+        }
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType4 extends ValueNode {
+
+        @Specialization
+        BExtendsAbstract do2(BExtendsAbstract a) {
+            return a;
+        }
+
+        @Specialization
+        Abstract do1(Abstract a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType5 extends ValueNode {
+
+        @Specialization
+        double do2(double a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(double).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType6 extends ValueNode {
+
+        @Specialization
+        BigInteger do2(BigInteger a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(BigInteger).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType7 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        BigInteger do1(BigInteger a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType8 extends ValueNode {
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        Object do1(Object a) {
+            return a;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class ReachabilityType9 extends ValueNode {
+
+        @Specialization
+        Object do2(Object a) {
+            return a;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2(Object).")
+        @Specialization
+        int do1(int a) {
+            return a;
+        }
+    }
+
+    static class ReachabilityGuard1 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo()")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard2 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization
+        int do2() {
+            return 2;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo()")
+        int do1() {
+            return 1;
+        }
+
+    }
+
+    static class ReachabilityGuard3 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo()")
+        int do2() {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityGuard4 extends ValueNode {
+
+        boolean foo() {
+            return false;
+        }
+
+        @Specialization(guards = "foo()")
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(guards = "foo()")
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityThrowable1 extends ValueNode {
+
+        @Specialization(rewriteOn = RuntimeException.class)
+        int do2() throws RuntimeException {
+            return 1;
+        }
+
+        @Specialization
+        int do1() {
+            return 2;
+        }
+
+    }
+
+    static class ReachabilityThrowable2 extends ValueNode {
+
+        @Specialization
+        int do2() {
+            return 1;
+        }
+
+        @ExpectError("Specialization is not reachable. It is shadowed by do2().")
+        @Specialization(rewriteOn = RuntimeException.class)
+        int do1() throws RuntimeException {
+            return 2;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.ShortCircuitWithImplicitCastNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class ShortCircuitTest {
+
+    @Test
+    public void testSingleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = true;
+        assertEquals(42, callTarget.call(new Object[]{42}));
+        assertEquals(1, arg0.getInvocationCount());
+    }
+
+    @Test
+    public void testSingleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        CallTarget callTarget = TestHelper.createCallTarget(SingleChildNodeFactory.create(arg0));
+        SingleChildNode.needsChild = false;
+        assertEquals(0, callTarget.call(new Object[]{42}));
+        assertEquals(0, arg0.getInvocationCount());
+    }
+
+    @NodeChild("child0")
+    abstract static class SingleChildNode extends ValueNode {
+
+        static boolean needsChild;
+
+        @ShortCircuit("child0")
+        boolean needsChild0() {
+            return needsChild;
+        }
+
+        @Specialization
+        int doIt(boolean hasChild0, int child0) {
+            assert hasChild0 == needsChild0();
+            return child0;
+        }
+
+    }
+
+    @Test
+    public void testDoubleChild1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(42, callTarget.call(new Object[]{41, 42}));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testDoubleChild2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(DoubleChildNodeFactory.create(arg0, arg1));
+        assertEquals(0, callTarget.call(new Object[]{42, 42}));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    @SuppressWarnings("unused")
+    abstract static class DoubleChildNode extends ValueNode {
+
+        @ShortCircuit("child1")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    @SuppressWarnings("unused")
+    abstract static class GuardChildNode extends ValueNode {
+
+        @ShortCircuit("child1")
+        boolean needsChild1(Object a) {
+            return a.equals(new Integer(42));
+        }
+
+        static boolean guard(int a, boolean hasB, int b) {
+            return false;
+        }
+
+        @Specialization(guards = "guard(a, hasB, b)")
+        int doIt(int a, boolean hasB, int b) {
+            return a + b;
+        }
+
+    }
+
+    @Test
+    public void testVarArgs1() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(42, callTarget.call(new Object[]{41, 42}));
+        assertEquals(1, arg1.getInvocationCount());
+    }
+
+    @Test
+    public void testVarArgs2() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(VarArgsNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(0, callTarget.call(new Object[]{42, 42}));
+        assertEquals(0, arg1.getInvocationCount());
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    abstract static class VarArgsNode extends ValueNode {
+
+        @ShortCircuit("children[1]")
+        boolean needsChild1(Object leftValue) {
+            return leftValue.equals(41);
+        }
+
+        @Specialization
+        @SuppressWarnings("unused")
+        int doIt(int child0, boolean hasChild1, int child1) {
+            return child1;
+        }
+
+    }
+
+    @Test
+    public void testShortCircuitWithImplicitCastNode() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(ShortCircuitWithImplicitCastNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(42, callTarget.call(new Object[]{42, 41}));
+    }
+
+    @TypeSystem(int.class)
+    abstract static class ShortCircuitWithImplicitCastTypes {
+
+        @ImplicitCast
+        public static int doAnImplicitCast(String foo) {
+            return Integer.parseInt(foo);
+        }
+
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    @TypeSystemReference(ShortCircuitWithImplicitCastTypes.class)
+    abstract static class ShortCircuitWithImplicitCastNode extends ValueNode {
+
+        @ShortCircuit("children[1]")
+        public boolean needsRightNode(Object left) {
+            return (int) left == 41;
+        }
+
+        @Specialization
+        public int doInteger(int left, boolean needsRight, int right) {
+            return needsRight ? right : left;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SourceSectionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection0Factory;
+import com.oracle.truffle.api.dsl.test.SourceSectionTestFactory.SourceSection1Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+@RunWith(Theories.class)
+public class SourceSectionTest {
+
+    @DataPoints public static final int[] data = new int[]{1, 2, 3, 4};
+
+    @Theory
+    public void testSourceSections(int value0, int value1, int value2) {
+        TestRootNode<SourceSection0> root = createRoot(SourceSection0Factory.getInstance());
+        SourceSection section = new NullSourceSection("a", "b");
+        root.getNode().assignSourceSection(section);
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value0), is(value0));
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value1), is(value1));
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, value2), is(value2));
+        expectSourceSection(root.getNode(), section);
+    }
+
+    private static void expectSourceSection(Node root, SourceSection section) {
+        assertThat(root.getSourceSection(), is(sameInstance(section)));
+        for (Node child : root.getChildren()) {
+            if (child instanceof ArgumentNode || child instanceof SpecializationNode) {
+                continue;
+            }
+            if (child != null) {
+                expectSourceSection(child, section);
+            }
+        }
+    }
+
+    @NodeChild("a")
+    static class SourceSection0 extends ValueNode {
+
+        @Specialization(guards = "a == 1")
+        int do1(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "a == 2")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(guards = "a == 3")
+        int do3(int a) {
+            return a;
+        }
+
+        @Fallback
+        Object do4(Object a) {
+            return a; // the generic answer to all questions
+        }
+    }
+
+    @Test
+    public void testCreateCast() {
+        SourceSection section = new NullSourceSection("a", "b");
+        TestRootNode<SourceSection1> root = createRootPrefix(SourceSection1Factory.getInstance(), true, section);
+        expectSourceSection(root.getNode(), section);
+        assertThat((int) executeWith(root, 1), is(1));
+        expectSourceSection(root.getNode(), section);
+    }
+
+    @NodeChild("a")
+    static class SourceSection1 extends ValueNode {
+
+        public SourceSection1(SourceSection section) {
+            super(section);
+        }
+
+        @CreateCast("a")
+        public ValueNode cast(ValueNode node) {
+            assert getSourceSection() != null;
+            return node;
+        }
+
+        @Specialization
+        int do0(int a) {
+            return a;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationFallthroughTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest0Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest1Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest2Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest3Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest4Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationFallthroughTestFactory.FallthroughTest5Factory;
+import com.oracle.truffle.api.dsl.test.TestHelper.ExecutionListener;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class SpecializationFallthroughTest {
+
+    @Test
+    public void testFallthrough0() {
+        assertRuns(FallthroughTest0Factory.getInstance(), //
+                        array(0, 0, 1, 2), //
+                        array(0, 0, 1, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest0.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest0 extends ValueNode {
+
+        static int fallthroughCount = 0;
+
+        public FallthroughTest0() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Fallback
+        Object doFallback(Object a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice for monomorphic cases.
+     */
+    @Test
+    public void testFallthrough1() {
+        assertRuns(FallthroughTest1Factory.getInstance(), //
+                        array(0, 0, 0, 1, 2), //
+                        array(0, 0, 0, 1, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest1.fallthroughCount > 1) {
+                                    Assert.fail("The fallthrough case must never be triggered twice. Therfore count must be <= 1, but is not.");
+                                }
+                            }
+                        });
+    }
+
+    /* TODO assert falltrough do1 before do2 */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest1 extends ValueNode {
+
+        static int fallthroughCount;
+
+        public FallthroughTest1() {
+            fallthroughCount = 0;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthroughCount++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do2(int a) {
+            return a;
+        }
+
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice with two falltrhoughs in one operation.
+     */
+    @Test
+    public void testFallthrough2() {
+        assertRuns(FallthroughTest2Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest2.fallthrough1 > 1) {
+                                    Assert.fail();
+                                }
+                                if (FallthroughTest2.fallthrough2 > 1) {
+                                    Assert.fail();
+                                }
+                                FallthroughTest2.fallthrough1 = 0;
+                                FallthroughTest2.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest2 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+    }
+
+    /*
+     * Tests that the fall through is never triggered twice. In this case mixed fallthrough with
+     * normal specializations.
+     */
+    @Test
+    public void testFallthrough3() {
+        assertRuns(FallthroughTest3Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest3.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest3.fallthrough1));
+                                }
+                                FallthroughTest3.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest3 extends ValueNode {
+
+        static int fallthrough1;
+
+        boolean guard0(int a) {
+            return a == 1;
+        }
+
+        @Specialization(guards = "guard0(a)")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization(rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough4() {
+        assertRuns(FallthroughTest4Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest4.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                if (FallthroughTest4.fallthrough2 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest4.fallthrough1));
+                                }
+                                FallthroughTest4.fallthrough1 = 0;
+                                FallthroughTest4.fallthrough2 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest4 extends ValueNode {
+
+        static int fallthrough1;
+        static int fallthrough2;
+
+        @Specialization(order = 1, rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization(order = 2, rewriteOn = ArithmeticException.class)
+        int do2(int a) throws ArithmeticException {
+            if (a == 1) {
+                fallthrough2++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    @Test
+    public void testFallthrough5() {
+        assertRuns(FallthroughTest5Factory.getInstance(), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        array(0, 0, 1, 1, 2, 2), //
+                        new ExecutionListener() {
+                            public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+                                if (!last) {
+                                    return;
+                                }
+                                if (FallthroughTest5.fallthrough1 > 1) {
+                                    Assert.fail(String.valueOf(FallthroughTest5.fallthrough1));
+                                }
+                                FallthroughTest5.fallthrough1 = 0;
+                            }
+                        });
+    }
+
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughTest5 extends ValueNode {
+
+        static int fallthrough1;
+
+        @Specialization(guards = "isDo1(a)", rewriteOn = ArithmeticException.class)
+        int do1(int a) throws ArithmeticException {
+            if (a == 0) {
+                fallthrough1++;
+                throw new ArithmeticException();
+            }
+            return a;
+        }
+
+        protected static boolean isDo1(int a) {
+            return a == 0 || a == 1;
+        }
+
+        @Specialization(guards = "isDo1(a)")
+        int do2(int a) {
+            return a;
+        }
+
+        @Specialization
+        int do3(int a) {
+            return a;
+        }
+
+    }
+
+    /* Throwing RuntimeExceptions without rewriteOn is allowed. */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughExceptionType0 extends ValueNode {
+
+        @Specialization
+        int do4(int a) throws RuntimeException {
+            return a;
+        }
+
+    }
+
+    /* Non runtime exceptions must be verified. */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughExceptionType1 extends ValueNode {
+
+        @ExpectError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @Specialization method must specify a throws clause with the exception type 'java.lang.Throwable'.")
+        @Specialization(rewriteOn = Throwable.class)
+        int do4(int a) {
+            return a;
+        }
+
+    }
+
+    /* Checked exception must be verified. */
+    @NodeChildren({@NodeChild("a")})
+    static class FallthroughExceptionType2 extends ValueNode {
+
+        @ExpectError("A checked exception 'java.lang.Throwable' is thrown but is not specified using the rewriteOn property. "
+                        + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.")
+        @Specialization
+        int do4(int a) throws Throwable {
+            return a;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/SpecializationGroupingTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug1Factory;
+import com.oracle.truffle.api.dsl.test.SpecializationGroupingTestFactory.TestElseConnectionBug2Factory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Tests execution counts of guards. While we do not make guarantees for guard invocation except for
+ * their execution order our implementation reduces the calls to guards as much as possible for the
+ * generic case.
+ */
+public class SpecializationGroupingTest {
+
+    @Test
+    public void testElseConnectionBug1() {
+        CallTarget target = TestHelper.createCallTarget(TestElseConnectionBug1Factory.create(new GenericInt()));
+        Assert.assertEquals(42, target.call());
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChild(value = "genericChild", type = GenericInt.class)
+    public abstract static class TestElseConnectionBug1 extends ValueNode {
+
+        @Specialization(rewriteOn = {SlowPathException.class}, guards = "isInitialized(value)")
+        public int do1(int value) throws SlowPathException {
+            throw new SlowPathException();
+        }
+
+        @Specialization(contains = "do1", guards = "isInitialized(value)")
+        public int do2(int value) {
+            return value == 42 ? value : 0;
+        }
+
+        @Specialization(guards = "!isInitialized(value)")
+        public Object do3(int value) {
+            throw new AssertionError();
+        }
+
+        boolean isInitialized(int value) {
+            return true;
+        }
+    }
+
+    public static final class GenericInt extends ValueNode {
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return executeInt(frame);
+        }
+
+        @Override
+        public int executeInt(VirtualFrame frame) {
+            return 42;
+        }
+
+    }
+
+    @Test
+    public void testElseConnectionBug2() {
+        TestHelper.assertRuns(TestElseConnectionBug2Factory.getInstance(), new Object[]{42}, new Object[]{42});
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChild
+    public abstract static class TestElseConnectionBug2 extends ValueNode {
+
+        @Specialization(guards = "guard0(value)")
+        public int do1(int value) {
+            throw new AssertionError();
+        }
+
+        @Specialization(guards = "guard1(value)")
+        public int do2(int value) {
+            throw new AssertionError();
+        }
+
+        @Specialization(guards = "!guard0(value)")
+        public int do3(int value) {
+            return value;
+        }
+
+        boolean guard0(int value) {
+            return false;
+        }
+
+        boolean guard1(int value) {
+            return false;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestHelper.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ChildrenNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Utility class to provide some test helper functions.
+ */
+class TestHelper {
+
+    // make nodes replacable
+    public static <T extends Node> T createRoot(final T node) {
+        new RootNode() {
+            @Child T child = node;
+
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return null;
+            }
+        }.adoptChildren();
+        return node;
+    }
+
+    private static ArgumentNode[] arguments(int count) {
+        ArgumentNode[] nodes = new ArgumentNode[count];
+        for (int i = 0; i < nodes.length; i++) {
+            nodes[i] = new ArgumentNode(i);
+        }
+        return nodes;
+    }
+
+    static <E extends ValueNode> E createNode(NodeFactory<E> factory, boolean prefixConstants, Object... constants) {
+        ArgumentNode[] argumentNodes = arguments(factory.getExecutionSignature().size());
+
+        List<Object> argumentList = new ArrayList<>();
+        if (prefixConstants) {
+            argumentList.addAll(Arrays.asList(constants));
+        }
+        if (ChildrenNode.class.isAssignableFrom(factory.getNodeClass())) {
+            argumentList.add(argumentNodes);
+        } else {
+            argumentList.addAll(Arrays.asList(argumentNodes));
+        }
+        if (!prefixConstants) {
+            argumentList.addAll(Arrays.asList(constants));
+        }
+        return factory.createNode(argumentList.toArray(new Object[argumentList.size()]));
+    }
+
+    static <E extends ValueNode> TestRootNode<E> createRoot(NodeFactory<E> factory, Object... constants) {
+        TestRootNode<E> rootNode = new TestRootNode<>(createNode(factory, false, constants));
+        rootNode.adoptChildren();
+        return rootNode;
+    }
+
+    static <E extends ValueNode> TestRootNode<E> createRootPrefix(NodeFactory<E> factory, boolean prefixConstants, Object... constants) {
+        TestRootNode<E> rootNode = new TestRootNode<>(createNode(factory, prefixConstants, constants));
+        rootNode.adoptChildren();
+        return rootNode;
+    }
+
+    static CallTarget createCallTarget(ValueNode node) {
+        return createCallTarget(new TestRootNode<>(node));
+    }
+
+    static CallTarget createCallTarget(TestRootNode<? extends ValueNode> node) {
+        return Truffle.getRuntime().createCallTarget(node);
+    }
+
+    static RootCallTarget createCallTarget(NodeFactory<? extends ValueNode> factory, Object... constants) {
+        return Truffle.getRuntime().createCallTarget(createRoot(factory, constants));
+    }
+
+    static boolean assertionsEnabled() {
+        boolean assertOn = false;
+        // *assigns* true if assertions are on.
+        assert (assertOn = true) == true;
+        return assertOn;
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T extends ValueNode> T getNode(CallTarget target) {
+        return ((TestRootNode<T>) ((RootCallTarget) target).getRootNode()).getNode();
+    }
+
+    static <E> Object executeWith(TestRootNode<? extends ValueNode> node, Object... values) {
+        return createCallTarget(node).call(values);
+    }
+
+    static Object[] array(Object... val) {
+        return val;
+    }
+
+    static <E> List<List<E>> permutations(List<E> list) {
+        return permutations(new ArrayList<E>(), list, new ArrayList<List<E>>());
+    }
+
+    static Object[][] permutations(Object... list) {
+        List<List<Object>> permutations = permutations(Arrays.asList(list));
+
+        Object[][] a = new Object[permutations.size()][];
+        int index = 0;
+        for (List<Object> p : permutations) {
+            a[index] = p.toArray(new Object[p.size()]);
+            index++;
+        }
+
+        return a;
+    }
+
+    static <E> List<List<E>> permutations(List<E> prefix, List<E> suffix, List<List<E>> output) {
+        if (suffix.size() == 1) {
+            ArrayList<E> newElement = new ArrayList<>(prefix);
+            newElement.addAll(suffix);
+            output.add(newElement);
+            return output;
+        }
+
+        for (int i = 0; i < suffix.size(); i++) {
+            List<E> newPrefix = new ArrayList<>(prefix);
+            newPrefix.add(suffix.get(i));
+            List<E> newSuffix = new ArrayList<>(suffix);
+            newSuffix.remove(i);
+            permutations(newPrefix, newSuffix, output);
+        }
+
+        return output;
+    }
+
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result) {
+        assertRuns(factory, testValues, result, null);
+    }
+
+    /* Methods tests all test values in combinational order. */
+    static void assertRuns(NodeFactory<? extends ValueNode> factory, Object[] testValues, Object[] result, ExecutionListener listener) {
+        // test each run by its own.
+        for (int i = 0; i < testValues.length; i++) {
+            assertValue(createRoot(factory), 0, testValues[i], result[i], listener, true);
+        }
+
+        // test all combinations of the test values
+        List<Object> testValuesList = Arrays.asList(testValues);
+        List<List<Object>> permuts = permutations(testValuesList);
+        for (List<Object> list : permuts) {
+            TestRootNode<?> root = createRoot(factory);
+            int index = 0;
+            for (Object object : list) {
+                assertValue(root, index, object, result[testValuesList.indexOf(object)], listener, index == list.size() - 1);
+                index++;
+            }
+        }
+    }
+
+    static void assertValue(TestRootNode<? extends ValueNode> root, int index, Object value, Object result, ExecutionListener listener, boolean last) {
+        Object actualResult = null;
+        if (result instanceof Class && Throwable.class.isAssignableFrom((Class<?>) result)) {
+            try {
+                if (value instanceof Object[]) {
+                    actualResult = executeWith(root, (Object[]) value);
+                } else {
+                    actualResult = executeWith(root, value);
+                }
+                fail(String.format("Exception %s  expected but not occured.", result.getClass()));
+            } catch (Throwable e) {
+                actualResult = e;
+                if (!e.getClass().isAssignableFrom(((Class<?>) result))) {
+                    e.printStackTrace();
+                    fail(String.format("Incompatible exception class thrown. Expected %s but was %s.", result.toString(), e.getClass()));
+                }
+            }
+        } else if (value instanceof Object[]) {
+            actualResult = executeWith(root, (Object[]) value);
+            assertEquals(result, actualResult);
+        } else {
+            actualResult = executeWith(root, value);
+            assertEquals(result, actualResult);
+        }
+        if (listener != null) {
+            listener.afterExecution(root, index, value, result, actualResult, last);
+        }
+    }
+
+    public static final class LogListener implements ExecutionListener {
+
+        public void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last) {
+            System.out.printf("Run %3d Node:%-20s Parameters: %10s Expected: %10s Result %10s%n", index, node.getNode().getClass().getSimpleName(), value, expectedResult, actualResult);
+        }
+
+    }
+
+    interface ExecutionListener {
+
+        void afterExecution(TestRootNode<? extends ValueNode> node, int index, Object value, Object expectedResult, Object actualResult, boolean last);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestSerialization.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TestSerializationFactory.SerializedNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.nodes.*;
+
+public class TestSerialization {
+
+    @Test
+    public void testUpdateRoot() {
+        /* Tests the unexpected polymorphic case. */
+        TestRootNode<SerializedNode> node = TestHelper.createRoot(SerializedNodeFactory.getInstance());
+        assertEquals(true, executeWith(node, true));
+        assertEquals(21, executeWith(node, 21));
+        assertEquals("s", executeWith(node, "s"));
+        assertEquals(3, node.getNode().invocations);
+        assertEquals(NodeCost.POLYMORPHIC, node.getNode().getCost());
+
+        @SuppressWarnings("unchecked")
+        TestRootNode<SerializedNode> copiedNode = (TestRootNode<SerializedNode>) node.deepCopy();
+        copiedNode.adoptChildren();
+        assertTrue(copiedNode != node);
+        assertEquals(true, executeWith(copiedNode, true));
+        assertEquals(21, executeWith(copiedNode, 21));
+        assertEquals("s", executeWith(copiedNode, "s"));
+        assertEquals(6, copiedNode.getNode().invocations);
+    }
+
+    @NodeChild
+    abstract static class SerializedNode extends ValueNode {
+
+        int invocations;
+
+        @Specialization
+        int add(int left) {
+            invocations++;
+            return left;
+        }
+
+        @Specialization
+        boolean add(boolean left) {
+            invocations++;
+            return left;
+        }
+
+        @Specialization
+        String add(String left) {
+            invocations++;
+            return left;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemErrorsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types1.Type1;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class TypeSystemErrorsTest {
+
+    @TypeSystem({int.class, boolean.class})
+    public static class ErrorTypes0 {
+
+    }
+
+    @ExpectError("Invalid type order. The type(s) [java.lang.String] are inherited from a earlier defined type java.lang.CharSequence.")
+    @TypeSystem({CharSequence.class, String.class})
+    public static class ErrorTypes1 {
+
+    }
+
+    public static class Types1 {
+        public static class Type1 {
+        }
+    }
+
+    public static class Types2 {
+        public static class Type1 {
+        }
+    }
+
+    // verify boxed type overlay
+    @ExpectError("Two types result in the same boxed name: Type1.")
+    @TypeSystem({Type1.class, com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types2.Type1.class})
+    public static class ErrorTypes2 {
+
+    }
+
+    public static class Types3 {
+        public static class Object {
+        }
+    }
+
+    // verify Object name cannot appear
+    @ExpectError("Two types result in the same boxed name: Object.")
+    @TypeSystem({com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types3.Object.class})
+    public static class ErrorTypes3 {
+    }
+
+    public static class Types4 {
+        public static class Integer {
+        }
+    }
+
+    // verify int boxed name
+    @ExpectError("Two types result in the same boxed name: Integer.")
+    @TypeSystem({int.class, com.oracle.truffle.api.dsl.test.TypeSystemErrorsTest.Types4.Integer.class})
+    public static class ErrorTypes4 {
+    }
+
+    @TypeSystemReference(ErrorTypes0.class)
+    @NodeChild
+    @ExpectError("The @TypeSystem of the node and the @TypeSystem of the @NodeChild does not match. Types0 != SimpleTypes. ")
+    abstract static class ErrorNode1 extends ValueNode {
+    }
+
+    @TypeSystem({int.class})
+    public static class CastError1 {
+        @TypeCast(int.class)
+        @ExpectError("The provided return type \"String\" does not match expected return type \"int\".%")
+        public static String asInteger(Object value) {
+            return (String) value;
+        }
+    }
+
+    @TypeSystem({int.class})
+    public static class CastError2 {
+        @TypeCast(int.class)
+        @ExpectError("The provided return type \"boolean\" does not match expected return type \"int\".%")
+        public static boolean asInteger(Object value) {
+            return (boolean) value;
+        }
+    }
+
+    @TypeSystem({int.class})
+    public static class CastError4 {
+        @ExpectError("@TypeCast annotated method asInt must be public and static.")
+        @TypeCast(int.class)
+        public int asInt(Object value) {
+            return (int) value;
+        }
+    }
+
+    @TypeSystem({int.class})
+    public static class CastError5 {
+        @ExpectError("@TypeCast annotated method asInt must be public and static.")
+        @TypeCast(int.class)
+        static int asInt(Object value) {
+            return (int) value;
+        }
+    }
+
+    @TypeSystem({int.class})
+    public static class CheckError2 {
+        @ExpectError("@TypeCheck annotated method isInt must be public and static.")
+        @TypeCheck(int.class)
+        public boolean isInt(Object value) {
+            return value instanceof Integer;
+        }
+    }
+
+    @TypeSystem({int.class})
+    public static class CheckError3 {
+        @ExpectError("@TypeCheck annotated method isInt must be public and static.")
+        @TypeCheck(int.class)
+        static boolean isInt(Object value) {
+            return value instanceof Integer;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TypeSystemTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.math.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+public class TypeSystemTest {
+
+    @TypeSystem({byte.class, short.class, int.class, long.class, double.class, boolean.class, BigInteger.class, String.class, CallTarget.class, BExtendsAbstract.class, CExtendsAbstract.class,
+                    Abstract.class, Interface.class, Object[].class})
+    @DSLOptions(useNewLayout = true)
+    static class SimpleTypes {
+
+        static int intCheck;
+        static int intCast;
+
+        @TypeCheck(int.class)
+        public static boolean isInteger(Object value) {
+            intCheck++;
+            return value instanceof Integer;
+        }
+
+        @TypeCast(int.class)
+        public static int asInteger(Object value) {
+            intCast++;
+            return (int) value;
+        }
+
+        @ImplicitCast
+        public static double castDouble(int value) {
+            return value;
+        }
+
+        @ImplicitCast
+        public static long castLong(int value) {
+            return value;
+        }
+
+        @ImplicitCast
+        public static BigInteger castBigInteger(int value) {
+            return BigInteger.valueOf(value);
+        }
+
+    }
+
+    @TypeSystemReference(SimpleTypes.class)
+    @GenerateNodeFactory
+    public static class ValueNode extends Node {
+
+        public ValueNode() {
+            super(null);
+        }
+
+        public ValueNode(SourceSection sourceSection) {
+            super(sourceSection);
+        }
+
+        public int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectInteger(execute(frame));
+        }
+
+        public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectLong(execute(frame));
+        }
+
+        public String executeString(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectString(execute(frame));
+        }
+
+        public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectBoolean(execute(frame));
+        }
+
+        public Object[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectObjectArray(execute(frame));
+        }
+
+        public BigInteger executeBigInteger(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectBigInteger(execute(frame));
+        }
+
+        public BExtendsAbstract executeBExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectBExtendsAbstract(execute(frame));
+        }
+
+        public CExtendsAbstract executeCExtendsAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectCExtendsAbstract(execute(frame));
+        }
+
+        public Abstract executeAbstract(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectAbstract(execute(frame));
+        }
+
+        public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectDouble(execute(frame));
+        }
+
+        public Interface executeInterface(VirtualFrame frame) throws UnexpectedResultException {
+            return SimpleTypesGen.expectInterface(execute(frame));
+        }
+
+        public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ValueNode copy() {
+            return (ValueNode) super.copy();
+        }
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    @GenerateNodeFactory
+    public abstract static class ChildrenNode extends ValueNode {
+
+    }
+
+    @TypeSystemReference(SimpleTypes.class)
+    public static class TestRootNode<E extends ValueNode> extends RootNode {
+
+        @Child private E node;
+
+        public TestRootNode(E node) {
+            super(null);
+            this.node = node;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return node.execute(frame);
+        }
+
+        public E getNode() {
+            return node;
+        }
+    }
+
+    public static class ArgumentNode extends ValueNode {
+
+        private int invocationCount;
+        final int index;
+
+        public ArgumentNode(int index) {
+            this.index = index;
+        }
+
+        public int getInvocationCount() {
+            return invocationCount;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            invocationCount++;
+            return frame.getArguments()[index];
+        }
+
+        @Override
+        public int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            invocationCount++;
+            // avoid casts for some tests
+            Object o = frame.getArguments()[index];
+            if (o instanceof Integer) {
+                return (int) o;
+            }
+            throw new UnexpectedResultException(o);
+        }
+
+    }
+
+    abstract static class Abstract {
+    }
+
+    static final class BExtendsAbstract extends Abstract {
+
+        static final BExtendsAbstract INSTANCE = new BExtendsAbstract();
+
+    }
+
+    static final class CExtendsAbstract extends Abstract {
+
+        static final CExtendsAbstract INSTANCE = new CExtendsAbstract();
+    }
+
+    interface Interface {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported1Factory;
+import com.oracle.truffle.api.dsl.test.UnsupportedSpecializationTestFactory.Unsupported2Factory;
+import com.oracle.truffle.api.nodes.*;
+
+public class UnsupportedSpecializationTest {
+
+    @Test
+    public void testUnsupported1() {
+        TestRootNode<Unsupported1> root = TestHelper.createRoot(Unsupported1Factory.getInstance());
+        try {
+            TestHelper.executeWith(root, "");
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertNotNull(e.getSuppliedValues());
+            Assert.assertEquals(1, e.getSuppliedValues().length);
+            Assert.assertEquals("", e.getSuppliedValues()[0]);
+            Assert.assertSame(root.getNode().getChildren().iterator().next(), e.getSuppliedNodes()[0]);
+            Assert.assertEquals(root.getNode(), e.getNode());
+        }
+    }
+
+    @NodeChild("a")
+    abstract static class Unsupported1 extends ValueNode {
+
+        @Specialization
+        public int doInteger(@SuppressWarnings("unused") int a) {
+            throw new AssertionError();
+        }
+    }
+
+    @Test
+    public void testUnsupported2() {
+        TestRootNode<Unsupported2> root = TestHelper.createRoot(Unsupported2Factory.getInstance());
+        try {
+            TestHelper.executeWith(root, "", 1);
+            Assert.fail();
+        } catch (UnsupportedSpecializationException e) {
+            Assert.assertNotNull(e.getSuppliedValues());
+            Assert.assertNotNull(e.getSuppliedNodes());
+            Assert.assertEquals(3, e.getSuppliedValues().length);
+            Assert.assertEquals(3, e.getSuppliedNodes().length);
+            Assert.assertEquals("", e.getSuppliedValues()[0]);
+            Assert.assertEquals(false, e.getSuppliedValues()[1]);
+            Assert.assertEquals(null, e.getSuppliedValues()[2]);
+            List<Node> children = NodeUtil.findNodeChildren(root.getNode());
+            Assert.assertSame(children.get(0), e.getSuppliedNodes()[0]);
+            Assert.assertNull(e.getSuppliedNodes()[1]);
+            Assert.assertSame(children.get(1), e.getSuppliedNodes()[2]);
+            Assert.assertEquals(root.getNode(), e.getNode());
+        }
+    }
+
+    @SuppressWarnings("unused")
+    @NodeChildren({@NodeChild("a"), @NodeChild("b")})
+    abstract static class Unsupported2 extends ValueNode {
+
+        @ShortCircuit("b")
+        public boolean needsB(Object a) {
+            return false;
+        }
+
+        @Specialization
+        public int doInteger(int a, boolean hasB, int b) {
+            throw new AssertionError();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+@TypeSystemReference(ExampleTypes.class)
+@NodeChild(value = "args", type = ExampleNode[].class)
+public abstract class ExampleNode extends Node {
+
+    public Object execute(@SuppressWarnings("unused") VirtualFrame frame) {
+        // will get implemented by the DSL.
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String toString() {
+        if (this instanceof SpecializedNode) {
+            return ((SpecializedNode) this).getSpecializationNode().toString();
+        } else {
+            return super.toString();
+        }
+    }
+
+    public static CallTarget createTarget(ExampleNode node) {
+        return Truffle.getRuntime().createCallTarget(new ExampleRootNode(node));
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getNode(CallTarget target) {
+        return (T) ((ExampleRootNode) ((RootCallTarget) target).getRootNode()).child;
+    }
+
+    public static ExampleNode[] createArguments(int count) {
+        ExampleNode[] nodes = new ExampleNode[count];
+        for (int i = 0; i < count; i++) {
+            nodes[i] = new ExampleArgumentNode(i);
+        }
+        return nodes;
+    }
+
+    private static class ExampleRootNode extends RootNode {
+
+        @Child ExampleNode child;
+
+        public ExampleRootNode(ExampleNode child) {
+            this.child = child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child.execute(frame);
+        }
+
+    }
+
+    private static class ExampleArgumentNode extends ExampleNode {
+
+        private final int index;
+
+        public ExampleArgumentNode(int index) {
+            this.index = index;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            Object[] arguments = frame.getArguments();
+            if (index < arguments.length) {
+                return arguments[index];
+            }
+            return null;
+        }
+    }
+
+    public static CallTarget createDummyTarget(int argumentIndex) {
+        return Truffle.getRuntime().createCallTarget(new DummyCallRootNode(argumentIndex));
+    }
+
+    private static class DummyCallRootNode extends RootNode {
+
+        private final int argumentIndex;
+
+        public DummyCallRootNode(int argumentIndex) {
+            this.argumentIndex = argumentIndex;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return frame.getArguments()[argumentIndex];
+        }
+
+        @Override
+        public String toString() {
+            return "DummyRootNode[arg = " + argumentIndex + "]";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/ExampleTypes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.examples.FunctionCall.Function;
+import com.oracle.truffle.api.dsl.test.examples.Interop.TruffleObject;
+import com.oracle.truffle.api.dsl.test.examples.RubyCall.InternalMethod;
+import com.oracle.truffle.api.dsl.test.examples.RubyCall.RubyObject;
+import com.oracle.truffle.api.dsl.test.examples.StableDispatch.SLFunction;
+
+@TypeSystem({int.class, double.class, boolean.class, TruffleObject.class, SLFunction.class, RubyObject.class, Function.class, InternalMethod.class, int[].class, double[].class, Object[].class})
+public class ExampleTypes {
+
+    @ImplicitCast
+    public static double castInt(int intValue) {
+        return intValue;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/FunctionCall.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.examples.FunctionCallFactory.FunctionCallNodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This example illustrates how {@link Cached} can be used to implement function calls that use
+ * local state for its guards. If there are always distinct Function objects with distinct
+ * CallTargets then we can use the directCallFunctionGuard specialization. If there are two Function
+ * instances cached with the same CallTarget then we use the directCall cache. We do this because
+ * the directCallFunctionGuard specialization can use a faster guard.
+ */
+@SuppressWarnings("unused")
+public class FunctionCall {
+
+    @Test
+    public void testFunctionCall() {
+        assertEquals(2, FunctionCallNode.CACHE_SIZE);
+
+        CallTarget dummyTarget1 = createDummyTarget(0);
+        CallTarget dummyTarget2 = createDummyTarget(0);
+        CallTarget dummyTarget3 = createDummyTarget(0);
+
+        Function dummyFunction1 = new Function(dummyTarget1);
+        Function dummyFunction2 = new Function(dummyTarget2);
+        Function dummyFunction3 = new Function(dummyTarget2); // same target as dummyFunction2
+        Function dummyFunction4 = new Function(dummyTarget3);
+
+        FunctionCallNode node = FunctionCallNodeGen.create(createArguments(2));
+        CallTarget target = createTarget(node);
+        assertEquals(42, target.call(dummyFunction1, 42));
+        assertEquals(43, target.call(dummyFunction2, 43));
+        assertEquals(44, target.call(dummyFunction3, 44)); // transition to directCall
+        assertEquals(2, node.directCallFunctionGuard);
+        assertEquals(1, node.directCall);
+
+        assertEquals(42, target.call(dummyFunction1, 42));
+        assertEquals(43, target.call(dummyFunction2, 43));
+        assertEquals(2, node.directCallFunctionGuard);
+        assertEquals(3, node.directCall);
+
+        assertEquals(44, target.call(dummyFunction4, 44)); // transition to indirectCall
+        assertEquals(2, node.directCallFunctionGuard);
+        assertEquals(3, node.directCall);
+        assertEquals(1, node.indirectCall);
+
+        assertEquals(42, target.call(dummyFunction1, 42));
+        assertEquals(43, target.call(dummyFunction2, 43));
+        assertEquals(44, target.call(dummyFunction3, 44));
+        assertEquals(2, node.directCallFunctionGuard);
+        assertEquals(3, node.directCall);
+        assertEquals(4, node.indirectCall);
+    }
+
+    public static class FunctionCallNode extends ExampleNode {
+
+        public static final int CACHE_SIZE = 2;
+
+        private Function[] cachedFunctions = new Function[CACHE_SIZE];
+
+        private int directCallFunctionGuard;
+        private int directCall;
+        private int indirectCall;
+
+        @Specialization(limit = "CACHE_SIZE", guards = {"function == cachedFunction", "cacheFunctionTarget(cachedFunction)"})
+        public Object directCallFunctionGuard(VirtualFrame frame, Function function, Object argument,  //
+                        @Cached("function") Function cachedFunction, //
+                        @Cached("create(cachedFunction.getTarget())") DirectCallNode callNode) {
+            directCallFunctionGuard++;
+            return callNode.call(frame, new Object[]{argument});
+        }
+
+        protected final boolean cacheFunctionTarget(Function function) {
+            CompilerAsserts.neverPartOfCompilation();
+            if (cachedFunctions != null) {
+                for (int i = 0; i < cachedFunctions.length; i++) {
+                    Function cachedFunction = cachedFunctions[i];
+                    if (cachedFunction == null) {
+                        cachedFunctions[i] = function;
+                        return true;
+                    } else if (cachedFunction == function) {
+                        return true;
+                    } else if (cachedFunction.getTarget() == function.getTarget()) {
+                        cachedFunctions = null;
+                        return false;
+                    }
+                }
+            }
+            return false;
+        }
+
+        @Specialization(limit = "CACHE_SIZE", contains = "directCallFunctionGuard", guards = {"function.getTarget() == cachedTarget"})
+        protected Object directCall(VirtualFrame frame, Function function, Object argument,  //
+                        @Cached("function.getTarget()") CallTarget cachedTarget, //
+                        @Cached("create(cachedTarget)") DirectCallNode callNode) {
+            directCall++;
+            return callNode.call(frame, new Object[]{argument});
+        }
+
+        @Specialization(contains = "directCall")
+        protected Object indirectCall(VirtualFrame frame, Function function, Object argument, //
+                        @Cached("create()") IndirectCallNode callNode) {
+            indirectCall++;
+            return callNode.call(frame, function.getTarget(), new Object[]{argument});
+        }
+    }
+
+    public static class Function {
+
+        private final CallTarget target;
+
+        public Function(CallTarget target) {
+            this.target = target;
+        }
+
+        public CallTarget getTarget() {
+            return target;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/Interop.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.examples.InteropFactory.UseInteropNodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This example aims to illustrate how the {@link Cached} annotation can be used to implement a
+ * cache for a simplified language interoperability pattern.
+ */
+public class Interop {
+
+    @Test
+    public void testInterop() {
+        UseInterop node = UseInteropNodeGen.create(createArguments(2));
+        CallTarget target = createTarget(node);
+        TruffleObject o1 = new TruffleObject();
+        TruffleObject o2 = new TruffleObject();
+        TruffleObject o3 = new TruffleObject();
+        TruffleObject o4 = new TruffleObject();
+        assertEquals(42, target.call(o1, 42));
+        assertEquals(43, target.call(o2, 43));
+        assertEquals(44, target.call(o3, 44));
+        assertEquals(3, node.cached);
+        assertEquals(0, node.generic);
+        assertEquals(45, target.call(o4, 45)); // operation gets generic
+        assertEquals(42, target.call(o1, 42));
+        assertEquals(43, target.call(o2, 43));
+        assertEquals(44, target.call(o3, 44));
+        assertEquals(3, node.cached);
+        assertEquals(4, node.generic);
+    }
+
+    public static class UseInterop extends ExampleNode {
+
+        int cached = 0;
+        int generic = 0;
+
+        @Specialization(guards = "operation.accept(target)")
+        protected Object interopCached(VirtualFrame frame, TruffleObject target, Object value, //
+                        @Cached("target.createOperation()") TruffleObjectOperation operation) {
+            cached++;
+            return operation.execute(frame, target, value);
+        }
+
+        @Specialization(contains = "interopCached")
+        protected Object interopGeneric(VirtualFrame frame, TruffleObject target, Object value) {
+            generic++;
+            return target.createOperation().execute(frame, target, value);
+        }
+    }
+
+    public abstract static class TruffleObjectOperation extends Node {
+
+        public abstract boolean accept(TruffleObject object);
+
+        public abstract Object execute(VirtualFrame frame, Object target, Object value);
+
+    }
+
+    public static class TruffleObject {
+
+        @TruffleBoundary
+        public TruffleObjectOperation createOperation() {
+            return new TruffleObjectOperation() {
+                @Override
+                public Object execute(VirtualFrame frame, Object target, Object value) {
+                    return value;
+                }
+
+                @Override
+                public boolean accept(TruffleObject object) {
+                    return TruffleObject.this == object;
+                }
+            };
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/MathPow.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.examples.MathPowFactory.MathPowNodeGen;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This example shows possible specializations for a simplified math pow node. It demonstrates how
+ * multiple caches can coexist within in the same node. This example does not show the best possible
+ * specializations for math.pow.
+ *
+ * Note: int values are implicitly casted to double values.
+ */
+@SuppressWarnings("unused")
+public class MathPow extends Node {
+
+    @Test
+    public void testPow() {
+        MathPowNode node = MathPowNodeGen.create(createArguments(2));
+        CallTarget target = createTarget(node);
+
+        // start with doPowCached
+        assertEquals(1D, target.call(1D, 1));
+        assertEquals(2D, target.call(2D, 1));
+        assertEquals(3D, target.call(3D, 1));
+        assertEquals(3, node.doPowCached);
+        assertEquals(0, node.doPowCachedExponent);
+
+        // transition to doPowCachedExponent
+        assertEquals(4D, target.call(4D, 1));
+        assertEquals(5D, target.call(5D, 1));
+        assertEquals(6D, target.call(6D, 1));
+        assertEquals(16D, target.call(4D, 2));
+        assertEquals(125D, target.call(5D, 3));
+        assertEquals(5, node.doPowCachedExponent);
+        assertEquals(0, node.doPowDoubleInt);
+
+        // transition to doPowDoubleInt
+        assertEquals(4D * 4D * 4D * 4D, target.call(4D, 4));
+        assertEquals(5D * 5D * 5D * 5D * 5D, target.call(5D, 5));
+        assertEquals(5, node.doPowCachedExponent);
+        assertEquals(2, node.doPowDoubleInt);
+
+        // transition to doPow
+        assertEquals(5D, target.call(5D, 1D));
+        assertEquals(2D, target.call(2D, 1D));
+
+        assertEquals(3, node.doPowCached);
+        assertEquals(5, node.doPowCachedExponent);
+        assertEquals(2, node.doPowDoubleInt);
+        assertEquals(2, node.doPow);
+    }
+
+    public static class MathPowNode extends ExampleNode {
+
+        // test flags
+        int doPowCached;
+        int doPowCachedExponent;
+        int doPowDoubleInt;
+        int doPow;
+
+        @Specialization(guards = {"base == cachedBase", "exponent == cachedExponent"})
+        double doPowCached(double base, int exponent, //
+                        @Cached("base") double cachedBase, //
+                        @Cached("exponent") int cachedExponent, //
+                        @Cached("cachePow(cachedBase, cachedExponent)") double cachedResult) {
+            doPowCached++;
+            return cachedResult;
+        }
+
+        /*
+         * We could just use the doPow specialization instead. But this makes the number of doPow
+         * calls more difficult to assert.
+         */
+        protected static double cachePow(double base, int exponent) {
+            return Math.pow(base, exponent);
+        }
+
+        @Specialization(contains = "doPowCached", guards = {"exponent == cachedExponent", "cachedExponent <= 10"})
+        double doPowCachedExponent(double base, int exponent, @Cached("exponent") int cachedExponent) {
+            doPowCachedExponent++;
+            double result = 1.0;
+            for (int i = 0; i < cachedExponent; i++) {
+                result *= base;
+            }
+            return result;
+        }
+
+        @Specialization(contains = "doPowCachedExponent", guards = "exponent >= 0")
+        double doPowDoubleInt(double base, int exponent) {
+            doPowDoubleInt++;
+            // Uses binary decomposition to limit the number of
+            // multiplications; see the discussion in "Hacker's Delight" by Henry
+            // S. Warren, Jr., figure 11-6, page 213.
+            double b = base;
+            int e = exponent;
+            double result = 1;
+            while (e > 0) {
+                if ((e & 1) == 1) {
+                    result *= b;
+                }
+                e >>= 1;
+                b *= b;
+            }
+            return result;
+        }
+
+        @Specialization(contains = {"doPowCached", "doPowDoubleInt"})
+        double doPow(double base, double exponent) {
+            doPow++;
+            return Math.pow(base, exponent);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/RubyCall.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import static com.oracle.truffle.api.dsl.test.examples.ExampleNode.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyDispatchNodeGen;
+import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyHeadNodeGen;
+import com.oracle.truffle.api.dsl.test.examples.RubyCallFactory.RubyLookupNodeGen;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+/**
+ * This example illustrates a simplified version of a Ruby function call semantics (RubyHeadNode).
+ * The example usage shows how methods can be redefined in this implementation.
+ */
+@SuppressWarnings("unused")
+public class RubyCall {
+
+    @Test
+    public void testCall() {
+        RubyHeadNode node = RubyHeadNodeGen.create(createArguments(4));
+        CallTarget nodeTarget = createTarget(node);
+        final Object firstArgument = "someArgument";
+
+        // dummyMethod is just going to return the some argument of the function
+        final Object testMethodName = "getSomeArgument";
+        // implementation returns first argument
+        InternalMethod aClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(3));
+        // implementation returns second argument
+        InternalMethod bClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(4));
+        // implementation returns third argument
+        InternalMethod cClassTestMethod = new InternalMethod(ExampleNode.createDummyTarget(5));
+
+        // defines hierarchy C extends B extends A
+        RubyClass aClass = new RubyClass("A", null);
+        RubyClass bClass = new RubyClass("B", aClass);
+        RubyClass cClass = new RubyClass("C", bClass);
+
+        RubyObject aInstance = new RubyObject(aClass);
+        RubyObject bInstance = new RubyObject(bClass);
+        RubyObject cInstance = new RubyObject(cClass);
+
+        // undefined method call
+        assertEquals(RubyObject.NIL, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument}));
+
+        // method defined in a
+        aClass.addMethod(testMethodName, aClassTestMethod);
+        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{firstArgument}));
+
+        // method redefined in b
+        bClass.addMethod(testMethodName, bClassTestMethod);
+        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, firstArgument}));
+
+        // method redefined in c
+        cClass.addMethod(testMethodName, cClassTestMethod);
+        assertEquals(firstArgument, nodeTarget.call(aInstance, testMethodName, null, new Object[]{firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(bInstance, testMethodName, null, new Object[]{null, firstArgument}));
+        assertEquals(firstArgument, nodeTarget.call(cInstance, testMethodName, null, new Object[]{null, null, firstArgument}));
+
+    }
+
+    public static class RubyHeadNode extends ExampleNode {
+
+        @Child private RubyLookupNode lookup = RubyLookupNodeGen.create();
+        @Child private RubyDispatchNode dispatch = RubyDispatchNodeGen.create();
+
+        @Specialization
+        public Object doCall(VirtualFrame frame, RubyObject receiverObject, Object methodName, Object blockObject, Object... argumentsObjects) {
+            InternalMethod method = lookup.executeLookup(receiverObject, methodName);
+
+            Object[] packedArguments = new Object[argumentsObjects.length + 3];
+            packedArguments[0] = method;
+            packedArguments[1] = receiverObject;
+            packedArguments[2] = blockObject;
+            System.arraycopy(argumentsObjects, 0, packedArguments, 3, argumentsObjects.length);
+
+            return dispatch.executeDispatch(frame, method, packedArguments);
+        }
+    }
+
+    public abstract static class RubyLookupNode extends Node {
+
+        public abstract InternalMethod executeLookup(RubyObject receiver, Object method);
+
+        @Specialization(guards = "receiver.getRubyClass() == cachedClass", assumptions = "cachedClass.getDependentAssumptions()")
+        protected static InternalMethod cachedLookup(RubyObject receiver, Object name, //
+                        @Cached("receiver.getRubyClass()") RubyClass cachedClass, //
+                        @Cached("genericLookup(receiver, name)") InternalMethod cachedLookup) {
+            return cachedLookup;
+        }
+
+        @Specialization(contains = "cachedLookup")
+        protected static InternalMethod genericLookup(RubyObject receiver, Object name) {
+            return receiver.getRubyClass().lookup(name);
+        }
+
+    }
+
+    @ImportStatic(InternalMethod.class)
+    public abstract static class RubyDispatchNode extends Node {
+
+        public abstract Object executeDispatch(VirtualFrame frame, InternalMethod function, Object[] packedArguments);
+
+        /*
+         * Please note that cachedMethod != METHOD_MISSING is invoked once at specialization
+         * instantiation. It is never executed on the fast path.
+         */
+        @Specialization(guards = {"method == cachedMethod", "cachedMethod != METHOD_MISSING"})
+        protected static Object directCall(VirtualFrame frame, InternalMethod method, Object[] arguments, //
+                        @Cached("method") InternalMethod cachedMethod, //
+                        @Cached("create(cachedMethod.getTarget())") DirectCallNode callNode) {
+            return callNode.call(frame, arguments);
+        }
+
+        /*
+         * The method == METHOD_MISSING can fold if the RubyLookup results just in a single entry
+         * returning the constant METHOD_MISSING.
+         */
+        @Specialization(guards = "method == METHOD_MISSING")
+        protected static Object methodMissing(VirtualFrame frame, InternalMethod method, Object[] arguments) {
+            // a real implementation would do a call to a method named method_missing here
+            return RubyObject.NIL;
+        }
+
+        @Specialization(contains = "directCall", guards = "method != METHOD_MISSING")
+        protected static Object indirectCall(VirtualFrame frame, InternalMethod method, Object[] arguments, //
+                        @Cached("create()") IndirectCallNode callNode) {
+            return callNode.call(frame, method.getTarget(), arguments);
+        }
+
+        @Override
+        public String toString() {
+            return ((SpecializedNode) this).getSpecializationNode().toString();
+        }
+    }
+
+    public static final class RubyObject {
+
+        public static final RubyObject NIL = new RubyObject(null);
+
+        private final RubyClass rubyClass;
+
+        public RubyObject(RubyClass rubyClass) {
+            this.rubyClass = rubyClass;
+        }
+
+        public RubyClass getRubyClass() {
+            return rubyClass;
+        }
+
+        @Override
+        public String toString() {
+            return "RubyObject[class=" + rubyClass + "]";
+        }
+
+    }
+
+    public static final class RubyClass /* this would extend RubyModule */{
+
+        private final String name;
+        private final RubyClass parent; // this would be a RubyModule
+        private final CyclicAssumption unmodified;
+        private final Map<Object, InternalMethod> methods = new HashMap<>();
+        private Assumption[] cachedDependentAssumptions;
+        private final int depth;
+
+        public RubyClass(String name, RubyClass parent) {
+            this.name = name;
+            this.parent = parent;
+            this.unmodified = new CyclicAssumption("unmodified class " + name);
+
+            // lookup depth for array allocation
+            RubyClass clazz = parent;
+            int currentDepth = 1;
+            while (clazz != null) {
+                currentDepth++;
+                clazz = clazz.parent;
+            }
+            this.depth = currentDepth;
+        }
+
+        @TruffleBoundary
+        public InternalMethod lookup(Object methodName) {
+            InternalMethod method = methods.get(methodName);
+            if (method == null) {
+                if (parent != null) {
+                    return parent.lookup(methodName);
+                } else {
+                    return InternalMethod.METHOD_MISSING;
+                }
+            } else {
+                return method;
+            }
+        }
+
+        @TruffleBoundary
+        public void addMethod(Object methodName, InternalMethod method) {
+            // check for existing method omitted for simplicity
+            this.methods.put(methodName, method);
+            this.unmodified.invalidate();
+        }
+
+        /*
+         * Method collects all unmodified assumptions in the class hierarchy. The result is cached
+         * per class to void recreation per call site.
+         */
+        @TruffleBoundary
+        public Assumption[] getDependentAssumptions() {
+            Assumption[] dependentAssumptions = cachedDependentAssumptions;
+            if (dependentAssumptions != null) {
+                // we can use the cached dependent assumptions only if they are still valid
+                for (Assumption assumption : cachedDependentAssumptions) {
+                    if (!assumption.isValid()) {
+                        dependentAssumptions = null;
+                        break;
+                    }
+                }
+            }
+            if (dependentAssumptions == null) {
+                cachedDependentAssumptions = dependentAssumptions = createDependentAssumptions();
+            }
+            return dependentAssumptions;
+        }
+
+        @Override
+        public String toString() {
+            return "RubyClass[name=" + name + "]";
+        }
+
+        private Assumption[] createDependentAssumptions() {
+            Assumption[] dependentAssumptions;
+            RubyClass clazz = this;
+            dependentAssumptions = new Assumption[depth];
+
+            // populate array
+            int index = 0;
+            do {
+                dependentAssumptions[index] = clazz.unmodified.getAssumption();
+                index++;
+                clazz = clazz.parent;
+            } while (clazz != null);
+            return dependentAssumptions;
+        }
+    }
+
+    public static final class InternalMethod {
+
+        public static final InternalMethod METHOD_MISSING = new InternalMethod(null);
+
+        private final CallTarget target;
+
+        public InternalMethod(CallTarget target) {
+            this.target = target;
+        }
+
+        public CallTarget getTarget() {
+            return target;
+        }
+
+        @Override
+        public String toString() {
+            return "InternalMethod[target=" + getTarget() + "]";
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/examples/StableDispatch.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.examples;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+/**
+ * This example is based on the SLDispatchNode of SimpleLanguage. It shows how to implement a simple
+ * inline cache with an assumption that needs to be checked.
+ *
+ * Note that if an assumption is invalidated the specialization instantiation is removed.
+ */
+@SuppressWarnings("unused")
+@NodeChildren({@NodeChild("function"), @NodeChild("arguments")})
+public class StableDispatch {
+
+    public static class StableDispatchNode extends ExampleNode {
+
+        @Specialization(guards = "function == cachedFunction", assumptions = "cachedFunction.getCallTargetStable()")
+        protected static Object directDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, //
+                        @Cached("function") SLFunction cachedFunction, //
+                        @Cached("create(cachedFunction.getCallTarget())") DirectCallNode callNode) {
+            return callNode.call(frame, arguments);
+        }
+
+        @Specialization(contains = "directDispatch")
+        protected static Object indirectDispatch(VirtualFrame frame, SLFunction function, Object[] arguments, //
+                        @Cached("create()") IndirectCallNode callNode) {
+            return callNode.call(frame, function.getCallTarget(), arguments);
+        }
+    }
+
+    public static final class SLFunction {
+
+        private CallTarget callTarget;
+        private final CyclicAssumption callTargetStable;
+
+        protected SLFunction(String name) {
+            this.callTargetStable = new CyclicAssumption(name);
+        }
+
+        protected void setCallTarget(CallTarget callTarget) {
+            this.callTarget = callTarget;
+            this.callTargetStable.invalidate();
+        }
+
+        public CallTarget getCallTarget() {
+            return callTarget;
+        }
+
+        public Assumption getCallTargetStable() {
+            return callTargetStable.getAssumption();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/Compile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.processor;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import javax.tools.*;
+import javax.tools.JavaFileObject.Kind;
+
+final class Compile implements DiagnosticListener<JavaFileObject> {
+    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
+    private final Map<String, byte[]> classes;
+    private final String sourceLevel;
+
+    private Compile(Class<?> processor, String code, String sl) {
+        this.sourceLevel = sl;
+        classes = compile(processor, code);
+    }
+
+    /**
+     * Performs compilation of given HTML page and associated Java code.
+     */
+    public static Compile create(Class<?> processor, String code) {
+        return new Compile(processor, code, "1.7");
+    }
+
+    /** Checks for given class among compiled resources. */
+    public byte[] get(String res) {
+        return classes.get(res);
+    }
+
+    /**
+     * Obtains errors created during compilation.
+     */
+    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
+        List<Diagnostic<? extends JavaFileObject>> err;
+        err = new ArrayList<>();
+        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
+            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
+                err.add(diagnostic);
+            }
+        }
+        return err;
+    }
+
+    private Map<String, byte[]> compile(Class<?> processor, final String code) {
+        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
+
+        final Map<String, ByteArrayOutputStream> class2BAOS;
+        class2BAOS = new HashMap<>();
+
+        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
+            @Override
+            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+                return code;
+            }
+        };
+
+        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
+            @Override
+            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
+                if (kind == Kind.CLASS) {
+                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
+                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
+                        @Override
+                        public OutputStream openOutputStream() {
+                            return buffer;
+                        }
+                    };
+                }
+
+                if (kind == Kind.SOURCE) {
+                    final String n = className.replace('.', '/') + ".java";
+                    final URI un;
+                    try {
+                        un = new URI("mem://" + n);
+                    } catch (URISyntaxException ex) {
+                        throw new IOException(ex);
+                    }
+                    return new VirtFO(un/* sibling.toUri() */, kind, n);
+                }
+
+                throw new IllegalStateException();
+            }
+
+            @Override
+            public boolean isSameFile(FileObject a, FileObject b) {
+                if (a instanceof VirtFO && b instanceof VirtFO) {
+                    return ((VirtFO) a).getName().equals(((VirtFO) b).getName());
+                }
+
+                return super.isSameFile(a, b);
+            }
+
+            class VirtFO extends SimpleJavaFileObject {
+
+                private final String n;
+
+                public VirtFO(URI uri, Kind kind, String n) {
+                    super(uri, kind);
+                    this.n = n;
+                }
+
+                private final ByteArrayOutputStream data = new ByteArrayOutputStream();
+
+                @Override
+                public OutputStream openOutputStream() {
+                    return data;
+                }
+
+                @Override
+                public String getName() {
+                    return n;
+                }
+
+                @Override
+                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+                    data.close();
+                    return new String(data.toByteArray());
+                }
+            }
+        };
+        List<String> args = Arrays.asList("-source", sourceLevel, "-target", "1.7", //
+                        "-processor", processor.getName());
+
+        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, args, null, Arrays.asList(file)).call();
+
+        Map<String, byte[]> result = new HashMap<>();
+
+        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
+            result.put(e.getKey(), e.getValue().toByteArray());
+        }
+
+        return result;
+    }
+
+    @Override
+    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+        errors.add(diagnostic);
+    }
+
+    void assertErrors() {
+        assertFalse("There are supposed to be some errors", getErrors().isEmpty());
+    }
+
+    void assertNoErrors() {
+        assertTrue("There are supposed to be no errors: " + getErrors(), getErrors().isEmpty());
+    }
+
+    void assertError(String expMsg) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Can't find ").append(expMsg).append(" among:");
+        for (Diagnostic<? extends JavaFileObject> e : errors) {
+            String msg = e.getMessage(Locale.US);
+            if (msg.contains(expMsg)) {
+                return;
+            }
+            sb.append("\n");
+            sb.append(msg);
+        }
+        fail(sb.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.processor;
+
+import java.io.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.dsl.test.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+public class LanguageRegistrationTest {
+
+    @ExpectError("Registered language class must be public")
+    @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my")
+    private static final class MyLang {
+    }
+
+    @ExpectError("Registered language inner-class must be static")
+    @TruffleLanguage.Registration(name = "myLangNonStatic", version = "0", mimeType = "text/x-my")
+    public final class MyLangNonStatic {
+    }
+
+    @ExpectError("Registered language class must subclass TruffleLanguage")
+    @TruffleLanguage.Registration(name = "myLang", version = "0", mimeType = "text/x-my")
+    public static final class MyLangNoSubclass {
+    }
+
+    @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter")
+    @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my")
+    public static final class MyLangWrongConstr extends TruffleLanguage {
+        private MyLangWrongConstr() {
+            super(null);
+        }
+
+        @Override
+        protected Object eval(Source code) throws IOException {
+            return null;
+        }
+
+        @Override
+        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+            return null;
+        }
+
+        @Override
+        protected Object getLanguageGlobal() {
+            return null;
+        }
+
+        @Override
+        protected boolean isObjectOfLanguage(Object object) {
+            return false;
+        }
+
+        @Override
+        protected ToolSupportProvider getToolSupport() {
+            return null;
+        }
+
+        @Override
+        protected DebugSupportProvider getDebugSupport() {
+            return null;
+        }
+
+    }
+
+    @ExpectError("Language must have a public constructor accepting TruffleLanguage.Env as parameter")
+    @TruffleLanguage.Registration(name = "myLangNoCnstr", version = "0", mimeType = "text/x-my")
+    public static final class MyLangNoConstr extends TruffleLanguage {
+        public MyLangNoConstr() {
+            super(null);
+        }
+
+        @Override
+        protected Object eval(Source code) throws IOException {
+            return null;
+        }
+
+        @Override
+        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+            return null;
+        }
+
+        @Override
+        protected Object getLanguageGlobal() {
+            return null;
+        }
+
+        @Override
+        protected boolean isObjectOfLanguage(Object object) {
+            return false;
+        }
+
+        @Override
+        protected ToolSupportProvider getToolSupport() {
+            return null;
+        }
+
+        @Override
+        protected DebugSupportProvider getDebugSupport() {
+            return null;
+        }
+
+    }
+
+    @TruffleLanguage.Registration(name = "myLangGood", version = "0", mimeType = "text/x-my")
+    public static final class MyLangGood extends TruffleLanguage {
+        public MyLangGood(TruffleLanguage.Env env) {
+            super(env);
+        }
+
+        @Override
+        protected Object eval(Source code) throws IOException {
+            return null;
+        }
+
+        @Override
+        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+            return null;
+        }
+
+        @Override
+        protected Object getLanguageGlobal() {
+            return null;
+        }
+
+        @Override
+        protected boolean isObjectOfLanguage(Object object) {
+            return false;
+        }
+
+        @Override
+        protected ToolSupportProvider getToolSupport() {
+            return null;
+        }
+
+        @Override
+        protected DebugSupportProvider getDebugSupport() {
+            return null;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/TruffleProcessorTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test.processor;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.tools.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.test.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.verify.*;
+
+/**
+ * Verify errors emitted by the processor.
+ */
+public class TruffleProcessorTest {
+    //
+    // AnnotationProcessor test using the NetBeans style
+    //
+
+    @Test
+    public void childCannotBeFinal() throws Exception {
+        // @formatter:off
+        String code = "package x.y.z;\n" +
+            "import com.oracle.truffle.api.nodes.Node;\n" +
+            "abstract class MyNode extends Node {\n" +
+            "  @Child final MyNode first;\n" +
+            "  MyNode(MyNode n) {\n" +
+            "    this.first = n;\n" +
+            "  };\n" +
+            "}\n";
+        // @formatter:on
+
+        Compile c = Compile.create(VerifyTruffleProcessor.class, code);
+        c.assertErrors();
+        boolean ok = false;
+        StringBuilder msgs = new StringBuilder();
+        for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
+            String msg = e.getMessage(Locale.ENGLISH);
+            if (msg.contains("cannot be final")) {
+                ok = true;
+            }
+            msgs.append("\n").append(msg);
+        }
+        if (!ok) {
+            fail("Should contain warning about final:" + msgs);
+        }
+    }
+
+    @Test
+    public void workAroundCannonicalDependency() throws Exception {
+        Class<?> myProc = VerifyTruffleProcessor.class;
+        assertNotNull(myProc);
+        StringBuilder sb = new StringBuilder();
+        sb.append("Cannot find ").append(myProc);
+        for (Processor load : ServiceLoader.load(Processor.class)) {
+            sb.append("Found ").append(load);
+            if (myProc.isInstance(load)) {
+                return;
+            }
+        }
+        fail(sb.toString());
+    }
+
+    //
+    // and now the Truffle traditional way
+    //
+
+    abstract class MyNode extends Node {
+        @ExpectError("@Child field cannot be final") @Child final MyNode first;
+
+        MyNode(MyNode n) {
+            this.first = n;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+/**
+ * <p>
+ * A parameter annotated with {@link Cached} in a {@link Specialization} refers to a <b>cached</b>
+ * value of a specialization instance. A cached parameter value is initialized once using the
+ * initializer expression at specialization instantiation. For each call of the specialization
+ * method the cached value is provided by using the annotated parameter from the method body. Cache
+ * initializers are potentially executed before guard expressions declared in
+ * {@link Specialization#guards()}.
+ * </p>
+ * <p>
+ * A typical specialization may define multiple dynamic and multiple cached parameters. Dynamic
+ * parameter values are typically provided by executing child nodes of the operation. Cached
+ * parameters are initialized and stored once per specialization instantiation. Cached parameters
+ * are always constant at compile time. You may verify this by invoking
+ * {@link CompilerAsserts#compilationConstant(Object)} on any cached parameter. For consistency
+ * between specialization declarations cached parameters must be declared last in a specialization
+ * method.
+ * </p>
+ * <p>
+ * The initializer expression of a cached parameter is defined using a subset of Java. This subset
+ * includes field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=,
+ * >, >=) and integer literals. The return type of the initializer expression must be assignable to
+ * the parameter type. If the annotated parameter type is derived from {@link Node} then the
+ * {@link Node} instance is allowed to use the {@link Node#replace(Node)} method to replace itself.
+ * Bound elements without receivers are resolved using the following order:
+ * <ol>
+ * <li>Dynamic and cached parameters of the enclosing specialization.</li>
+ * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
+ * <li>Public constructors of the type of the annotated parameter using the <code>new</code> keyword
+ * as method name.</li>
+ * <li>Public and static methods or fields of the type of the annotated parameter.</li>
+ * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
+ * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
+ * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
+ * </ol>
+ *
+ * The following examples explain the intended use of the {@link Cached} annotation. All of the
+ * examples have to be enclosed in the following node declaration:
+ * </p>
+ *
+ * <pre>
+ * @NodeChild("operand")
+ * abstract TestNode extends Node {
+ *   abstract void execute(Object operandValue);
+ *   // ... example here ...
+ * }
+ * </pre>
+ *
+ * <ol>
+ * <li>
+ * This example defines one dynamic and one cached parameter. The operand parameter is representing
+ * the dynamic value of the operand while the cachedOperand is initialized once at first execution
+ * of the specialization (specialization instantiation time).
+ *
+ * <pre>
+ *  &#064;Specialization
+ *  void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
+ *      CompilerAsserts.compilationConstant(cachedOperand);
+ *      ...
+ *  }
+ *
+ *  Example executions:
+ *  execute(1) => doCached(1, 1) // new instantiation, localOperand is bound to 1
+ *  execute(0) => doCached(0, 1)
+ *  execute(2) => doCached(2, 1)
+ *
+ * </pre>
+ *
+ * </li>
+ * <li>
+ * We extend the previous example by a guard for the cachedOperand value to be equal to the dynamic
+ * operand value. This specifies that the specialization is instantiated for each individual operand
+ * value that is provided. There are a lot of individual <code>int</code> values and for each
+ * individual <code>int</code> value a new specialization would get instantiated. The
+ * {@link Specialization#limit()} property defines a limit for the number of specializations that
+ * can get instantiated. If the specialization instantiation limit is reached then no further
+ * specializations are instantiated. Like for other specializations if there are no more
+ * specializations defined an {@link UnsupportedSpecializationException} is thrown. The default
+ * specialization instantiation limit is <code>3</code>.
+ *
+ * <pre>
+ * &#064;Specialization(guards = &quot;operand == cachedOperand&quot;)
+ * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
+ *    CompilerAsserts.compilationConstant(cachedOperand);
+ *    ...
+ * }
+ *
+ * Example executions:
+ * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
+ * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
+ * execute(1) => doCached(1, 1)
+ * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
+ * execute(3) => throws UnsupportedSpecializationException // instantiation limit overflows
+ *
+ * </pre>
+ *
+ * </li>
+ * <li>
+ * To handle the limit overflow we extend our example by an additional specialization named
+ * <code>doNormal</code>. This specialization has the same type restrictions but does not have local
+ * state nor the operand identity guard. It is also declared after <code>doCached</code> therefore
+ * it is only instantiated if the limit of the <code>doCached</code> specialization has been
+ * reached. In other words <code>doNormal</code> is more generic than <code>doCached</code> . The
+ * <code>doNormal</code> specialization uses <code>contains=&quot;doCached&quot;</code> to specify
+ * that all instantiations of <code>doCached</code> get removed if <code>doNormal</code> is
+ * instantiated. Alternatively if the <code>contains</code> relation is omitted then all
+ * <code>doCached</code> instances remain but no new instances are created.
+ *
+ * <code>
+ * &#064;Specialization(guards = &quot;operand == cachedOperand&quot;)
+ * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
+ *    CompilerAsserts.compilationConstant(cachedOperand);
+ *    ...
+ * }
+ *
+ * &#064;Specialization(contains = &quot;doCached&quot;)
+ * void doNormal(int operand) {...}
+ *
+ * Example executions with contains = &quot;doCached&quot;:
+ * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
+ * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
+ * execute(1) => doCached(1, 1)
+ * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
+ * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow; doCached gets removed.
+ * execute(1) => doNormal(1)
+ *
+ * Example executions without contains = &quot;doCached&quot;:
+ * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
+ * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
+ * execute(1) => doCached(1, 1)
+ * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
+ * execute(3) => doNormal(3)    // new instantiation of doNormal due to limit overflow
+ * execute(1) => doCached(1, 1)
+ *
+ * </code>
+ *
+ * </li>
+ * <li>
+ * This next example shows how methods from the enclosing node can be used to initialize cached
+ * parameters. Please note that the visibility of transformLocal must not be <code>private</code>.
+ *
+ * <pre>
+ * &#064;Specialization
+ * void s(int operand, @Cached(&quot;transformLocal(operand)&quot;) int cachedOperand) {
+ * }
+ *
+ * int transformLocal(int operand) {
+ *     return operand & 0x42;
+ * }
+ *
+ * </li>
+ * </pre>
+ * <li>
+ * The <code>new</code> keyword can be used to initialize a cached parameter using a constructor of
+ * the parameter type.
+ *
+ * <pre>
+ * &#064;Specialization
+ * void s(Object operand, @Cached(&quot;new()&quot;) OtherNode someNode) {
+ *     someNode.execute(operand);
+ * }
+ *
+ * static class OtherNode extends Node {
+ *
+ *     public String execute(Object value) {
+ *         throw new UnsupportedOperationException();
+ *     }
+ * }
+ *
+ * </pre>
+ *
+ * </li>
+ * <li>
+ * Java types without public constructor but with a static factory methods can be initialized by
+ * just referencing its static factory method and its parameters. In this case
+ * {@link BranchProfile#create()} is used to instantiate the {@link BranchProfile} instance.
+ *
+ * <pre>
+ * &#064;Specialization
+ * void s(int operand, @Cached(&quot;create()&quot;) BranchProfile profile) {
+ * }
+ * </pre>
+ *
+ * </li>
+ * </ol>
+ *
+ * @see Specialization#guards()
+ * @see Specialization#contains()
+ * @see Specialization#limit()
+ * @see ImportStatic
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface Cached {
+
+    /**
+     * Defines the initializer expression of the cached parameter value.
+     *
+     * @see Cached
+     */
+    String value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/CreateCast.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Specifies a factory method that creates a {@link Node} which is used to cast this child.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface CreateCast {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Fallback.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <p>
+ * A method annotated with {@link Fallback} is treated as a {@link Specialization} that implicitly
+ * links all the guards of all other declared {@link Specialization} annotated methods of the
+ * operation in a negated form. As a consequence it cannot declare any other guards. The expected
+ * signature of the method must match to the signature of a {@link Specialization} with the
+ * additional limitation that only generically executable argument types are allowed. A generically
+ * executable argument is a an argument hat can be executed from the child {@link Node} using an
+ * execute method without {@link UnsupportedOperationException}. In many cases the generically
+ * executable type is {@link Object}. An operation is limited to just one {@link Fallback}
+ * specialization which is always ordered at the end of the specialization chain.
+ * </p>
+ *
+ * <p>
+ * A simple example showing the use of the {@link Fallback} annotation in a DSL operation:
+ * </p>
+ *
+ * <pre>
+ * &#064;Specialization int doInt(int a) {..}
+ * &#064;Specialization int doDouble(double a) {..}
+ * &#064;Fallback int orElse(Object a) {..}
+ * </pre>
+ *
+ * <p>
+ * The previous example could be redeclared just using {@link Specialization} annotated methods as
+ * follows:
+ * </p>
+ *
+ * <pre>
+ * &#064;Specialization int doInt(int a) {..}
+ * &#064;Specialization int doDouble(double a) {..}
+ * &#064;Specialization(guard={"!isInt(a)", "!isDouble(a)"})
+ * int orElse(Object a) {..}
+ * </pre>
+ *
+ * <p>
+ * <b>Performance note:</b> For operations with a lot of {@link Specialization} annotated methods
+ * the use of {@link Fallback} might generate a guard that is very big. Try to avoid the use of
+ * {@link Fallback} for specializations that are significantly important for peak performance.
+ * </p>
+ *
+ * @see Specialization
+ * @see NodeChild
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface Fallback {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GenerateNodeFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotate nodes or base classes of nodes to generate factory handlers implementing the
+ * {@link NodeFactory} interface. The generated factory handlers class name starts with the source
+ * original class and ends with 'Factory'.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface GenerateNodeFactory {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/GeneratedBy.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Marks a type as being generated based on another class or method of a class.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface GeneratedBy {
+
+    Class<?> value();
+
+    String methodName() default "";
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImplicitCast.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface ImplicitCast {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Implies.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Experimental API.
+ *
+ * @deprecated annotation has no effect anymore.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+@Deprecated
+public @interface Implies {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ImportStatic.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Imports all <code>public</code> and <code>static</code> methods and fields of the provided
+ * classes for the use in DSL expressions of the annotated class or its subclasses.
+ *
+ * @see Specialization#guards()
+ * @see Specialization#assumptions()
+ * @see Specialization#limit()
+ * @see Cached
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface ImportStatic {
+
+    Class<?>[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeAssumptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * @deprecated use {@link NodeField} with type {@link Assumption} instead.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+@Deprecated
+public @interface NodeAssumptions {
+
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChild.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A {@link NodeChild} element defines an executable child for the enclosing {@link Node}. A
+ * {@link Node} contains multiple {@link NodeChildren} specified in linear execution order.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeChild {
+
+    String value() default "";
+
+    Class<?> type() default Node.class;
+
+    /**
+     * The {@link #executeWith()} property allows a node to pass the result of one child's
+     * executable as an input to another child's executable. These referenced children must be
+     * defined before the current node in the execution order. The current node {@link #type()}
+     * attribute must be set to a {@link Node} which supports the evaluated execution with the
+     * number of {@link #executeWith()} arguments that are defined. For example if this child is
+     * executed with one argument, the {@link #type()} attribute must define a node which publicly
+     * declares a method with the signature <code>Object execute*(VirtualFrame, Object)</code>.
+     */
+    String[] executeWith() default {};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeChildren.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeChildren {
+
+    NodeChild[] value() default {};
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Enables the dynamic creation of generated nodes. It provides an convenient way to instantiate
+ * generated node classes without using reflection.
+ */
+public interface NodeFactory<T> {
+
+    /**
+     * Instantiates the node using the arguments array. The arguments length and types must suffice
+     * one of the returned signatures in {@link #getNodeSignatures()}. If the arguments array does
+     * not suffice one of the node signatures an {@link IllegalArgumentException} is thrown.
+     *
+     * @param arguments the argument values
+     * @return the instantiated node
+     * @throws IllegalArgumentException
+     */
+    T createNode(Object... arguments);
+
+    /**
+     * Returns the node class that will get created by {@link #createNode(Object...)}. The node
+     * class does not match exactly to the instantiated object but they are guaranteed to be
+     * assignable.
+     */
+    Class<T> getNodeClass();
+
+    /**
+     * Returns a list of signatures that can be used to invoke {@link #createNode(Object...)}.
+     */
+    List<List<Class<?>>> getNodeSignatures();
+
+    /**
+     * Returns a list of children that will be executed by the created node. This is useful for base
+     * nodes that can execute a variable amount of nodes.
+     */
+    List<Class<? extends Node>> getExecutionSignature();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeField.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A {@link NodeField} element defines a field for the generated {@link Node}. A {@link Node}
+ * contains multiple {@link NodeFields} specified in linear declaration order. The field can be
+ * accessed by declaring an abstract getter named
+ * <code>"get" + firstLetterUpperCase({@link #name()})()</code>.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeField {
+
+    String name();
+
+    Class<?> type();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/NodeFields.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A {@link NodeFields} element defines a field for the generated {@link Node}. A {@link Node}
+ * contains multiple {@link NodeFields} specified in linear declaration order. The field can be
+ * accessed by declaring an abstract getter named
+ * <code>"get" + firstLetterUpperCase({@link #value()})()</code>.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface NodeFields {
+
+    NodeField[] value() default {};
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/ShortCircuit.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface ShortCircuit {
+
+    String value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <p>
+ * Defines a method of a node subclass to represent one specialization of an operation. Multiple
+ * specializations can be defined in a node representing an operation. A specialization defines
+ * which kind of input is expected using the method signature and the annotation attributes. The
+ * specialized semantics of the operation are defined using the body of the annotated Java method. A
+ * specialization method must be declared in a class that is derived from {@link Node} that
+ * references a {@link TypeSystem}. At least one specialization must be defined per operation. If no
+ * specialization is valid for the given set of input values then an
+ * {@link UnsupportedSpecializationException} is thrown instead of invoking any specialization
+ * method.
+ * </p>
+ * <p>
+ * A specialization must have at least as many parameters as there are {@link NodeChild} annotations
+ * declared for the enclosing operation node. These parameters are declared in the same order as the
+ * {@link NodeChild} annotations (linear execution order). We call such parameters dynamic input
+ * parameters. Every specialization that is declared within an operation must have an equal number
+ * of dynamic input parameters.
+ * </p>
+ * <p>
+ * The supported kind of input values for a specialization are declared using guards. A
+ * specialization may provide declarative specifications for four kinds of guards:
+ * <ul>
+ * <li><b>Type guards</b> optimistically assume the type of an input value. A value that matches the
+ * type is cast to its expected type automatically. Type guards are modeled using the parameter type
+ * of the specialization method. Types used for type guards must be defined in the
+ * {@link TypeSystem}. If the type of the parameter is {@link Object} then no type guard is used for
+ * the dynamic input parameter.</li>
+ *
+ * <li><b>Expression guards</b> optimistically assume the return value of a user-defined expression
+ * to be <code>true</code>. Expression guards are modeled using Java expressions that return a
+ * <code>boolean</code> value. If the guard expression returns <code>false</code>, the
+ * specialization is no longer applicable and the operation is re-specialized. Guard expressions are
+ * declared using the {@link #guards()} attribute.</li>
+ *
+ * <li><b>Event guards</b> trigger re-specialization in case an exception is thrown in the
+ * specialization body. The {@link #rewriteOn()} attribute can be used to declare a list of such
+ * exceptions. Guards of this kind are useful to avoid calculating a value twice when it is used in
+ * the guard and its specialization.</li>
+ *
+ * <li><b>Assumption guards</b> optimistically assume that the state of an {@link Assumption}
+ * remains <code>true</code>. Assumptions can be assigned to specializations using the
+ * {@link #assumptions()} attribute.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The enclosing {@link Node} of a specialization method must have at least one <code>public</code>
+ * and non-<code>final</code> execute method. An execute method is a method that starts with
+ * 'execute'. If all execute methods declare the first parameter type as {@link Frame},
+ * {@link VirtualFrame} or {@link MaterializedFrame} then the same frame type can be used as
+ * optional first parameter of the specialization. This parameter does not count to the number of
+ * dynamic parameters.
+ * </p>
+ * <p>
+ * A specialization method may declare multiple parameters annotated with {@link Cached}. Cached
+ * parameters are initialized and stored once per specialization instantiation. For consistency
+ * between specialization declarations cached parameters must be declared last in a specialization
+ * method.
+ * </p>
+ * <p>
+ * If the operation is re-specialized or if it is executed for the first time then all declared
+ * specializations of the operation are tried in declaration order until the guards of the first
+ * specialization accepts the current input values. The new specialization is then added to the
+ * chain of current specialization instances which might consist of one (monomorph) or multiple
+ * instances (polymorph). If an assumption of an instantiated specialization is violated then
+ * re-specialization is triggered again.
+ * </p>
+ * <p>
+ * With guards in combination with cached parameters it is possible that multiple instances of the
+ * same specialization are created. The {@link #limit()} attribute can be used to limit the number
+ * of instantiations per specialization.
+ * </p>
+ *
+ * @see NodeChild
+ * @see ShortCircuit
+ * @see Fallback
+ * @see Cached
+ * @see TypeSystem
+ * @see TypeSystemReference
+ * @see UnsupportedSpecializationException
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface Specialization {
+
+    /**
+     * @deprecated do not use anymore. Will get removed in the next release.
+     */
+    @Deprecated int DEFAULT_ORDER = -1;
+
+    /**
+     * @deprecated use declaration order instead. Will get removed in the next release.
+     */
+    @Deprecated
+    int order() default DEFAULT_ORDER;
+
+    /**
+     * References a specialization of a super class by its method name where this specialization is
+     * inserted before. The declaration order of a specialization is not usable for nodes where
+     * specializations are partly declared in the super class and partly declared in a derived
+     * class. By default all specializations declared in the derived class are appended to those in
+     * the super class. This attribute can be used to override the default behavior.
+     */
+    String insertBefore() default "";
+
+    /**
+     * <p>
+     * Declares an event guards that trigger re-specialization in case an exception is thrown in the
+     * specialization body. This attribute can be used to declare a list of such exceptions. Guards
+     * of this kind are useful to avoid calculating a value twice when it is used in the guard and
+     * its specialization.
+     * </p>
+     *
+     * <p>
+     * If an event guard exception is triggered then all instantiations of this specialization are
+     * removed. If one of theses exceptions is thrown once then no further instantiations of this
+     * specialization are going to be created for this node. A specialization that rewrites on an
+     * exception must ensure that no non-repeatable side-effect is caused until the rewrite is
+     * triggered.
+     * </p>
+     *
+     * <b>Example usage:</b>
+     *
+     * <pre>
+     * &#064;Specialization(rewriteOn = ArithmeticException.class)
+     * int doAddNoOverflow(int a, int b) {
+     *     return ExactMath.addExact(a, b);
+     * }
+     * &#064;Specialization
+     * long doAddWithOverflow(int a, int b) {
+     *     return a + b;
+     * }
+     * ...
+     * Example executions:
+     *   execute(Integer.MAX_VALUE - 1, 1) => doAddNoOverflow(Integer.MAX_VALUE - 1, 1)
+     *   execute(Integer.MAX_VALUE, 1)     => doAddNoOverflow(Integer.MAX_VALUE, 1)
+     *                                     => throws ArithmeticException
+     *                                     => doAddWithOverflow(Integer.MAX_VALUE, 1)
+     *   execute(Integer.MAX_VALUE - 1, 1) => doAddWithOverflow(Integer.MAX_VALUE - 1, 1)
+     * </pre>
+     *
+     * </p>
+     *
+     * @see ExactMath#addExact(int, int)
+     */
+    Class<? extends Throwable>[] rewriteOn() default {};
+
+    /**
+     * <p>
+     * Declares other specializations of the same node to be contained by this specialization. Other
+     * specializations are references using their unique method name. If this specialization is
+     * instantiated then all contained specialization instances are removed and never instantiated
+     * again for this node instance. Therefore this specialization should handle strictly more
+     * inputs than which were handled by the contained specialization, otherwise the removal of the
+     * contained specialization will lead to unspecialized types of input values. The contains
+     * declaration is transitive for multiple involved specializations.
+     * </p>
+     * <b>Example usage:</b>
+     *
+     * <pre>
+     * &#064;Specialization(guards = "b == 2")
+     * void doDivPowerTwo(int a, int b) {
+     *     return a >> 1;
+     * }
+     * &#064;Specialization(contains ="doDivPowerTwo", guards = "b > 0")
+     * void doDivPositive(int a, int b) {
+     *     return a / b;
+     * }
+     * ...
+     * Example executions with contains="doDivPowerTwo":
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     *   execute(9, 3) => doDivPositive(9, 3) // doDivPowerTwo instances get removed
+     *   execute(4, 2) => doDivPositive(4, 2)
+     * Same executions without contains="doDivPowerTwo"
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     *   execute(9, 3) => doDivPositive(9, 3)
+     *   execute(4, 2) => doDivPowerTwo(4, 2)
+     * </pre>
+     *
+     * </p>
+     *
+     * @see #guards()
+     */
+    String[] contains() default {};
+
+    /**
+     * <p>
+     * Declares <code>boolean</code> expressions that define whether or not input values are
+     * applicable to this specialization instance. Guard expressions must always return the same
+     * result for each combination of the enclosing node instance and the bound input values.
+     * </p>
+     * <p>
+     * If a guard expression does not bind any dynamic input parameters then the DSL assumes that
+     * the result will not change for this node after specialization instantiation. The DSL asserts
+     * this assumption if assertions are enabled (-ea).
+     * </p>
+     * <p>
+     * Guard expressions are defined using a subset of Java. This subset includes field/parameter
+     * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
+     * negation (!), logical disjunction (||) and integer literals. The return type of guard
+     * expressions must be <code>boolean</code>. Bound elements without receivers are resolved using
+     * the following order:
+     * <ol>
+     * <li>Dynamic and cached parameters of the enclosing specialization.</li>
+     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
+     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
+     * </ol>
+     * </p>
+     * <p>
+     * <b>Example usage:</b>
+     *
+     * <pre>
+     * static boolean acceptOperand(int operand) {
+     *     assert operand <= 42;
+     *     return operand & 1 == 1;
+     * }
+     * &#064;Specialization(guards = {"operand <= 42", "acceptOperand(operand)"})
+     * void doSpecialization(int operand) {...}
+     * </pre>
+     *
+     * </p>
+     *
+     * @see Cached
+     * @see ImportStatic
+     */
+    String[] guards() default {};
+
+    /**
+     * <p>
+     * Declares assumption guards that optimistically assume that the state of an {@link Assumption}
+     * remains valid. Assumption expressions are cached once per specialization instantiation. If
+     * one of the returned assumptions gets invalidated then the specialization instance is removed.
+     * If the assumption expression returns an array of assumptions then all assumptions of the
+     * array are checked. This is limited to one-dimensional arrays.
+     * </p>
+     * <p>
+     * Assumption expressions are defined using a subset of Java. This subset includes
+     * field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=, >,
+     * >=), logical negation (!), logical disjunction (||) and integer literals. The return type of
+     * the expression must be {@link Assumption} or an array of {@link Assumption} instances.
+     * Assumption expressions are not allowed to bind to dynamic parameter values of the
+     * specialization. Bound elements without receivers are resolved using the following order:
+     * <ol>
+     * <li>Cached parameters of the enclosing specialization.</li>
+     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
+     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
+     * </ol>
+     * </p>
+     *
+     * <p>
+     * <b>Example usage:</b>
+     *
+     * <pre>
+     * static abstract class DynamicObject() {
+     *      abstract Shape getShape();
+     *      ...
+     * }
+     * static abstract class Shape() {
+     *      abstract Assumption getUnmodifiedAssuption();
+     *      ...
+     * }
+     * &#064;Specialization(guards = "operand.getShape() == cachedShape", assumptions = "cachedShape.getUnmodifiedAssumption()")
+     * void doAssumeUnmodifiedShape(DynamicObject operand, @Cached("operand.getShape()") Shape cachedShape) {...}
+     * </pre>
+     *
+     * </p>
+     *
+     * @see Cached
+     * @see ImportStatic
+     */
+    String[] assumptions() default {};
+
+    /**
+     * <p>
+     * Declares the expression that limits the number of specialization instantiations. The default
+     * limit for specialization instantiations is defined as <code>"3"</code>. If the limit is
+     * exceeded no more instantiations of the enclosing specialization method are created. Please
+     * note that the existing specialization instantiations are <b>not</b> removed from the
+     * specialization chain. You can use {@link #contains()} to remove unnecessary specializations
+     * instances.
+     * </p>
+     * <p>
+     * The limit expression is defined using a subset of Java. This subset includes field/parameter
+     * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
+     * negation (!), logical disjunction (||) and integer literals. The return type of the limit
+     * expression must be <code>int</code>. Limit expressions are not allowed to bind to dynamic
+     * parameter values of the specialization. Bound elements without receivers are resolved using
+     * the following order:
+     * <ol>
+     * <li>Cached parameters of the enclosing specialization.</li>
+     * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
+     * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
+     * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
+     * </ol>
+     * </p>
+     *
+     * <p>
+     * <b>Example usage:</b>
+     *
+     * <pre>
+     * static int getCacheLimit() {
+     *     return Integer.parseInt(System.getProperty("language.cacheLimit"));
+     * }
+     * &#064;Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()")
+     * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...}
+     * </pre>
+     *
+     * </p>
+     *
+     * @see #guards()
+     * @see #contains()
+     * @see Cached
+     * @see ImportStatic
+     */
+    String limit() default "";
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCast.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Overrides the standard way of casting a certain type in a {@link TypeSystem}. This is useful for
+ * types where the guest language specific type cast can be implemented more efficiently than an
+ * instanceof check. The annotated method must be contained in a {@link TypeSystem} annotated class.
+ * Type checks must conform to the following signature: <code>public static Type as{TypeName}(Object
+ * value)</code>. The casted type must be a type declared in the {@link TypeSystem}.
+ *
+ * <p>
+ * If no {@link TypeCast} is declared then the type system implicitly uses a type cast that can be
+ * declared as follows:
+ *
+ * <pre>
+ * {@literal @}TypeCast(Type.class)
+ * public static Type asType(Object value) {
+ *         return (Type) value;
+ * }
+ * </pre>
+ *
+ * @see TypeCheck
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface TypeCast {
+
+    Class<?> value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeCheck.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+/**
+ * Overrides the standard way of checking for a certain type in a {@link TypeSystem}. This is useful
+ * for types where the guest language specific type check can be implemented more efficiently than a
+ * direct cast. The annotated method must be contained in a {@link TypeSystem} annotated class. Type
+ * checks must conform to the following signature: <code>public static boolean is{TypeName}(Object
+ * value)</code>. The checked type must be a type declared in the {@link TypeSystem}.
+ *
+ * <p>
+ * If no {@link TypeCheck} is declared then the type system implicitly uses a type check that can be
+ * declared as follows:
+ *
+ * <pre>
+ * {@literal @}TypeCheck(Type.class)
+ * public static boolean isType(Object value) {
+ *         return value instanceof Type;
+ * }
+ * </pre>
+ *
+ * @see TypeCast
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface TypeCheck {
+
+    Class<?> value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystem.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <p>
+ * Each {@link Node} has one {@link TypeSystem} at its root to define the types that can be used
+ * throughout the system. Multiple {@link TypeSystem}s are allowed, but they cannot be mixed inside
+ * a single {@link Node} hierarchy. A {@link TypeSystem} defines a list of types as its child
+ * elements, in which every type precedes its super types.The latter condition ensures that the most
+ * concrete type is found first when searching the list sequentially for the type of a given generic
+ * value.
+ * </p>
+ *
+ * <p>
+ * Each {@link #value()} is represented as a java type. A type can specify two annotations:
+ * {@link TypeCheck} and {@link TypeCast}. The {@link TypeCheck} checks whether a given generic
+ * value matches to the current type. The {@link TypeCast} casts a generic type value to the current
+ * type. If the {@link TypeCheck} and {@link TypeCast} annotations are not declared in the
+ * {@link TypeSystem} the a default implementation is provided. The default implementation of
+ * {@link TypeCheck} returns <code>true</code> only on an exact type match and {@link TypeCast} is
+ * only a cast to this type. Specified methods with {@link TypeCheck} and {@link TypeCast} may be
+ * used to extend the definition of a type in the language. In our example, the
+ * <code>isInteger</code> and <code>asInteger</code> methods are defined in a way so that they
+ * accept also {@link Integer} values, implicitly converting them to {@link Double} . This example
+ * points out how we express implicit type conversions.
+ * </p>
+ *
+ * <p>
+ * <b>Example:</b> The {@link TypeSystem} contains the types {@link Boolean}, {@link Integer}, and
+ * {@link Double}. The type {@link Object} is always used implicitly as the generic type represent
+ * all values.
+ *
+ * <pre>
+ *
+ * {@literal @}TypeSystem(types = {boolean.class, int.class, double.class})
+ * public abstract class ExampleTypeSystem {
+ *
+ *     {@literal @}TypeCheck
+ *     public boolean isInteger(Object value) {
+ *         return value instanceof Integer || value instanceof Double;
+ *     }
+ *
+ *     {@literal @}TypeCast
+ *     public double asInteger(Object value) {
+ *         return ((Number)value).doubleValue();
+ *     }
+ * }
+ * </pre>
+ *
+ *
+ * @see TypeCast
+ * @see TypeCheck
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface TypeSystem {
+
+    /**
+     * The list of types as child elements of the {@link TypeSystem}. Each precedes its super type.
+     */
+    Class<?>[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/TypeSystemReference.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * References a {@link TypeSystem} on a node. Must be applied on a {@link Node} class. At least one
+ * {@link TypeSystem} must be referenced in a {@link Node}'s type hierarchy.
+ *
+ * @see TypeSystem
+ * @see Node
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE})
+public @interface TypeSystemReference {
+
+    /** The {@link TypeSystem} java type. */
+    Class<?> value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Thrown by the generated code of Truffle-DSL if no compatible Specialization could be found for
+ * the provided values.
+ */
+public final class UnsupportedSpecializationException extends RuntimeException {
+
+    private static final long serialVersionUID = -2122892028296836269L;
+
+    private final Node node;
+    private final Node[] suppliedNodes;
+    private final Object[] suppliedValues;
+
+    @TruffleBoundary
+    public UnsupportedSpecializationException(Node node, Node[] suppliedNodes, Object... suppliedValues) {
+        Objects.requireNonNull(suppliedNodes, "The suppliedNodes parameter must not be null.");
+        if (suppliedNodes.length != suppliedValues.length) {
+            throw new IllegalArgumentException("The length of suppliedNodes must match the length of suppliedValues.");
+        }
+        this.node = node;
+        this.suppliedNodes = suppliedNodes;
+        this.suppliedValues = suppliedValues;
+    }
+
+    @Override
+    public String getMessage() {
+        return String.format("Unexpected values provided for %s: %s", node, Arrays.toString(suppliedValues));
+    }
+
+    /**
+     * Returns the {@link Node} that caused the this {@link UnsupportedSpecializationException}.
+     */
+    public Node getNode() {
+        return node;
+    }
+
+    /**
+     * Returns the children of the {@link Node} returned by {@link #getNode()} which produced the
+     * values returned by {@link #getSuppliedValues()}. The array returned by
+     * {@link #getSuppliedNodes()} has the same length as the array returned by
+     * {@link #getSuppliedValues()}. Never returns null.
+     */
+    public Node[] getSuppliedNodes() {
+        return suppliedNodes;
+    }
+
+    /**
+     * Returns the dynamic values that were supplied to the node.The array returned by
+     * {@link #getSuppliedNodes()} has the same length as the array returned by
+     * {@link #getSuppliedValues()}. Never returns null.
+     */
+    public Object[] getSuppliedValues() {
+        return suppliedValues;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public final class DSLMetadata {
+
+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[]{};
+    public static final DSLMetadata NONE = new DSLMetadata(null, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, 0, 0);
+
+    private final Class<?> specializationClass;
+    private final Class<?>[] includes;
+    private final Class<?>[] excludedBy;
+    private final Class<?>[] specializedTypes;
+
+    private final int costs;
+    private final int order;
+
+    public DSLMetadata(Class<?> specializationClass, Class<?>[] includes, Class<?>[] excludes, Class<?>[] specializedTypes, int costs, int order) {
+        this.specializationClass = specializationClass;
+        this.includes = includes;
+        this.excludedBy = excludes;
+        this.specializedTypes = specializedTypes;
+        this.costs = costs;
+        this.order = order;
+    }
+
+    public Class<?> getSpecializationClass() {
+        return specializationClass;
+    }
+
+    public Class<?>[] getSpecializedTypes() {
+        return specializedTypes;
+    }
+
+    Class<?>[] getIncludes() {
+        return includes;
+    }
+
+    Class<?>[] getExcludedBy() {
+        return excludedBy;
+    }
+
+    int getCosts() {
+        return costs;
+    }
+
+    int getOrder() {
+        return order;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public interface DSLNode {
+
+    DSLMetadata getMetadata0();
+
+    void adoptChildren0(Node other, Node next);
+
+    void updateTypes0(Class<?>[] types);
+
+    Node getNext0();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLOptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.lang.annotation.*;
+
+/**
+ * Internal DSL options to tune the generated code. These are expert options and not intended to be
+ * changed used for guest language implementations.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface DSLOptions {
+
+    /** Flag has no effect anymore. Is going to be removed soon. */
+    @Deprecated
+    boolean useNewLayout() default true;
+
+    /**
+     * Lazy class loading ensures that all generated specialization classes are loaded lazily.
+     * Disabling this feature will eagerly load all classes but will also reduce the generated code
+     * size.
+     */
+    boolean useLazyClassLoading() default true;
+
+    /**
+     * Sets the optimization strategy for implicit casts.
+     */
+    ImplicitCastOptimization implicitCastOptimization() default ImplicitCastOptimization.DUPLICATE_TAIL;
+
+    /** Not yet implemented. */
+    boolean useDisjunctiveMethodGuardOptimization() default true;
+
+    public enum ImplicitCastOptimization {
+
+        /** Perform no informed optimization for implicit casts. */
+        NONE,
+
+        /** Duplicate specializations for each used implicit cast combination. */
+        DUPLICATE_TAIL,
+
+        /**
+         * Use the same specialization for multiple combinations of implicit casts and specialize
+         * them independently. Not yet fully implemented.
+         */
+        MERGE_CASTS;
+
+        public boolean isNone() {
+            return this == NONE;
+        }
+
+        public boolean isDuplicateTail() {
+            return this == DUPLICATE_TAIL;
+        }
+
+        public boolean isMergeCasts() {
+            return this == MERGE_CASTS;
+        }
+    }
+
+    public enum TypeBoxingOptimization {
+        /** Perform the optimization for all types. */
+        ALWAYS,
+        /** Perform the optimization just for primitive types. */
+        PRIMITIVE,
+        /** Perform the optimization for no types. */
+        NONE;
+    }
+
+    /**
+     * Defines the range of the generation of type specialized execute methods for return types and
+     * for specialized parameter types. A type specialized execute method is generated as soon as
+     * one declared type is either returned or used a specialized parameter.
+     */
+    TypeBoxingOptimization monomorphicTypeBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
+
+    /**
+     * Defines the range of types for which type specialized execute methods should be used for
+     * polymorphic operations.
+     */
+    TypeBoxingOptimization polymorphicTypeBoxingElimination() default TypeBoxingOptimization.PRIMITIVE;
+
+    /**
+     * Defines the range of types for which type specialized execute methods for implicit cast
+     * optimizations are used. This option only has an effect if
+     * {@link ImplicitCastOptimization#DUPLICATE_TAIL} or
+     * {@link ImplicitCastOptimization#MERGE_CASTS} is set in {@link #implicitCastOptimization()}.
+     */
+    TypeBoxingOptimization implicitTypeBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
+
+    /**
+     * Defines range of specialization return types in which the void boxing optimization is used.
+     * Void boxing generates an extra execute method with {@link Void} return type in order to avoid
+     * boxing and type checking of the return type in case the return type is not needed. For this
+     * to work the operation class needs to provide an overridable execute method returning
+     * {@link Void}.
+     */
+    TypeBoxingOptimization voidBoxingOptimization() default TypeBoxingOptimization.PRIMITIVE;
+
+    public enum FallbackOptimization {
+        /** Always generate an optimized fallback specialization. */
+        ALWAYS,
+
+        /**
+         * Only generate an optimized fallback specialization if a method annotated with @Fallback
+         * is used in the operation.
+         */
+        DECLARED,
+
+        /**
+         * Never generate an optimized fallback specialization. Please be aware that triggering a @Fallback
+         * case without optimization will also invalidate your compiled code.
+         */
+        NEVER;
+    }
+
+    /** Defines the optimization strategy that is used to optimize @Fallback annotated methods. */
+    FallbackOptimization optimizeFallback() default FallbackOptimization.DECLARED;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/** Contains utility classes shared across generated DSLNode implementations. */
+public class DSLShare {
+
+    public static boolean isExcluded(Node currentNode, DSLMetadata otherMetadata) {
+        assert otherMetadata.getExcludedBy().length > 0 : "At least one exclude must be defined for isIncluded.";
+        Node cur = findRoot(currentNode);
+        while (cur != null) {
+            Class<?> curClass = cur.getClass();
+            if (curClass == otherMetadata.getSpecializationClass()) {
+                return true;
+            } else if (containsClass(otherMetadata.getExcludedBy(), cur)) {
+                return true;
+            }
+            cur = getNext(cur);
+        }
+        return false;
+    }
+
+    private static boolean includes(Node oldNode, DSLNode newNode) {
+        return containsClass(newNode.getMetadata0().getIncludes(), oldNode);
+    }
+
+    public static <T extends Node & DSLNode> T rewrite(final Node thisNode, final T newNode, final String message) {
+        return thisNode.atomic(new Callable<T>() {
+            public T call() {
+                assert newNode != null;
+                if (getNext(thisNode) != null || getPrevious(thisNode) != null) {
+                    // already polymorphic -> append
+                    return appendPolymorphic(findUninitialized(thisNode), newNode);
+                } else if (includes(thisNode, newNode)) {
+                    // included -> remains monomorphic
+                    newNode.adoptChildren0(thisNode, null);
+                    return thisNode.replace(newNode, message);
+                } else {
+                    // goto polymorphic
+                    return null;
+                }
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T findRoot(T node) {
+        Node prev = node;
+        Node cur;
+        do {
+            cur = prev;
+            prev = getPrevious(cur);
+        } while (prev != null);
+        return (T) cur;
+    }
+
+    private static Node findUninitialized(Node node) {
+        Node next = node;
+        Node cur;
+        do {
+            cur = next;
+            next = getNext(cur);
+        } while (next != null);
+        return cur;
+    }
+
+    public static <T extends Node & DSLNode> T rewriteUninitialized(final Node uninitialized, final T newNode) {
+        return uninitialized.atomic(new Callable<T>() {
+            public T call() {
+                Node prev = getPrevious(uninitialized);
+                if (prev == null) {
+                    newNode.adoptChildren0(uninitialized, null);
+                    return uninitialized.replace(newNode, "Uninitialized monomorphic");
+                } else {
+                    return appendPolymorphic(uninitialized, newNode);
+                }
+            }
+        });
+
+    }
+
+    public static <T extends Node & DSLNode> T rewriteToPolymorphic(final Node oldNode, final DSLNode uninitializedDSL, final T polymorphic, final DSLNode currentCopy, final DSLNode newNodeDSL,
+                    final String message) {
+        return oldNode.atomic(new Callable<T>() {
+            public T call() {
+                assert getNext(oldNode) == null;
+                assert getPrevious(oldNode) == null;
+                assert newNodeDSL != null;
+
+                Node uninitialized = (Node) uninitializedDSL;
+                Node newNode = (Node) newNodeDSL;
+                polymorphic.adoptChildren0(oldNode, (Node) currentCopy);
+
+                updateSourceSection(oldNode, uninitialized);
+                // new specialization
+                updateSourceSection(oldNode, newNode);
+                newNodeDSL.adoptChildren0(null, uninitialized);
+                currentCopy.adoptChildren0(null, newNode);
+
+                oldNode.replace(polymorphic, message);
+
+                assert newNode != null ? currentCopy.getNext0() == newNode : currentCopy.getNext0() == uninitialized;
+                assert uninitializedDSL.getNext0() == null;
+                return polymorphic;
+            }
+        });
+    }
+
+    private static void updateSourceSection(Node oldNode, Node newNode) {
+        if (newNode.getSourceSection() == null) {
+            newNode.assignSourceSection(oldNode.getSourceSection());
+        }
+    }
+
+    private static Class<?>[] mergeTypes(DSLNode node, Class<?>[] types) {
+        Class<?>[] specializedTypes = node.getMetadata0().getSpecializedTypes();
+        if (specializedTypes.length == 0) {
+            return null;
+        } else if (types == null) {
+            return Arrays.copyOf(specializedTypes, specializedTypes.length);
+        } else {
+            for (int i = 0; i < specializedTypes.length; i++) {
+                if (specializedTypes[i] != types[i]) {
+                    types[i] = Object.class;
+                }
+            }
+            return types;
+        }
+    }
+
+    private static <T extends Node & DSLNode> T appendPolymorphic(Node uninitialized, T newNode) {
+        Class<?>[] includes = newNode.getMetadata0().getIncludes();
+        Node cur = getPrevious(uninitialized);
+        Node prev = uninitialized;
+        int depth = 0;
+        Class<?>[] types = null;
+        while (cur != null) {
+            if (containsClass(includes, cur)) {
+                cur.replace(prev, "Included in other specialization");
+                cur = prev;
+            } else {
+                depth++;
+                types = mergeTypes((DSLNode) cur, types);
+            }
+            prev = cur;
+            cur = getPrevious(cur);
+        }
+        assert prev.getCost() == NodeCost.POLYMORPHIC;
+
+        updateSourceSection(prev, newNode);
+        if (depth <= 1) {
+            newNode.adoptChildren0(prev, null);
+            return prev.replace(newNode, "Polymorphic to monomorphic.");
+        } else {
+            newNode.adoptChildren0(null, uninitialized);
+            ((DSLNode) prev).updateTypes0(mergeTypes(newNode, types));
+            return uninitialized.replace(newNode, "Appended polymorphic");
+        }
+    }
+
+    private static boolean containsClass(Class<?>[] classList, Node node) {
+        Class<?> nodeClass = node.getClass();
+        for (Class<?> toCheck : classList) {
+            if (nodeClass == toCheck) {
+                if (node.getCost() == NodeCost.UNINITIALIZED) {
+                    /*
+                     * In case a specialization is excluded by the fallback specialization the
+                     * uninitialized class is used as exclusion class. Because the fallback field in
+                     * the uninitialized specialization is not accessible we use the costs to check
+                     * if the fallback was reached or not. In case the fallback was reached in the
+                     * uninitialized version the cost is MONOMORPHIC, otherwise it is UNINITIALIZED.
+                     */
+                    continue;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Node getNext(Node node) {
+        return ((DSLNode) node).getNext0();
+    }
+
+    private static Node getPrevious(Node node) {
+        Node parent = node.getParent();
+        if (parent instanceof DSLNode && getNext(parent) == node) {
+            return parent;
+        } else {
+            return null;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public abstract class NodeFactoryBase<T> implements NodeFactory<T> {
+
+    private final Class<T> nodeClass;
+    private final Class<?>[][] nodeSignatures;
+    private final Class<? extends Node>[] executionSignatures;
+
+    @SuppressWarnings("unchecked")
+    public NodeFactoryBase(Class<T> nodeClass, Class<?>[] executionSignatures, Class<?>[][] nodeSignatures) {
+        this.nodeClass = nodeClass;
+        this.nodeSignatures = nodeSignatures;
+        this.executionSignatures = (Class<? extends Node>[]) executionSignatures;
+    }
+
+    public abstract T createNode(Object... arguments);
+
+    public final Class<T> getNodeClass() {
+        return nodeClass;
+    }
+
+    public final List<List<Class<?>>> getNodeSignatures() {
+        List<List<Class<?>>> signatures = new ArrayList<>();
+        for (int i = 0; i < nodeSignatures.length; i++) {
+            signatures.add(Arrays.asList(nodeSignatures[i]));
+        }
+        return signatures;
+    }
+
+    public final List<Class<? extends Node>> getExecutionSignature() {
+        return Arrays.asList(executionSignatures);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SlowPathEvent.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Lazy rewrite event that implements {@link CharSequence} to be provided as message in
+ * {@link Node#replace(Node, CharSequence)}.
+ */
+abstract class SlowPathEvent implements CharSequence {
+
+    protected final SpecializationNode source;
+    protected final String reason;
+    protected final Frame frame;
+    private String message;
+
+    SlowPathEvent(SpecializationNode source, String reason, Frame frame) {
+        this.source = source;
+        this.reason = reason;
+        this.frame = frame;
+    }
+
+    public int length() {
+        return getMessage().length();
+    }
+
+    public char charAt(int index) {
+        return getMessage().charAt(index);
+    }
+
+    public CharSequence subSequence(int start, int end) {
+        return getMessage().subSequence(start, end);
+    }
+
+    @Override
+    public String toString() {
+        return getMessage();
+    }
+
+    private String getMessage() {
+        if (message == null) {
+            message = createMessage();
+        }
+        return message;
+    }
+
+    private String createMessage() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(source);
+        builder.append(" ");
+        builder.append(reason);
+        Object[] values = getValues();
+        if (values.length > 0) {
+            builder.append(" with parameters (");
+            String sep = "";
+            for (Object value : values) {
+                builder.append(sep);
+                if (value == null) {
+                    builder.append("null");
+                } else {
+                    builder.append(value).append(" (").append(value.getClass().getSimpleName()).append(")");
+                }
+
+                sep = ", ";
+            }
+            builder.append(")");
+        }
+        return builder.toString();
+    }
+
+    public abstract Object[] getValues();
+
+    static class SlowPathEvent0 extends SlowPathEvent {
+
+        private static final Object[] EMPTY = new Object[0];
+
+        public SlowPathEvent0(SpecializationNode source, String reason, Frame frame) {
+            super(source, reason, frame);
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return EMPTY;
+        }
+
+    }
+
+    static class SlowPathEvent1 extends SlowPathEvent {
+
+        protected final Object o1;
+
+        public SlowPathEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
+            super(source, reason, frame);
+            this.o1 = o1;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return new Object[]{o1};
+        }
+
+    }
+
+    static class SlowPathEvent2 extends SlowPathEvent {
+
+        protected final Object o1;
+        protected final Object o2;
+
+        public SlowPathEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
+            super(source, reason, frame);
+            this.o1 = o1;
+            this.o2 = o2;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return new Object[]{o1, o2};
+        }
+
+    }
+
+    static class SlowPathEvent3 extends SlowPathEvent {
+
+        protected final Object o1;
+        protected final Object o2;
+        protected final Object o3;
+
+        public SlowPathEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
+            super(source, reason, frame);
+            this.o1 = o1;
+            this.o2 = o2;
+            this.o3 = o3;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return new Object[]{o1, o2, o3};
+        }
+
+    }
+
+    static class SlowPathEvent4 extends SlowPathEvent {
+
+        protected final Object o1;
+        protected final Object o2;
+        protected final Object o3;
+        protected final Object o4;
+
+        public SlowPathEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+            super(source, reason, frame);
+            this.o1 = o1;
+            this.o2 = o2;
+            this.o3 = o3;
+            this.o4 = o4;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return new Object[]{o1, o2, o3, o4};
+        }
+
+    }
+
+    static class SlowPathEvent5 extends SlowPathEvent {
+
+        protected final Object o1;
+        protected final Object o2;
+        protected final Object o3;
+        protected final Object o4;
+        protected final Object o5;
+
+        public SlowPathEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+            super(source, reason, frame);
+            this.o1 = o1;
+            this.o2 = o2;
+            this.o3 = o3;
+            this.o4 = o4;
+            this.o5 = o5;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return new Object[]{o1, o2, o3, o4, o5};
+        }
+
+    }
+
+    static class SlowPathEventN extends SlowPathEvent {
+
+        protected final Object[] args;
+
+        public SlowPathEventN(SpecializationNode source, String reason, Frame frame, Object... args) {
+            super(source, reason, frame);
+            this.args = args;
+        }
+
+        @Override
+        public final Object[] getValues() {
+            return args;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent0;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent1;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent2;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent3;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent4;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEvent5;
+import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEventN;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Internal implementation dependent base class for generated specialized nodes.
+ */
+@NodeInfo(cost = NodeCost.NONE)
+@SuppressWarnings("unused")
+public abstract class SpecializationNode extends Node {
+
+    @Child protected SpecializationNode next;
+
+    final int index;
+
+    public SpecializationNode() {
+        this(-1);
+    }
+
+    public SpecializationNode(int index) {
+        this.index = index;
+    }
+
+    @Override
+    public final NodeCost getCost() {
+        return NodeCost.NONE;
+    }
+
+    public void reset() {
+        SpecializationNode start = findStart();
+        SpecializationNode end = findEnd();
+        if (start != end) {
+            start.replace(end, "reset specialization");
+        }
+    }
+
+    public static Node updateRoot(Node node) {
+        updateRootImpl(((SpecializedNode) node).getSpecializationNode(), node);
+        return node;
+    }
+
+    private static void updateRootImpl(SpecializationNode start, Node node) {
+        NodeFieldAccessor[] fields = NodeClass.get(start).getFields();
+        for (int i = fields.length - 1; i >= 0; i--) {
+            NodeFieldAccessor f = fields[i];
+            if (f.getName().equals("root")) {
+                f.putObject(start, node);
+                break;
+            }
+        }
+        if (start.next != null) {
+            updateRootImpl(start.next, node);
+        }
+    }
+
+    protected final SpecializationNode polymorphicMerge(SpecializationNode newNode, SpecializationNode merged) {
+        if (merged == newNode && count() <= 2) {
+            return removeSame(new SlowPathEvent0(this, "merged polymorphic to monomorphic", null));
+        }
+        return merged;
+    }
+
+    public final NodeCost getNodeCost() {
+        switch (count()) {
+            case 0:
+            case 1:
+                return NodeCost.UNINITIALIZED;
+            case 2:
+                return NodeCost.MONOMORPHIC;
+            default:
+                return NodeCost.POLYMORPHIC;
+        }
+    }
+
+    protected abstract Node[] getSuppliedChildren();
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame) {
+        if (isIdentical(newNode, frame)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1) {
+        if (isIdentical(newNode, frame, o1)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, o1) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2) {
+        if (isIdentical(newNode, frame, o1, o2)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, o1, o2) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3) {
+        if (isIdentical(newNode, frame, o1, o2, o3)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, o1, o2, o3) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        if (isIdentical(newNode, frame, o1, o2, o3, o4)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, o1, o2, o3, o4) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        if (isIdentical(newNode, frame, o1, o2, o3, o4, o5)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, o1, o2, o3, o4, o5) : newNode;
+    }
+
+    protected SpecializationNode merge(SpecializationNode newNode, Frame frame, Object... args) {
+        if (isIdentical(newNode, frame, args)) {
+            return this;
+        }
+        return next != null ? next.merge(newNode, frame, args) : newNode;
+    }
+
+    protected boolean isSame(SpecializationNode other) {
+        return getClass() == other.getClass();
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        return isSame(newNode);
+    }
+
+    protected boolean isIdentical(SpecializationNode newNode, Frame frame, Object... args) {
+        return isSame(newNode);
+    }
+
+    protected final int countSame(SpecializationNode node) {
+        return findStart().countSameImpl(node);
+    }
+
+    private int countSameImpl(SpecializationNode node) {
+        if (next != null) {
+            return next.countSameImpl(node) + (isSame(node) ? 1 : 0);
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public final boolean equals(Object obj) {
+        if (obj instanceof SpecializationNode) {
+            return ((SpecializationNode) obj).isSame(this);
+        }
+        return super.equals(obj);
+    }
+
+    @Override
+    public final int hashCode() {
+        return index;
+    }
+
+    private int count() {
+        return next != null ? next.count() + 1 : 1;
+    }
+
+    private SpecializationNode findEnd() {
+        SpecializationNode node = this;
+        while (node.next != null) {
+            node = node.next;
+        }
+        return node;
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame) {
+        return removeThisImpl(reason).acceptAndExecute(frame);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        return removeThisImpl(reason).acceptAndExecute(frame, o1, o2, o3, o4, o5);
+    }
+
+    protected final Object removeThis(final CharSequence reason, Frame frame, Object... args) {
+        return removeThisImpl(reason).acceptAndExecute(frame, args);
+    }
+
+    private SpecializationNode removeThisImpl(final CharSequence reason) {
+        this.replace(this.next, reason);
+        return findEnd().findStart();
+    }
+
+    protected final SpecializationNode removeSame(final CharSequence reason) {
+        SpecializationNode start = SpecializationNode.this.findStart();
+        SpecializationNode current = start;
+        while (current != null) {
+            if (current.isSame(SpecializationNode.this)) {
+                NodeUtil.nonAtomicReplace(current, current.next, reason);
+                if (current == start) {
+                    start = start.next;
+                }
+            }
+            current = current.next;
+        }
+        return SpecializationNode.this.findEnd().findStart();
+    }
+
+    /** Find the topmost of the specialization chain. */
+    private SpecializationNode findStart() {
+        SpecializationNode node = this;
+        Node parent = this.getParent();
+        while (parent instanceof SpecializationNode) {
+            SpecializationNode parentCast = ((SpecializationNode) parent);
+            if (parentCast.next != node) {
+                break;
+            }
+            node = parentCast;
+            parent = node.getParent();
+        }
+        return node;
+    }
+
+    private Node findRoot() {
+        return findStart().getParent();
+    }
+
+    private SpecializedNode findSpecializedNode() {
+        return (SpecializedNode) findEnd().findStart().getParent();
+    }
+
+    private static SpecializationNode removeSameImpl(SpecializationNode toRemove, CharSequence reason) {
+        SpecializationNode start = toRemove.findStart();
+        SpecializationNode current = start;
+        while (current != null) {
+            if (current.isSame(toRemove)) {
+                NodeUtil.nonAtomicReplace(current, current.next, reason);
+                if (current == start) {
+                    start = start.next;
+                }
+            }
+            current = current.next;
+        }
+        return toRemove.findEnd().findStart();
+    }
+
+    public Object acceptAndExecute(Frame frame) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object o1) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object o1, Object o2) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object acceptAndExecute(Frame frame, Object... args) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createFallback() {
+        return null;
+    }
+
+    protected SpecializationNode createPolymorphic() {
+        return null;
+    }
+
+    protected SpecializationNode createNext(Frame frame) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object o1) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object o1, Object o2) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected SpecializationNode createNext(Frame frame, Object... args) {
+        throw new UnsupportedOperationException();
+    }
+
+    protected final Object uninitialized(Frame frame) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent0(this, "insert new specialization", frame));
+        if (newNode == null) {
+            return unsupported(frame);
+        }
+        return newNode.acceptAndExecute(frame);
+    }
+
+    protected final Object uninitialized(Frame frame, Object o1) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent1(this, "insert new specialization", frame, o1));
+        if (newNode == null) {
+            return unsupported(frame, o1);
+        }
+        return newNode.acceptAndExecute(frame, o1);
+    }
+
+    protected final Object uninitialized(Frame frame, Object o1, Object o2) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent2(this, "insert new specialization", frame, o1, o2));
+        if (newNode == null) {
+            return unsupported(frame, o1, o2);
+        }
+        return newNode.acceptAndExecute(frame, o1, o2);
+    }
+
+    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent3(this, "insert new specialization", frame, o1, o2, o3));
+        if (newNode == null) {
+            return unsupported(frame, o1, o2, o3);
+        }
+        return newNode.acceptAndExecute(frame, o1, o2, o3);
+    }
+
+    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent4(this, "insert new specialization", frame, o1, o2, o3, o4));
+        if (newNode == null) {
+            return unsupported(frame, o1, o2, o3, o4);
+        }
+        return newNode.acceptAndExecute(frame, o1, o2, o3, o4);
+    }
+
+    protected final Object uninitialized(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEvent5(this, "insert new specialization", frame, o1, o2, o3, o4, o5));
+        if (newNode == null) {
+            return unsupported(frame, o1, o2, o3, o4, o5);
+        }
+        return newNode.acceptAndExecute(frame, o1, o2, o3, o4, o5);
+    }
+
+    protected final Object uninitialized(Frame frame, Object... args) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        SpecializationNode newNode = atomic(new InsertionEventN(this, "insert new specialization", frame, args));
+        if (newNode == null) {
+            return unsupported(frame, args);
+        }
+        return newNode.acceptAndExecute(frame, args);
+    }
+
+    protected final Object remove(String reason, Frame frame) {
+        return atomic(new RemoveEvent0(this, reason, frame)).acceptAndExecute(frame);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object o1) {
+        return atomic(new RemoveEvent1(this, reason, frame, o1)).acceptAndExecute(frame, o1);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object o1, Object o2) {
+        return atomic(new RemoveEvent2(this, reason, frame, o1, o2)).acceptAndExecute(frame, o1, o2);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3) {
+        return atomic(new RemoveEvent3(this, reason, frame, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        return atomic(new RemoveEvent4(this, reason, frame, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        return atomic(new RemoveEvent5(this, reason, frame, o1, o2, o3, o4, o5)).acceptAndExecute(frame, o1, o2, o3, o4, o5);
+    }
+
+    protected final Object remove(String reason, Frame frame, Object... args) {
+        return atomic(new RemoveEventN(this, reason, frame, args)).acceptAndExecute(frame, args);
+    }
+
+    protected Object unsupported(Frame frame) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren());
+    }
+
+    protected Object unsupported(Frame frame, Object o1) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1);
+    }
+
+    protected Object unsupported(Frame frame, Object o1, Object o2) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2);
+    }
+
+    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3);
+    }
+
+    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4);
+    }
+
+    protected Object unsupported(Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), o1, o2, o3, o4, o5);
+    }
+
+    protected Object unsupported(Frame frame, Object... args) {
+        throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), args);
+    }
+
+    static SpecializationNode insertSorted(SpecializationNode start, final SpecializationNode generated, final CharSequence message, final SpecializationNode merged) {
+        if (merged == generated) {
+            // new node
+            if (start.count() == 2) {
+                SpecializationNode polymorphic = start.createPolymorphic();
+                /*
+                 * For nodes with all parameters evaluated in the execute method we do not need a
+                 * polymorphic node. the generated code returns null in createPolymorphic in this
+                 * case.
+                 */
+                if (polymorphic != null) {
+                    insertAt(start, polymorphic, "insert polymorphic");
+                }
+            }
+            SpecializationNode current = start;
+            while (current != null && current.index < generated.index) {
+                current = current.next;
+            }
+            return insertAt(current, generated, message);
+        } else {
+            // existing node
+            return start;
+        }
+    }
+
+    static <T> SpecializationNode insertAt(SpecializationNode node, SpecializationNode insertBefore, CharSequence reason) {
+        insertBefore.next = node;
+        // always guaranteed to be executed inside of an atomic block
+        return NodeUtil.nonAtomicReplace(node, insertBefore, reason);
+    }
+
+    @Override
+    public final String toString() {
+        Class<?> clazz = getClass();
+        StringBuilder b = new StringBuilder();
+        b.append(clazz.getSimpleName());
+
+        appendFields(b, clazz);
+        if (next != null) {
+            b.append("\n -> ").append(next.toString());
+        }
+        return b.toString();
+    }
+
+    private void appendFields(StringBuilder b, Class<?> clazz) {
+        Field[] fields = clazz.getDeclaredFields();
+        if (fields.length == 0) {
+            return;
+        }
+        b.append("(");
+        String sep = "";
+        for (Field field : fields) {
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            b.append(sep);
+            String name = field.getName();
+            if (name.equals("root")) {
+                continue;
+            }
+            b.append(field.getName());
+            b.append(" = ");
+            try {
+                field.setAccessible(true);
+                Object value = field.get(this);
+                if (value instanceof Object[]) {
+                    b.append(Arrays.toString((Object[]) field.get(this)));
+                } else {
+                    b.append(field.get(this));
+                }
+            } catch (IllegalArgumentException e) {
+                b.append(e.toString());
+            } catch (IllegalAccessException e) {
+                b.append(e.toString());
+            }
+            sep = ", ";
+        }
+        b.append(")");
+    }
+
+    protected static void check(Assumption assumption) throws InvalidAssumptionException {
+        if (assumption != null) {
+            assumption.check();
+        }
+    }
+
+    @ExplodeLoop
+    protected static void check(Assumption[] assumptions) throws InvalidAssumptionException {
+        if (assumptions != null) {
+            CompilerAsserts.compilationConstant(assumptions.length);
+            for (Assumption assumption : assumptions) {
+                check(assumption);
+            }
+        }
+    }
+
+    protected static boolean isValid(Assumption assumption) {
+        if (assumption != null) {
+            return assumption.isValid();
+        }
+        return true;
+    }
+
+    protected static boolean isValid(Assumption[] assumptions) {
+        if (assumptions != null) {
+            for (Assumption assumption : assumptions) {
+                if (!isValid(assumption)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private static final class InsertionEvent0 extends SlowPathEvent0 implements Callable<SpecializationNode> {
+
+        public InsertionEvent0(SpecializationNode source, String reason, Frame frame) {
+            super(source, reason, frame);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame));
+            }
+        }
+
+    }
+
+    private static final class InsertionEvent1 extends SlowPathEvent1 implements Callable<SpecializationNode> {
+
+        public InsertionEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
+            super(source, reason, frame, o1);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, o1);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, o1));
+            }
+        }
+
+    }
+
+    private static final class InsertionEvent2 extends SlowPathEvent2 implements Callable<SpecializationNode> {
+
+        public InsertionEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
+            super(source, reason, frame, o1, o2);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, o1, o2);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, o1, o2));
+            }
+        }
+
+    }
+
+    private static final class InsertionEvent3 extends SlowPathEvent3 implements Callable<SpecializationNode> {
+
+        public InsertionEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
+            super(source, reason, frame, o1, o2, o3);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, o1, o2, o3);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3));
+            }
+        }
+
+    }
+
+    private static final class InsertionEvent4 extends SlowPathEvent4 implements Callable<SpecializationNode> {
+
+        public InsertionEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+            super(source, reason, frame, o1, o2, o3, o4);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, o1, o2, o3, o4);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3, o4));
+            }
+        }
+
+    }
+
+    private static final class InsertionEvent5 extends SlowPathEvent5 implements Callable<SpecializationNode> {
+
+        public InsertionEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+            super(source, reason, frame, o1, o2, o3, o4, o5);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, o1, o2, o3, o4, o5);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, o1, o2, o3, o4, o5));
+            }
+        }
+
+    }
+
+    private static final class InsertionEventN extends SlowPathEventN implements Callable<SpecializationNode> {
+
+        public InsertionEventN(SpecializationNode source, String reason, Frame frame, Object[] args) {
+            super(source, reason, frame, args);
+        }
+
+        public SpecializationNode call() throws Exception {
+            SpecializationNode next = source.createNext(frame, args);
+            if (next == null) {
+                next = source.createFallback();
+            }
+            if (next == null) {
+                return null;
+            }
+            SpecializationNode start = source.findStart();
+            if (start.index == Integer.MAX_VALUE) {
+                return insertAt(start, next, this);
+            } else {
+                return insertSorted(start, next, this, start.merge(next, frame, args));
+            }
+        }
+    }
+
+    private static final class RemoveEvent0 extends SlowPathEvent0 implements Callable<SpecializationNode> {
+
+        public RemoveEvent0(SpecializationNode source, String reason, Frame frame) {
+            super(source, reason, frame);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEvent1 extends SlowPathEvent1 implements Callable<SpecializationNode> {
+
+        public RemoveEvent1(SpecializationNode source, String reason, Frame frame, Object o1) {
+            super(source, reason, frame, o1);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEvent2 extends SlowPathEvent2 implements Callable<SpecializationNode> {
+
+        public RemoveEvent2(SpecializationNode source, String reason, Frame frame, Object o1, Object o2) {
+            super(source, reason, frame, o1, o2);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEvent3 extends SlowPathEvent3 implements Callable<SpecializationNode> {
+
+        public RemoveEvent3(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3) {
+            super(source, reason, frame, o1, o2, o3);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEvent4 extends SlowPathEvent4 implements Callable<SpecializationNode> {
+
+        public RemoveEvent4(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4) {
+            super(source, reason, frame, o1, o2, o3, o4);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEvent5 extends SlowPathEvent5 implements Callable<SpecializationNode> {
+
+        public RemoveEvent5(SpecializationNode source, String reason, Frame frame, Object o1, Object o2, Object o3, Object o4, Object o5) {
+            super(source, reason, frame, o1, o2, o3, o4, o5);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+
+    }
+
+    private static final class RemoveEventN extends SlowPathEventN implements Callable<SpecializationNode> {
+
+        public RemoveEventN(SpecializationNode source, String reason, Frame frame, Object[] args) {
+            super(source, reason, frame, args);
+        }
+
+        public SpecializationNode call() throws Exception {
+            return source.removeSame(this);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializedNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.internal;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Implemented by DSL generated operation classes. This is internal implementation dependent API.
+ */
+public interface SpecializedNode extends NodeInterface {
+
+    /** Returns the root {@link SpecializationNode} of the DSL operation. */
+    SpecializationNode getSpecializationNode();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/META-INF/services/com.oracle.truffle.api.impl.SymbolInvoker	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+com.oracle.truffle.api.interop.impl.SymbolInvokerImpl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Execute.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class Execute extends KnownMessage {
+    public static final int HASH1 = 423430;
+    public static final int HASH2 = 423429;
+
+    private final int arity;
+    private final boolean invoke;
+
+    public static Execute create(boolean invoke, int arity) {
+        return new Execute(invoke, arity);
+    }
+
+    private Execute(boolean invoke, int arity) {
+        this.invoke = invoke;
+        this.arity = arity;
+    }
+
+    public int getArity() {
+        return arity;
+    }
+
+    @Override
+    public boolean equals(Object message) {
+        if (!(message instanceof Execute)) {
+            return false;
+        }
+        Execute m1 = this;
+        Execute m2 = (Execute) message;
+        return m1.invoke == m2.invoke;
+    }
+
+    @Override
+    public int hashCode() {
+        return invoke ? HASH1 : HASH2;
+    }
+
+    @Override
+    public String toString() {
+        return invoke ? "msgInvoke" : "msgExecute";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccess.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.impl.ReadOnlyArrayList;
+import com.oracle.truffle.api.nodes.Node;
+import java.util.List;
+
+/**
+ * Encapsulates types of access to {@link TruffleObject}. If you want to expose your own objects to
+ * foreign language implementations, you need to implement {@link TruffleObject} and its
+ * {@link TruffleObject#getForeignAccess()} method. To create instance of <code>ForeignAccess</code>
+ * , use one of the factory methods available in this class.
+ */
+public final class ForeignAccess {
+    private final Factory factory;
+
+    private ForeignAccess(Factory faf) {
+        this.factory = faf;
+    }
+
+    /**
+     * Creates new instance of {@link ForeignAccess} that delegates to provided factory.
+     *
+     * @param baseClass the super class of all {@link TruffleObject}s handled by this factory (if
+     *            <code>null</code> than the second interface also needs to implement
+     *            {@link Factory})
+     * @param factory the factory that handles access requests to {@link Message}s known as of
+     *            version 1.0
+     * @return new instance wrapping <code>factory</code>
+     */
+    public static ForeignAccess create(final Class<? extends TruffleObject> baseClass, final Factory10 factory) {
+        if (baseClass == null) {
+            Factory f = (Factory) factory;
+            assert f != null;
+        }
+        class DelegatingFactory implements Factory {
+            @Override
+            public boolean canHandle(TruffleObject obj) {
+                if (baseClass == null) {
+                    return ((Factory) factory).canHandle(obj);
+                }
+                return baseClass.isInstance(obj);
+            }
+
+            @Override
+            public CallTarget accessMessage(Message msg) {
+                if (msg instanceof KnownMessage) {
+                    switch (msg.hashCode()) {
+                        case Execute.HASH1:
+                            return factory.accessInvoke(((Execute) msg).getArity());
+                        case Execute.HASH2:
+                            return factory.accessExecute(((Execute) msg).getArity());
+                        case GetSize.HASH:
+                            return factory.accessGetSize();
+                        case HasSize.HASH:
+                            return factory.accessHasSize();
+                        case IsBoxed.HASH:
+                            return factory.accessIsBoxed();
+                        case IsExecutable.HASH:
+                            return factory.accessIsExecutable();
+                        case IsNull.HASH:
+                            return factory.accessIsNull();
+                        case Read.HASH:
+                            return factory.accessRead();
+                        case Unbox.HASH:
+                            return factory.accessUnbox();
+                        case Write.HASH:
+                            return factory.accessWrite();
+                    }
+                }
+                return factory.accessMessage(msg);
+            }
+        }
+        return new ForeignAccess(new DelegatingFactory());
+    }
+
+    /**
+     * Creates new instance of {@link ForeignAccess} that delegates to provided factory.
+     *
+     * @param factory the factory that handles various access requests {@link Message}s.
+     * @return new instance wrapping <code>factory</code>
+     */
+    public static ForeignAccess create(Factory factory) {
+        return new ForeignAccess(factory);
+    }
+
+    /**
+     * Executes {@link Message#createNode() foreign node}.
+     * 
+     * @param foreignNode the createNode created by {@link Message#createNode()}
+     * @param frame the call frame
+     * @param receiver foreign object to receive the message passed to {@link Message#createNode()}
+     *            method
+     * @param arguments parameters for the receiver
+     * @return return value, if any
+     * @throws ClassCastException if the createNode has not been created by
+     *             {@link Message#createNode()} method.
+     */
+    public static Object execute(Node foreignNode, VirtualFrame frame, TruffleObject receiver, Object... arguments) {
+        ForeignObjectAccessHeadNode fn = (ForeignObjectAccessHeadNode) foreignNode;
+        return fn.executeForeign(frame, receiver, arguments);
+    }
+
+    /**
+     * Read only access to foreign call arguments inside of a frame.
+     *
+     * @param frame the frame that was called via
+     *            {@link #execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) }
+     * @return read-only list of parameters passed to the frame
+     */
+    public static List<Object> getArguments(Frame frame) {
+        final Object[] arr = frame.getArguments();
+        return ReadOnlyArrayList.asList(arr, 1, arr.length);
+    }
+
+    /**
+     * The foreign receiver in the frame.
+     *
+     * @param frame the frame that was called via
+     *            {@link #execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object...) }
+     * @return the receiver used when invoking the frame
+     */
+    public static TruffleObject getReceiver(Frame frame) {
+        return (TruffleObject) frame.getArguments()[ForeignAccessArguments.RECEIVER_INDEX];
+    }
+
+    CallTarget access(Message message) {
+        return factory.accessMessage(message);
+    }
+
+    boolean canHandle(TruffleObject receiver) {
+        return factory.canHandle(receiver);
+    }
+
+    /**
+     * Interface of a factory that produces AST snippets that can access a foreign
+     * {@code TruffleObject}. A Truffle language implementation accesses a {@code TruffleObject} via
+     * a {@code Message}. The {@code TruffleObject} instance provides a {@link ForeignAccess}
+     * instance (built via {@link #create(com.oracle.truffle.api.interop.ForeignAccess.Factory)})
+     * that provides an AST snippet for a given {@link Message}. Rather than using this generic
+     * {@code Factory}, consider implementing {@link Factory10} interface that captures the set of
+     * messages each language should implement as of Truffle version 1.0.
+     */
+    public interface Factory {
+
+        /**
+         * * Checks whether provided {@link TruffleObject} can be accessed using AST snippets
+         * produced by this {@link Factory}.
+         *
+         * @param obj the object to check
+         * @return true, if the object can be processed
+         */
+        boolean canHandle(TruffleObject obj);
+
+        /**
+         * Provides an AST snippet to access a {@code TruffleObject}.
+         *
+         * @param tree the {@code Message} that represents the access to a {@code TruffleObject}.
+         * @return the AST snippet for accessing the {@code TruffleObject}, wrapped as a
+         *         {@code CallTarget}.
+         */
+        CallTarget accessMessage(Message tree);
+    }
+
+    /**
+     * Specialized {@link Factory factory} that handles {@link Message messages} known as of release
+     * 1.0 of Truffle API.
+     *
+     */
+    public interface Factory10 {
+        /**
+         * Handles {@link Message#IS_NULL} message.
+         *
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessIsNull();
+
+        /**
+         * Handles {@link Message#IS_EXECUTABLE} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessIsExecutable();
+
+        /**
+         * Handles {@link Message#IS_BOXED} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessIsBoxed();
+
+        /**
+         * Handles {@link Message#HAS_SIZE} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessHasSize();
+
+        /**
+         * Handles {@link Message#GET_SIZE} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessGetSize();
+
+        /**
+         * Handles {@link Message#UNBOX} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessUnbox();
+
+        /**
+         * Handles {@link Message#READ} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessRead();
+
+        /**
+         * Handles {@link Message#WRITE} message.
+         * 
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessWrite();
+
+        /**
+         * Handles {@link Message#createExecute(int)} messages.
+         * 
+         * @param argumentsLength number of parameters the messages has been created for
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessExecute(int argumentsLength);
+
+        /**
+         * Handles {@link Message#createInvoke(int)} messages.
+         * 
+         * @param argumentsLength number of parameters the messages has been created for
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessInvoke(int argumentsLength);
+
+        /**
+         * Handles request for access to a message not known in version 1.0.
+         *
+         * @param unknown the message
+         * @return call target to handle the message or <code>null</code> if this message is not
+         *         supported
+         */
+        CallTarget accessMessage(Message unknown);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignAccessArguments.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class ForeignAccessArguments {
+    static final Object[] EMPTY_ARGUMENTS_ARRAY = new Object[0];
+    static final int RECEIVER_INDEX = 0;
+    static final int RUNTIME_ARGUMENT_COUNT = 1;
+
+    static Object[] create(Object receiver, Object... arguments) {
+        if (arguments.length == 0) {
+            return new Object[]{receiver};
+        }
+        Object[] objectArguments = new Object[RUNTIME_ARGUMENT_COUNT + arguments.length];
+        objectArguments[RECEIVER_INDEX] = receiver;
+        arraycopy(arguments, 0, objectArguments, RUNTIME_ARGUMENT_COUNT, arguments.length);
+        return objectArguments;
+    }
+
+    private static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
+        for (int i = 0; i < length; i++) {
+            dest[destPos + i] = src[srcPos + i];
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ForeignObjectAccessHeadNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.truffle.api.interop;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.Node;
+
+final class ForeignObjectAccessHeadNode extends Node {
+
+    @Child private ObjectAccessNode first;
+    private final Message accessTree;
+
+    protected ForeignObjectAccessHeadNode(Message tree) {
+        this.accessTree = tree;
+        this.first = new UnresolvedObjectAccessNode();
+        adoptChildren();
+    }
+
+    protected Message getAccessTree() {
+        return accessTree;
+    }
+
+    protected ObjectAccessNode getFirst() {
+        return first;
+    }
+
+    public Object executeForeign(VirtualFrame frame, TruffleObject receiver, Object... arguments) {
+        return first.executeWith(frame, receiver, arguments);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/GetSize.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class GetSize extends UnaryMessage {
+    public static final int HASH = 423432;
+
+    static Message INSTANCE = new GetSize();
+
+    @Override
+    public String toString() {
+        return "msgGetSize";
+    }
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/HasSize.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class HasSize extends UnaryMessage {
+    public static final int HASH = 423433;
+    static Message INSTANCE = new HasSize();
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgHasSize";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsBoxed.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class IsBoxed extends UnaryMessage {
+    public static final int HASH = 423434;
+    static Message INSTANCE = new IsBoxed();
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgIsBoxed";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsExecutable.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class IsExecutable extends UnaryMessage {
+    public static final int HASH = 423435;
+    static Message INSTANCE = new IsExecutable();
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgIsExecutable";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/IsNull.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class IsNull extends UnaryMessage {
+    public static final int HASH = 423436;
+    static Message INSTANCE = new IsNull();
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgIsNull";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/KnownMessage.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+/**
+ * Marker class.
+ */
+abstract class KnownMessage extends Message {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Message.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.interop.ForeignAccess.Factory;
+
+/**
+ * Inter-operability is based on sending messages. Standard messages are defined as as constants
+ * like {@link #IS_NULL} or factory methods in this class, but one can always define their own,
+ * specialized messages.
+ */
+public abstract class Message {
+    /**
+     * Message to read a field.
+     */
+    public static final Message READ = Read.INSTANCE;
+
+    /**
+     * Converts {@link TruffleObject truffle value} to Java primitive type. Primitive types are
+     * subclasses of {@link Number}, {@link Boolean}, {@link Character} and {@link String}. Related
+     * to {@link #IS_BOXED} message.
+     */
+    public static final Message UNBOX = Unbox.INSTANCE;
+
+    /**
+     * Message to write a field.
+     */
+    public static Message WRITE = Write.INSTANCE;
+
+    /**
+     * Creates an execute message. All messages created by this method are
+     * {@link Object#equals(java.lang.Object) equal} to each other regardless of the value of
+     * <code>argumentsLength</code>.
+     *
+     * @param argumentsLength number of parameters to pass to the target
+     * @return execute message
+     */
+    public static Message createExecute(int argumentsLength) {
+        return Execute.create(false, argumentsLength);
+    }
+
+    /**
+     * Message to check for executability.
+     * <p>
+     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
+     * this message should yield value of {@link Boolean}.
+     */
+    public static final Message IS_EXECUTABLE = IsExecutable.INSTANCE;
+
+    /**
+     * Creates an execute message. All messages created by this method are
+     * {@link Object#equals(java.lang.Object) equal} to each other regardless of the value of
+     * <code>argumentsLength</code>. The expected behavior of this message is to perform
+     * {@link #READ} first and on the result invoke {@link #createExecute(int)}.
+     *
+     * @param argumentsLength number of parameters to pass to the target
+     * @return read & execute message
+     */
+    public static Message createInvoke(int argumentsLength) {
+        return Execute.create(true, argumentsLength);
+    }
+
+    /**
+     * Check for <code>null</code> message. The Truffle languages are suggested to have their own
+     * object representing <code>null</code> like values in their languages. For purposes of
+     * inter-operability it is essential to canonicalize such values from time to time - sending
+     * this message is a way to recognize such <code>null</code> representing values.
+     * <p>
+     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
+     * this message should yield value of {@link Boolean}.
+     */
+    public static final Message IS_NULL = IsNull.INSTANCE;
+
+    /**
+     * Message to check for having a size.
+     * <p>
+     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
+     * this message should yield value of {@link Boolean}.
+     */
+    public static final Message HAS_SIZE = HasSize.INSTANCE;
+
+    /**
+     * Getter of the size. If {@link #HAS_SIZE supported}, this message allows to obtain a size (of
+     * an array).
+     * <p>
+     * Calling {@link Factory#access(com.oracle.truffle.api.interop.Message) the target} created for
+     * this message should yield value of {@link Integer}.
+     */
+    public static final Message GET_SIZE = GetSize.INSTANCE;
+
+    /**
+     * Check for value being boxed. Can you value be converted to one of the basic Java types? Many
+     * languages have a special representation for types like number, string, etc. To ensure
+     * inter-operability, these types should support unboxing - if they do, they should handle this
+     * message.
+     * <p>
+     * Calling {@link Factory#accessMessage(com.oracle.truffle.api.interop.Message) the target}
+     * created for this message should yield value of {@link Boolean}.
+     */
+    public static final Message IS_BOXED = IsBoxed.INSTANCE;
+
+    /**
+     * Compares types of two messages. Messages are encouraged to implement this method. All
+     * standard ones ({@link #IS_NULL}, {@link #READ}, etc.) do so. Messages obtained via the same
+     * {@link #createExecute(int) method} are equal, messages obtained by different methods or
+     * fields are not.
+     *
+     * @param message the object to compare to
+     * @return true, if the structure of the message is that same as of <code>this</code> one.
+     */
+    @Override
+    public abstract boolean equals(Object message);
+
+    /**
+     * When re-implementing {@link #equals(java.lang.Object)}, it is generally recommended to also
+     * implement <code>hashCode()</code>.
+     * 
+     * @return hash code
+     */
+    @Override
+    public abstract int hashCode();
+
+    /**
+     * Creates an AST node for this message. The node can be inserted into AST of your language and
+     * will handle communication with the foreign language.
+     *
+     * @return node to be inserted into your AST and passed back to
+     *         {@link ForeignAccess#execute(com.oracle.truffle.api.nodes.Node, com.oracle.truffle.api.frame.VirtualFrame, com.oracle.truffle.api.interop.TruffleObject, java.lang.Object[])}
+     *         method.
+     */
+    public final Node createNode() {
+        return new ForeignObjectAccessHeadNode(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/ObjectAccessNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+abstract class ObjectAccessNode extends Node {
+
+    public abstract Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments);
+
+}
+
+class UnresolvedObjectAccessNode extends ObjectAccessNode {
+
+    private static final int CACHE_SIZE = 8;
+    private int cacheLength = 1;
+
+    @Override
+    public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        ForeignObjectAccessHeadNode nthParent = (ForeignObjectAccessHeadNode) NodeUtil.getNthParent(this, cacheLength);
+        ObjectAccessNode first = nthParent.getFirst();
+        if (cacheLength < CACHE_SIZE) {
+            cacheLength++;
+            CachedObjectAccessNode createCachedAccess = createCachedAccess(receiver, nthParent.getAccessTree(), first);
+            return first.replace(createCachedAccess).executeWith(frame, receiver, arguments);
+        } else {
+            return first.replace(createGenericAccess(nthParent.getAccessTree())).executeWith(frame, receiver, arguments);
+        }
+    }
+
+    private static CachedObjectAccessNode createCachedAccess(TruffleObject receiver, Message accessTree, ObjectAccessNode next) {
+        ForeignAccess fa = receiver.getForeignAccess();
+        final CallTarget ct = fa.access(accessTree);
+        if (ct == null) {
+            throw new IllegalArgumentException("Message " + accessTree + " not recognized by " + fa);
+        }
+        return new CachedObjectAccessNode(Truffle.getRuntime().createDirectCallNode(ct), next, fa);
+    }
+
+    private static GenericObjectAccessNode createGenericAccess(Message access) {
+        return new GenericObjectAccessNode(access);
+    }
+}
+
+class GenericObjectAccessNode extends ObjectAccessNode {
+
+    private final Message access;
+    @Child private IndirectCallNode indirectCallNode;
+
+    public GenericObjectAccessNode(Message access) {
+        this.access = access;
+        indirectCallNode = Truffle.getRuntime().createIndirectCallNode();
+    }
+
+    public GenericObjectAccessNode(GenericObjectAccessNode prev) {
+        this(prev.access);
+    }
+
+    @Override
+    public Object executeWith(VirtualFrame frame, TruffleObject truffleObject, Object[] arguments) {
+        final ForeignAccess fa = truffleObject.getForeignAccess();
+        final CallTarget ct = fa.access(access);
+        if (ct == null) {
+            throw new IllegalStateException("Message " + access + " not recognized by " + fa);
+        }
+        return indirectCallNode.call(frame, ct, ForeignAccessArguments.create(truffleObject, arguments));
+    }
+}
+
+class CachedObjectAccessNode extends ObjectAccessNode {
+    @Child private DirectCallNode callTarget;
+    @Child private ObjectAccessNode next;
+
+    private final ForeignAccess languageCheck;
+
+    protected CachedObjectAccessNode(DirectCallNode callTarget, ObjectAccessNode next, ForeignAccess languageCheck) {
+        this.callTarget = callTarget;
+        this.next = next;
+        this.languageCheck = languageCheck;
+        this.callTarget.forceInlining();
+    }
+
+    protected CachedObjectAccessNode(CachedObjectAccessNode prev) {
+        this(prev.callTarget, prev.next, prev.languageCheck);
+    }
+
+    @Override
+    public Object executeWith(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
+        return doAccess(frame, receiver, arguments);
+    }
+
+    private Object doAccess(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
+        if (languageCheck.canHandle(receiver)) {
+            return callTarget.call(frame, ForeignAccessArguments.create(receiver, arguments));
+        } else {
+            return doNext(frame, receiver, arguments);
+        }
+    }
+
+    private Object doNext(VirtualFrame frame, TruffleObject receiver, Object[] arguments) {
+        return next.executeWith(frame, receiver, arguments);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Read.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class Read extends KnownMessage {
+    public static final int HASH = 423438;
+    static Message INSTANCE = new Read();
+
+    private Read() {
+    }
+
+    @Override
+    public boolean equals(Object message) {
+        return message instanceof Read;
+    }
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgRead";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/TruffleObject.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+/**
+ * Interface for any entity of a Truffle guest language implementations that can be shared across
+ * other language implementations.
+ */
+public interface TruffleObject {
+    /**
+     * Provides the {@code ForeignAccessFactory} instance for this {@code TruffleObject} instance.
+     *
+     * @return the {@code ForeignAccessFactory} instance for this {@code TruffleObject} instance.
+     */
+    ForeignAccess getForeignAccess();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/UnaryMessage.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+abstract class UnaryMessage extends KnownMessage {
+    protected UnaryMessage() {
+    }
+
+    @Override
+    public boolean equals(Object message) {
+        if (message == null) {
+            return false;
+        }
+        return this.getClass() == message.getClass();
+    }
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract String toString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Unbox.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class Unbox extends UnaryMessage {
+    public static final int HASH = 423437;
+    static Message INSTANCE = new Unbox();
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgUnbox";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/Write.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop;
+
+final class Write extends KnownMessage {
+    public static final int HASH = 423431;
+
+    static Message INSTANCE = new Write();
+
+    @Override
+    public boolean equals(Object message) {
+        return message instanceof Write;
+    }
+
+    @Override
+    public int hashCode() {
+        return HASH;
+    }
+
+    @Override
+    public String toString() {
+        return "msgWrite";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/ReadOnlyArrayList.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop.impl;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+public final class ReadOnlyArrayList<T> implements List<T> {
+    private final T[] arr;
+    private final int first;
+    private final int last;
+
+    private ReadOnlyArrayList(T[] arr, int first, int last) {
+        this.arr = arr;
+        this.first = first;
+        this.last = last;
+    }
+
+    public static <T> List<T> asList(T[] arr, int first, int last) {
+        return new ReadOnlyArrayList<>(arr, first, last);
+    }
+
+    @Override
+    public int size() {
+        return last - first;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return first == last;
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        for (int i = first; i < last; i++) {
+            if (o == arr[i] || (o != null && o.equals(arr[i]))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+        return new LI(first);
+    }
+
+    @Override
+    public Object[] toArray() {
+        return toArray(new Object[size()]);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <A> A[] toArray(A[] b) {
+        A[] a;
+        if (b.length < size()) {
+            a = (A[]) Array.newInstance(b.getClass().getComponentType(), size());
+        } else {
+            a = b;
+        }
+        for (int i = 0, at = first; at < last; i++, at++) {
+            a[i] = (A) arr[at];
+        }
+        return a;
+    }
+
+    @Override
+    public boolean add(Object e) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        for (Object obj : c) {
+            if (!contains(obj)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends T> c) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean addAll(int index, Collection<? extends T> c) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public T get(int index) {
+        int at = first + index;
+        T ret = arr[at];
+        if (at >= last) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        return ret;
+    }
+
+    @Override
+    public T set(int index, Object element) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void add(int index, Object element) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public T remove(int index) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int indexOf(Object o) {
+        for (int i = first; i < last; i++) {
+            if (arr[i] == null) {
+                if (o == null) {
+                    return i - first;
+                }
+            } else {
+                if (arr[i].equals(o)) {
+                    return i - first;
+                }
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+        for (int i = last - 1; i >= first; i--) {
+            if (arr[i] == null) {
+                if (o == null) {
+                    return i - first;
+                }
+            } else {
+                if (arr[i].equals(o)) {
+                    return i - first;
+                }
+            }
+        }
+        return -1;
+    }
+
+    @Override
+    public ListIterator<T> listIterator() {
+        return new LI(first);
+    }
+
+    @Override
+    public ListIterator<T> listIterator(int index) {
+        return new LI(first + index);
+    }
+
+    @Override
+    public List<T> subList(int fromIndex, int toIndex) {
+        return new ReadOnlyArrayList<>(arr, first + fromIndex, first + toIndex);
+    }
+
+    private final class LI implements ListIterator<T>, Iterator<T> {
+        private int index;
+
+        public LI(int index) {
+            this.index = index;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return index < last;
+        }
+
+        @Override
+        public T next() {
+            if (index >= last) {
+                throw new NoSuchElementException();
+            }
+            return arr[index++];
+        }
+
+        @Override
+        public boolean hasPrevious() {
+            return index > first;
+        }
+
+        @Override
+        public T previous() {
+            if (first == index) {
+                throw new NoSuchElementException();
+            }
+            return arr[--index];
+        }
+
+        @Override
+        public int nextIndex() {
+            return index - first;
+        }
+
+        @Override
+        public int previousIndex() {
+            return index - 1 - first;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void set(Object e) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void add(Object e) {
+            throw new UnsupportedOperationException();
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/impl/SymbolInvokerImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.interop.impl;
+
+import java.io.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.*;
+
+public final class SymbolInvokerImpl extends SymbolInvoker {
+    static final FrameDescriptor UNUSED_FRAMEDESCRIPTOR = new FrameDescriptor();
+
+    @Override
+    protected Object invoke(Object symbol, Object... arr) throws IOException {
+        if (symbol instanceof String) {
+            return symbol;
+        }
+        if (symbol instanceof Number) {
+            return symbol;
+        }
+        if (symbol instanceof Boolean) {
+            return symbol;
+        }
+        Node executeMain = Message.createExecute(arr.length).createNode();
+        CallTarget callTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(executeMain, (TruffleObject) symbol, arr));
+        VirtualFrame frame = Truffle.getRuntime().createVirtualFrame(arr, UNUSED_FRAMEDESCRIPTOR);
+        Object ret = callTarget.call(frame);
+        if (ret instanceof TruffleObject) {
+            TruffleObject tret = (TruffleObject) ret;
+            Object isBoxedResult;
+            try {
+                Node isBoxed = Message.IS_BOXED.createNode();
+                CallTarget isBoxedTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isBoxed, tret));
+                isBoxedResult = isBoxedTarget.call(frame);
+            } catch (IllegalArgumentException ex) {
+                isBoxedResult = false;
+            }
+            if (Boolean.TRUE.equals(isBoxedResult)) {
+                Node unbox = Message.UNBOX.createNode();
+                CallTarget unboxTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(unbox, tret));
+                Object unboxResult = unboxTarget.call(frame);
+                return unboxResult;
+            } else {
+                try {
+                    Node isNull = Message.IS_NULL.createNode();
+                    CallTarget isNullTarget = Truffle.getRuntime().createCallTarget(new TemporaryRoot(isNull, tret));
+                    Object isNullResult = isNullTarget.call(frame);
+                    if (Boolean.TRUE.equals(isNullResult)) {
+                        return null;
+                    }
+                } catch (IllegalArgumentException ex) {
+                    // fallthrough
+                }
+            }
+        }
+        return ret;
+    }
+
+    private static class TemporaryRoot extends RootNode {
+        @Child private Node foreignAccess;
+        private final TruffleObject function;
+        private final Object[] args;
+
+        public TemporaryRoot(Node foreignAccess, TruffleObject function, Object... args) {
+            this.foreignAccess = foreignAccess;
+            this.function = function;
+            this.args = args;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return ForeignAccess.execute(foreignAccess, frame, function, args);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/package-info.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This package provides inter-operability between different
+ * {@link com.oracle.truffle.api.TruffleLanguage Truffle languages}.
+ * <p>
+ * Languages can exchange primitive Java type wrapper objects (e.g., {@link java.lang.Integer},
+ * {@link java.lang.Double}, {@link java.lang.String}, etc) as well as any type
+ * implementing {@link com.oracle.truffle.api.interop.TruffleObject}. Foreign objects are
+ * precisely those implementing {@link com.oracle.truffle.api.interop.TruffleObject}.
+ * <p>
+ * To use a {@link com.oracle.truffle.api.interop.TruffleObject} from a different language,
+ * you need to ask the language to build appropriate AST for a given
+ * {@link com.oracle.truffle.api.interop.Message} with
+ * {@link com.oracle.truffle.api.interop.Message#createNode}. The message can then
+ * be executed with {@link com.oracle.truffle.api.interop.ForeignAccess#execute}.
+ */
+package com.oracle.truffle.api.interop;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BaseLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface BaseLocation {
+    /**
+     * Get object value as object at this location in store.
+     *
+     * @param shape the current shape of the object, which must contain this location
+     */
+    Object get(DynamicObject store, Shape shape);
+
+    /**
+     * Get object value as object at this location in store. For internal use only and subject to
+     * change, use {@link #get(DynamicObject, Shape)} instead.
+     *
+     * @param condition the result of a shape check or {@code false}
+     * @see #get(DynamicObject, Shape)
+     */
+    Object get(DynamicObject store, boolean condition);
+
+    /**
+     * Set object value at this location in store.
+     *
+     * @throws IncompatibleLocationException for storage type invalidations
+     * @throws FinalLocationException for effectively final fields
+     */
+    void set(DynamicObject store, Object value) throws IncompatibleLocationException, FinalLocationException;
+
+    /**
+     * Set object value at this location in store.
+     *
+     * @param shape the current shape of the storage object
+     * @throws IncompatibleLocationException for storage type invalidations
+     * @throws FinalLocationException for effectively final fields
+     */
+    void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException;
+
+    /**
+     * Set object value at this location in store and update shape.
+     *
+     * @param oldShape the shape before the transition
+     * @param newShape new shape after the transition
+     * @throws IncompatibleLocationException if value is of non-assignable type
+     */
+    void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/BooleanLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface BooleanLocation extends TypedLocation {
+    /**
+     * @see #get(DynamicObject, Shape)
+     */
+    boolean getBoolean(DynamicObject store, Shape shape);
+
+    /**
+     * @see #get(DynamicObject, boolean)
+     */
+    boolean getBoolean(DynamicObject store, boolean condition);
+
+    /**
+     * @see #set(DynamicObject, Object)
+     */
+    void setBoolean(DynamicObject store, boolean value) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape)
+     */
+    void setBoolean(DynamicObject store, boolean value, Shape shape) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape, Shape)
+     */
+    void setBoolean(DynamicObject store, boolean value, Shape oldShape, Shape newShape);
+
+    Class<Boolean> getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DebugCounter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+public final class DebugCounter {
+    private static final ArrayList<DebugCounter> allCounters = new ArrayList<>();
+
+    private final String name;
+    private final AtomicLong value;
+
+    private DebugCounter(String name) {
+        this.name = name;
+        this.value = new AtomicLong();
+        allCounters.add(this);
+    }
+
+    public static DebugCounter create(String name) {
+        return new DebugCounter(name);
+    }
+
+    public long get() {
+        return value.get();
+    }
+
+    public void inc() {
+        value.incrementAndGet();
+    }
+
+    @Override
+    public String toString() {
+        return name + ": " + value;
+    }
+
+    public static void dumpCounters() {
+        dumpCounters(System.out);
+    }
+
+    public static void dumpCounters(PrintStream out) {
+        for (DebugCounter counter : allCounters) {
+            out.println(counter);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DoubleLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface DoubleLocation extends TypedLocation {
+    /**
+     * @see #get(DynamicObject, Shape)
+     */
+    double getDouble(DynamicObject store, Shape shape);
+
+    /**
+     * @see #get(DynamicObject, boolean)
+     */
+    double getDouble(DynamicObject store, boolean condition);
+
+    /**
+     * @see #set(DynamicObject, Object)
+     */
+    void setDouble(DynamicObject store, double value) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape)
+     */
+    void setDouble(DynamicObject store, double value, Shape shape) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape, Shape)
+     */
+    void setDouble(DynamicObject store, double value, Shape oldShape, Shape newShape);
+
+    Class<Double> getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObject.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.interop.*;
+
+public abstract class DynamicObject implements TypedObject, TruffleObject {
+    /**
+     * Get the object's current shape.
+     */
+    public abstract Shape getShape();
+
+    /**
+     * Get property value.
+     *
+     * @param key property identifier
+     * @param defaultValue return value if property is not found
+     * @return property value or defaultValue if object has no such property
+     */
+    public abstract Object get(Object key, Object defaultValue);
+
+    /**
+     * Set value of existing property.
+     *
+     * @param key property identifier
+     * @param value value to be set
+     * @return {@code true} if successful or {@code false} if property not found
+     */
+    public abstract boolean set(Object key, Object value);
+
+    /**
+     * Returns {@code true} if this object contains a property with the given key.
+     */
+    public final boolean containsKey(Object key) {
+        return getShape().getProperty(key) != null;
+    }
+
+    /**
+     * Define new property or redefine existing property.
+     *
+     * @param key property identifier
+     * @param value value to be set
+     */
+    public final void define(Object key, Object value) {
+        define(key, value, 0);
+    }
+
+    /**
+     * Define new property or redefine existing property.
+     *
+     * @param key property identifier
+     * @param value value to be set
+     * @param flags flags to be set
+     */
+    public abstract void define(Object key, Object value, int flags);
+
+    /**
+     * Define new property with a static location or change existing property.
+     *
+     * @param key property identifier
+     * @param value value to be set
+     * @param flags flags to be set
+     * @param locationFactory factory function that creates a location for a given shape and value
+     */
+    public abstract void define(Object key, Object value, int flags, LocationFactory locationFactory);
+
+    /**
+     * Change property flags.
+     *
+     * @param key property identifier
+     * @param newFlags flags to be set
+     * @return {@code true} if successful or {@code false} if property not found
+     */
+    public abstract boolean changeFlags(Object key, int newFlags);
+
+    /**
+     * Change property flags.
+     *
+     * @param key property identifier
+     * @param flagsUpdateFunction function updating old flags to new flags
+     * @return {@code true} if successful or {@code false} if property not found
+     */
+    public abstract boolean changeFlags(Object key, FlagsFunction flagsUpdateFunction);
+
+    /**
+     * Delete property.
+     *
+     * @param key property identifier
+     * @return {@code true} if successful or {@code false} if property not found
+     */
+    public abstract boolean delete(Object key);
+
+    /**
+     * Returns the number of properties in this object.
+     */
+    public abstract int size();
+
+    /**
+     * Returns {@code true} if this object contains no properties.
+     */
+    public abstract boolean isEmpty();
+
+    /**
+     * Set object shape and grow storage if necessary.
+     *
+     * @param oldShape the object's current shape (must equal {@link #getShape()})
+     * @param newShape the new shape to be set
+     */
+    public abstract void setShapeAndGrow(Shape oldShape, Shape newShape);
+
+    /**
+     * Set object shape and resize storage if necessary.
+     *
+     * @param oldShape the object's current shape (must equal {@link #getShape()})
+     * @param newShape the new shape to be set
+     */
+    public abstract void setShapeAndResize(Shape oldShape, Shape newShape);
+
+    /**
+     * Ensure object shape is up-to-date.
+     *
+     * @return {@code true} if shape has changed
+     */
+    public abstract boolean updateShape();
+
+    public interface FlagsFunction {
+        int apply(int t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/DynamicObjectFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface DynamicObjectFactory {
+    DynamicObject newInstance(Object... initialValues);
+
+    Shape getShape();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/FinalLocationException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import com.oracle.truffle.api.nodes.*;
+
+public final class FinalLocationException extends SlowPathException {
+    private static final long serialVersionUID = -30188494510914293L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/HiddenKey.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public final class HiddenKey {
+    private final String name;
+
+    public HiddenKey(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IncompatibleLocationException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import com.oracle.truffle.api.nodes.*;
+
+public final class IncompatibleLocationException extends SlowPathException {
+    private static final long serialVersionUID = -7734865392357341789L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/IntLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface IntLocation extends TypedLocation {
+    /**
+     * @see #get(DynamicObject, Shape)
+     */
+    int getInt(DynamicObject store, Shape shape);
+
+    /**
+     * @see #get(DynamicObject, boolean)
+     */
+    int getInt(DynamicObject store, boolean condition);
+
+    /**
+     * @see #set(DynamicObject, Object)
+     */
+    void setInt(DynamicObject store, int value) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape)
+     */
+    void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape, Shape)
+     */
+    void setInt(DynamicObject store, int value, Shape oldShape, Shape newShape);
+
+    Class<Integer> getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Layout.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
+import com.oracle.truffle.api.object.Shape.Allocator;
+
+public abstract class Layout {
+    public static final EnumSet<ImplicitCast> NONE = EnumSet.noneOf(ImplicitCast.class);
+    public static final EnumSet<ImplicitCast> INT_TO_DOUBLE = EnumSet.of(ImplicitCast.IntToDouble);
+    public static final EnumSet<ImplicitCast> INT_TO_LONG = EnumSet.of(ImplicitCast.IntToLong);
+
+    public static final String OPTION_PREFIX = "truffle.object.";
+
+    private static final LayoutFactory LAYOUT_FACTORY = loadLayoutFactory();
+
+    public enum ImplicitCast {
+        IntToDouble,
+        IntToLong,
+    }
+
+    public static Layout createLayout() {
+        return createLayout(NONE);
+    }
+
+    public static Layout createLayout(EnumSet<ImplicitCast> allowedImplicitCasts) {
+        return new LayoutBuilder().setAllowedImplicitCasts(allowedImplicitCasts).build();
+    }
+
+    public static Layout createLayout(EnumSet<ImplicitCast> allowedImplicitCasts, FieldOffsetProvider fieldOffsetProvider) {
+        return new LayoutBuilder().setAllowedImplicitCasts(allowedImplicitCasts).setFieldOffsetProvider(fieldOffsetProvider).build();
+    }
+
+    public abstract DynamicObject newInstance(Shape shape);
+
+    public abstract Class<? extends DynamicObject> getType();
+
+    public abstract Shape createShape(ObjectType operations);
+
+    public abstract Shape createShape(ObjectType operations, Object sharedData);
+
+    public abstract Shape createShape(ObjectType operations, Object sharedData, int id);
+
+    /**
+     * Create an allocator for static property creation. Reserves all array extension slots.
+     */
+    public abstract Allocator createAllocator();
+
+    protected static LayoutFactory getFactory() {
+        return LAYOUT_FACTORY;
+    }
+
+    private static LayoutFactory loadLayoutFactory() {
+        LayoutFactory bestLayoutFactory = null;
+
+        String layoutFactoryImplClassName = System.getProperty(OPTION_PREFIX + "LayoutFactory");
+        if (layoutFactoryImplClassName != null) {
+            Class<?> clazz;
+            try {
+                clazz = Class.forName(layoutFactoryImplClassName);
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+            try {
+                bestLayoutFactory = (LayoutFactory) clazz.newInstance();
+            } catch (InstantiationException | IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        } else {
+            ServiceLoader<LayoutFactory> serviceLoader = ServiceLoader.load(LayoutFactory.class, Layout.class.getClassLoader());
+            for (LayoutFactory currentLayoutFactory : serviceLoader) {
+                if (bestLayoutFactory == null) {
+                    bestLayoutFactory = currentLayoutFactory;
+                } else if (currentLayoutFactory.getPriority() >= bestLayoutFactory.getPriority()) {
+                    assert currentLayoutFactory.getPriority() != bestLayoutFactory.getPriority();
+                    bestLayoutFactory = currentLayoutFactory;
+                }
+            }
+        }
+
+        if (bestLayoutFactory == null) {
+            throw new AssertionError("LayoutFactory not found");
+        }
+        return bestLayoutFactory;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutBuilder.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
+import com.oracle.truffle.api.object.Layout.ImplicitCast;
+
+public class LayoutBuilder {
+    private EnumSet<ImplicitCast> allowedImplicitCasts;
+    private FieldOffsetProvider fieldOffsetProvider;
+
+    public LayoutBuilder() {
+        this.allowedImplicitCasts = Layout.NONE;
+        this.fieldOffsetProvider = null;
+    }
+
+    public Layout build() {
+        return Layout.getFactory().createLayout(this);
+    }
+
+    public LayoutBuilder setAllowedImplicitCasts(EnumSet<ImplicitCast> allowedImplicitCasts) {
+        this.allowedImplicitCasts = allowedImplicitCasts;
+        return this;
+    }
+
+    public LayoutBuilder setFieldOffsetProvider(FieldOffsetProvider fieldOffsetProvider) {
+        this.fieldOffsetProvider = fieldOffsetProvider;
+        return this;
+    }
+
+    public EnumSet<ImplicitCast> getAllowedImplicitCasts() {
+        return allowedImplicitCasts;
+    }
+
+    public FieldOffsetProvider getFieldOffsetProvider() {
+        return fieldOffsetProvider;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LayoutFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface LayoutFactory {
+    Layout createLayout(LayoutBuilder layoutBuilder);
+
+    Property createProperty(Object id, Location location);
+
+    Property createProperty(Object id, Location location, int flags);
+
+    int getPriority();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Location.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Property location.
+ *
+ * @see Shape
+ * @see Property
+ * @see DynamicObject
+ */
+public abstract class Location implements BaseLocation {
+    protected static IncompatibleLocationException incompatibleLocation() throws IncompatibleLocationException {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        throw new IncompatibleLocationException();
+    }
+
+    protected static FinalLocationException finalLocation() throws FinalLocationException {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        throw new FinalLocationException();
+    }
+
+    public final Object get(DynamicObject store, Shape shape) {
+        return get(store, checkShape(store, shape));
+    }
+
+    public Object get(DynamicObject store, boolean condition) {
+        return getInternal(store);
+    }
+
+    public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
+        setInternal(store, value);
+    }
+
+    public final void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException {
+        if (canStore(value)) {
+            store.setShapeAndGrow(oldShape, newShape);
+            try {
+                setInternal(store, value);
+            } catch (IncompatibleLocationException ex) {
+                throw new IllegalStateException();
+            }
+        } else {
+            throw incompatibleLocation();
+        }
+    }
+
+    public final void set(DynamicObject store, Object value) throws IncompatibleLocationException, FinalLocationException {
+        set(store, value, null);
+    }
+
+    protected abstract Object getInternal(DynamicObject store);
+
+    /**
+     * Like {@link #set(DynamicObject, Object, Shape)}, but does not invalidate final locations. For
+     * internal use only and subject to change, use {@link DynamicObjectFactory} to create objects
+     * with predefined properties.
+     *
+     * @throws IncompatibleLocationException if value is of non-assignable type
+     */
+    protected abstract void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException;
+
+    /**
+     * Returns {@code true} if the location can be set to the value.
+     *
+     * @param store the receiver object
+     * @param value the value in question
+     */
+    public boolean canSet(DynamicObject store, Object value) {
+        return canStore(value);
+    }
+
+    /**
+     * Returns {@code true} if the location is compatible with the value.
+     *
+     * The value may still be rejected if {@link #canSet(DynamicObject, Object)} returns false.
+     *
+     * @param value the value in question
+     */
+    public boolean canStore(Object value) {
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if this is a final location, i.e. readonly once set.
+     */
+    public boolean isFinal() {
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if this is an immutable constant location.
+     */
+    public boolean isConstant() {
+        return false;
+    }
+
+    /*
+     * Abstract to force overriding.
+     */
+    @Override
+    public abstract int hashCode();
+
+    /*
+     * Abstract to force overriding.
+     */
+    @Override
+    public abstract boolean equals(Object obj);
+
+    protected static boolean checkShape(DynamicObject store, Shape shape) {
+        return store.getShape() == shape;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface LocationFactory {
+    Location createLocation(Shape shape, Object value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LocationModifier.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public enum LocationModifier {
+    Final,
+    NonNull,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/LongLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface LongLocation extends TypedLocation {
+    /**
+     * @see #get(DynamicObject, Shape)
+     */
+    long getLong(DynamicObject store, Shape shape);
+
+    /**
+     * @see #get(DynamicObject, boolean)
+     */
+    long getLong(DynamicObject store, boolean condition);
+
+    /**
+     * @see #set(DynamicObject, Object)
+     */
+    void setLong(DynamicObject store, long value) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape)
+     */
+    void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException;
+
+    /**
+     * @see #set(DynamicObject, Object, Shape, Shape)
+     */
+    void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape);
+
+    Class<Long> getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface ObjectLocation extends TypedLocation {
+    Class<? extends Object> getType();
+
+    /**
+     * If {@code true}, this location does not accept {@code null} values.
+     */
+    boolean isNonNull();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.*;
+
+public class ObjectType {
+    /**
+     * Delegate method for {@link DynamicObject#equals(Object)}.
+     */
+    public boolean equals(DynamicObject object, Object other) {
+        return object == other;
+    }
+
+    /**
+     * Delegate method for {@link DynamicObject#hashCode()}.
+     */
+    public int hashCode(DynamicObject object) {
+        return System.identityHashCode(object);
+    }
+
+    /**
+     * Delegate method for {@link DynamicObject#toString()}.
+     */
+    @TruffleBoundary
+    public String toString(DynamicObject object) {
+        return "DynamicObject<" + this.toString() + ">@" + Integer.toHexString(hashCode(object));
+    }
+
+    /**
+     * Creates a data object to be associated with a newly created shape.
+     *
+     * @param shape the shape for which to create the data object
+     */
+    public Object createShapeData(Shape shape) {
+        return null;
+    }
+
+    public ForeignAccess getForeignAccessFactory() {
+        return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() {
+
+            public boolean canHandle(TruffleObject obj) {
+                throw new IllegalArgumentException(this.toString() + " cannot be shared");
+            }
+
+            public CallTarget accessMessage(Message tree) {
+                throw new IllegalArgumentException(this.toString() + " cannot be shared; Message not possible: " + tree.toString());
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Property.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+/**
+ * Property objects represent the mapping between property identifiers (keys) and storage locations.
+ * Optionally, properties may have metadata attached to them.
+ */
+public abstract class Property {
+    protected Property() {
+    }
+
+    public static Property create(Object key, Location location, int flags) {
+        return Layout.getFactory().createProperty(key, location, flags);
+    }
+
+    /**
+     * Get property identifier.
+     */
+    public abstract Object getKey();
+
+    /**
+     * Get property flags.
+     */
+    public abstract int getFlags();
+
+    /**
+     * Change the property's location.
+     *
+     * @return a Property with the new location (or {@code this} if the location is unchanged).
+     */
+    public abstract Property relocate(Location newLocation);
+
+    /**
+     * Gets the value of this property of the object.
+     *
+     * @param store the store that this property resides in
+     * @param shape the current shape of the object, which must contain this location
+     * @see DynamicObject#get(Object, Object)
+     */
+    public abstract Object get(DynamicObject store, Shape shape);
+
+    /**
+     * Gets the value of this property of the object.
+     *
+     * @param store the store that this property resides in
+     * @param condition the result of a shape check or {@code false}
+     * @see DynamicObject#get(Object, Object)
+     * @see #get(DynamicObject, Shape)
+     */
+    public abstract Object get(DynamicObject store, boolean condition);
+
+    /**
+     * Assigns value to this property of the object.
+     *
+     * Throws an exception if the value cannot be assigned to the property's current location.
+     *
+     * @param store the store that this property resides in
+     * @param value the value to assign
+     * @param shape the current shape of the object or {@code null}
+     * @throws IncompatibleLocationException if the value is incompatible with the property location
+     * @throws FinalLocationException if the location is final and values differ
+     * @see DynamicObject#set(Object, Object)
+     */
+    public abstract void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException;
+
+    /**
+     * Assigns value to this property of the object.
+     *
+     * Automatically relocates the property if the value cannot be assigned to its current location.
+     *
+     * @param shape the current shape of the object or {@code null}
+     */
+    public abstract void setGeneric(DynamicObject store, Object value, Shape shape);
+
+    /**
+     * Like {@link #set(DynamicObject, Object, Shape)}, but throws an {@link IllegalStateException}
+     * instead.
+     */
+    public abstract void setSafe(DynamicObject store, Object value, Shape shape);
+
+    /**
+     * Like {@link #setSafe}, but ignores the finalness of the property. For internal use only.
+     *
+     * @param store the store that this property resides in
+     * @param value the value to assign
+     */
+    public abstract void setInternal(DynamicObject store, Object value);
+
+    /**
+     * Assigns value to this property of the object, changing the object's shape.
+     *
+     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
+     * {@link #set(DynamicObject, Object, Shape)} to an atomic operation.
+     *
+     * @param store the store that this property resides in
+     * @param value the value to assign
+     * @param oldShape the shape before the transition
+     * @param newShape the shape after the transition
+     * @throws IncompatibleLocationException if the value is incompatible with the property location
+     */
+    public abstract void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException;
+
+    /**
+     * Assigns value to this property of the object, changing the object's shape.
+     *
+     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
+     * {@link #setGeneric(DynamicObject, Object, Shape)} to an atomic operation.
+     *
+     * @param store the store that this property resides in
+     * @param value the value to assign
+     * @param oldShape the shape before the transition
+     * @param newShape the shape after the transition
+     */
+    public abstract void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape);
+
+    /**
+     * Assigns value to this property of the object, changing the object's shape.
+     *
+     * Combines {@link DynamicObject#setShapeAndGrow(Shape, Shape)} and
+     * {@link #setSafe(DynamicObject, Object, Shape)} to an atomic operation.
+     *
+     * @param store the store that this property resides in
+     * @param value the value to assign
+     * @param oldShape the shape before the transition
+     * @param newShape the shape after the transition
+     */
+    public abstract void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape);
+
+    /**
+     * Returns {@code true} if this property and some other property have the same key and flags.
+     */
+    public abstract boolean isSame(Property other);
+
+    /**
+     * Get the property location.
+     */
+    public abstract Location getLocation();
+
+    /**
+     * Is this property hidden from iteration.
+     *
+     * @see HiddenKey
+     */
+    public abstract boolean isHidden();
+
+    public abstract boolean isShadow();
+
+    /**
+     * Create a copy of the property with the given flags.
+     */
+    public abstract Property copyWithFlags(int newFlags);
+
+    public abstract Property copyWithRelocatable(boolean newRelocatable);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/Shape.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Shape objects create a mapping of Property objects to Locations. Shapes are immutable; adding or
+ * deleting a property yields a new Shape which links to the old one. This allows inline caching to
+ * simply check the identity of an object's Shape to determine if the cache is valid. There is one
+ * exception to this immutability, the transition map, but that is used simply to assure that an
+ * identical series of property additions and deletions will yield the same Shape object.
+ *
+ * @see DynamicObject
+ * @see Property
+ * @see Location
+ */
+public abstract class Shape {
+    /**
+     * Get a property entry by key.
+     *
+     * @param key the identifier to look up
+     * @return a Property object, or null if not found
+     */
+    public abstract Property getProperty(Object key);
+
+    /**
+     * Add a new property in the map, yielding a new or cached Shape object.
+     *
+     * @param property the property to add
+     * @return the new Shape
+     */
+    public abstract Shape addProperty(Property property);
+
+    /**
+     * An {@link Iterable} over the shape's properties in insertion order.
+     */
+    public abstract Iterable<Property> getProperties();
+
+    /**
+     * Get a list of properties that this Shape stores.
+     *
+     * @return list of properties
+     */
+    public abstract List<Property> getPropertyList(Pred<Property> filter);
+
+    /**
+     * Get a list of all properties that this Shape stores.
+     *
+     * @return list of properties
+     */
+    public abstract List<Property> getPropertyList();
+
+    /**
+     * Returns all (also hidden) property objects in this shape.
+     *
+     * @param ascending desired order ({@code true} for insertion order, {@code false} for reverse
+     *            insertion order)
+     */
+    public abstract List<Property> getPropertyListInternal(boolean ascending);
+
+    /**
+     * Get a filtered list of property keys in insertion order.
+     */
+    public abstract List<Object> getKeyList(Pred<Property> filter);
+
+    /**
+     * Get a list of all property keys in insertion order.
+     */
+    public abstract List<Object> getKeyList();
+
+    /**
+     * Get all property keys in insertion order.
+     */
+    public abstract Iterable<Object> getKeys();
+
+    /**
+     * Get an assumption that the shape is valid.
+     */
+    public abstract Assumption getValidAssumption();
+
+    /**
+     * Check whether this shape is valid.
+     */
+    public abstract boolean isValid();
+
+    /**
+     * Get an assumption that the shape is a leaf.
+     */
+    public abstract Assumption getLeafAssumption();
+
+    /**
+     * Check whether this shape is a leaf in the transition graph, i.e. transitionless.
+     */
+    public abstract boolean isLeaf();
+
+    /**
+     * @return the parent shape or {@code null} if none.
+     */
+    public abstract Shape getParent();
+
+    /**
+     * Check whether the shape has a property with the given key.
+     */
+    public abstract boolean hasProperty(Object key);
+
+    /**
+     * Remove the given property from the shape.
+     */
+    public abstract Shape removeProperty(Property property);
+
+    /**
+     * Replace a property in the shape.
+     */
+    public abstract Shape replaceProperty(Property oldProperty, Property newProperty);
+
+    /**
+     * Get the last added property.
+     */
+    public abstract Property getLastProperty();
+
+    public abstract int getId();
+
+    /**
+     * Append the property, relocating it to the next allocated location.
+     */
+    public abstract Shape append(Property oldProperty);
+
+    /**
+     * Obtain an {@link Allocator} instance for the purpose of allocating locations.
+     */
+    public abstract Allocator allocator();
+
+    /**
+     * Get number of properties in this shape.
+     */
+    public abstract int getPropertyCount();
+
+    /**
+     * Get the shape's operations.
+     */
+    public abstract ObjectType getObjectType();
+
+    /**
+     * Get the root shape.
+     */
+    public abstract Shape getRoot();
+
+    /**
+     * Check whether this shape is identical to the given shape.
+     */
+    public abstract boolean check(DynamicObject subject);
+
+    /**
+     * Get the shape's layout.
+     */
+    public abstract Layout getLayout();
+
+    /**
+     * Get the shape's custom data.
+     */
+    public abstract Object getData();
+
+    /**
+     * Get the shape's shared data.
+     */
+    public abstract Object getSharedData();
+
+    /**
+     * Query whether the shape has a transition with the given key.
+     */
+    public abstract boolean hasTransitionWithKey(Object key);
+
+    /**
+     * Clone off a separate shape with new shared data.
+     */
+    public abstract Shape createSeparateShape(Object sharedData);
+
+    /**
+     * Change the shape's type, yielding a new shape.
+     */
+    public abstract Shape changeType(ObjectType newOps);
+
+    /**
+     * Reserve the primitive extension array field.
+     */
+    public abstract Shape reservePrimitiveExtensionArray();
+
+    /**
+     * Create a new {@link DynamicObject} instance with this shape.
+     */
+    public abstract DynamicObject newInstance();
+
+    /**
+     * Create a {@link DynamicObjectFactory} for creating instances of this shape.
+     */
+    public abstract DynamicObjectFactory createFactory();
+
+    /**
+     * Get mutex object shared by related shapes, i.e. shapes with a common root.
+     */
+    public abstract Object getMutex();
+
+    public abstract int getObjectArraySize();
+
+    public abstract int getObjectFieldSize();
+
+    public abstract int getPrimitiveArraySize();
+
+    public abstract int getPrimitiveFieldSize();
+
+    public abstract int getObjectArrayCapacity();
+
+    public abstract int getPrimitiveArrayCapacity();
+
+    public abstract boolean hasPrimitiveArray();
+
+    /**
+     * Are these two shapes related, i.e. do they have the same root?
+     *
+     * @param other Shape to compare to
+     * @return true if one shape is an upcast of the other, or the Shapes are equal
+     */
+    public abstract boolean isRelated(Shape other);
+
+    public abstract Shape tryMerge(Shape other);
+
+    public <R> R accept(ShapeVisitor<R> visitor) {
+        return visitor.visitShape(this);
+    }
+
+    public abstract static class Allocator {
+        protected abstract Location locationForValue(Object value, boolean useFinal, boolean nonNull);
+
+        public final Location locationForValue(Object value) {
+            return locationForValue(value, false, value != null);
+        }
+
+        public final Location locationForValue(Object value, EnumSet<LocationModifier> modifiers) {
+            assert value != null || !modifiers.contains(LocationModifier.NonNull);
+            return locationForValue(value, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
+        }
+
+        protected abstract Location locationForType(Class<?> type, boolean useFinal, boolean nonNull);
+
+        public final Location locationForType(Class<?> type) {
+            return locationForType(type, false, false);
+        }
+
+        public final Location locationForType(Class<?> type, EnumSet<LocationModifier> modifiers) {
+            return locationForType(type, modifiers.contains(LocationModifier.Final), modifiers.contains(LocationModifier.NonNull));
+        }
+
+        public abstract Location constantLocation(Object value);
+
+        public abstract Location declaredLocation(Object value);
+
+        public abstract Allocator addLocation(Location location);
+    }
+
+    /**
+     * Represents a predicate (boolean-valued function) of one argument. For Java 7 compatibility.
+     *
+     * @param <T> the type of the input to the predicate
+     */
+    public interface Pred<T> {
+        /**
+         * Evaluates this predicate on the given argument.
+         *
+         * @param t the input argument
+         * @return {@code true} if the input argument matches the predicate, otherwise {@code false}
+         */
+        boolean test(T t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface ShapeListener {
+    /**
+     * Called when a property is added, removed, or replaced.
+     *
+     * @param key identifier of the property
+     */
+    void onPropertyTransition(Object key);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface ShapeVisitor<R> {
+    R visitShape(Shape shape);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/TypedLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.object;
+
+public interface TypedLocation extends BaseLocation {
+    /**
+     * The type of this location.
+     */
+    Class<?> getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Passing Arguments</h3>
+ *
+ * <p>
+ * When invoking a call target with {@link CallTarget#call(Object[])}, arguments can be passed. A
+ * Truffle node can access the arguments passed into the Truffle method by using
+ * {@link VirtualFrame#getArguments}.
+ * </p>
+ *
+ * <p>
+ * The arguments class should only contain fields that are declared as final. This allows the
+ * Truffle runtime to improve optimizations around guest language method calls. Also, the arguments
+ * object array must never be stored into a field. It should be created immediately before invoking
+ * {@link CallTarget#call(Object[])} and no longer be accessed afterwards.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.FrameTest}
+ * .
+ * </p>
+ */
+public class ArgumentsTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode(new TestArgumentNode[]{new TestArgumentNode(0), new TestArgumentNode(1)});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call(new Object[]{20, 22});
+        Assert.assertEquals(42, result);
+    }
+
+    private static class TestRootNode extends RootNode {
+
+        @Children private final TestArgumentNode[] children;
+
+        TestRootNode(TestArgumentNode[] children) {
+            super(null);
+            this.children = children;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute(frame);
+            }
+            return sum;
+        }
+    }
+
+    private static class TestArgumentNode extends Node {
+
+        private final int index;
+
+        TestArgumentNode(int index) {
+            super(null);
+            this.index = index;
+        }
+
+        int execute(VirtualFrame frame) {
+            return (Integer) frame.getArguments()[index];
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/CallTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Calling Another Tree</h3>
+ *
+ * <p>
+ * A guest language implementation can create multiple call targets using the
+ * {@link TruffleRuntime#createCallTarget(RootNode)} method. Those call targets can be passed around
+ * as normal Java objects and used for calling guest language methods.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.ArgumentsTest}.
+ * </p>
+ */
+public class CallTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        CallTarget foo = runtime.createCallTarget(new ConstantRootNode(20));
+        CallTarget bar = runtime.createCallTarget(new ConstantRootNode(22));
+        CallTarget main = runtime.createCallTarget(new DualCallNode(foo, bar));
+        Object result = main.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class DualCallNode extends RootNode {
+
+        private final CallTarget firstTarget;
+        private final CallTarget secondTarget;
+
+        DualCallNode(CallTarget firstTarget, CallTarget secondTarget) {
+            super(null);
+            this.firstTarget = firstTarget;
+            this.secondTarget = secondTarget;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return ((Integer) firstTarget.call()) + ((Integer) secondTarget.call());
+        }
+    }
+
+    class ConstantRootNode extends RootNode {
+
+        private final int value;
+
+        public ConstantRootNode(int value) {
+            super(null);
+            this.value = value;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildNodeTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+
+/**
+ * <h3>Creating a Child Node</h3>
+ *
+ * <p>
+ * Child nodes are stored in the class of the parent node in fields that are marked with the
+ * {@link Child} annotation. The {@link Node#getParent()} method allows access to this field. Every
+ * node also provides the ability to iterate over its children using {@link Node#getChildren()}.
+ * </p>
+ *
+ * <p>
+ * A child node field must be declared private and non-final. It may only be assigned in the
+ * constructor of the parent node. For changing the structure of the tree at run time, the method
+ * {@link Node#replace(Node)} must be used (see {@link ReplaceTest}).
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.ChildrenNodesTest}.
+ * </p>
+ */
+public class ChildNodeTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode leftChild = new TestChildNode();
+        TestChildNode rightChild = new TestChildNode();
+        TestRootNode rootNode = new TestRootNode(leftChild, rightChild);
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(rootNode, leftChild.getParent());
+        Assert.assertEquals(rootNode, rightChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child private TestChildNode left;
+        @Child private TestChildNode right;
+
+        public TestRootNode(TestChildNode left, TestChildNode right) {
+            super(null);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return left.execute() + right.execute();
+        }
+    }
+
+    class TestChildNode extends Node {
+
+        public TestChildNode() {
+            super(null);
+        }
+
+        public int execute() {
+            return 21;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ChildrenNodesTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Creating an Array of Children Nodes</h3>
+ *
+ * <p>
+ * An array of children nodes can be used as a field in a parent node. The field has to be annotated
+ * with {@link com.oracle.truffle.api.nodes.Node.Children} and must be declared private and final.
+ * Before assigning the field in the parent node constructor, {@link Node#adoptChildren} must be
+ * called in order to update the parent pointers in the child nodes. After filling the array with
+ * its first values, it must never be changed. It is only possible to call {@link Node#replace} on a
+ * child node.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.FinalFieldTest}.
+ * </p>
+ */
+public class ChildrenNodesTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode firstChild = new TestChildNode();
+        TestChildNode secondChild = new TestChildNode();
+        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{firstChild, secondChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(rootNode, firstChild.getParent());
+        Assert.assertEquals(rootNode, secondChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(firstChild, iterator.next());
+        Assert.assertEquals(secondChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children private final TestChildNode[] children;
+
+        public TestRootNode(TestChildNode[] children) {
+            super(null);
+            this.children = children;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    class TestChildNode extends Node {
+
+        public TestChildNode() {
+            super(null);
+        }
+
+        public int execute() {
+            return 21;
+        }
+    }
+
+    @Test
+    public void testMultipleChildrenFields() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildNode firstChild = new TestChildNode();
+        TestChildNode secondChild = new TestChildNode();
+        TestChildNode thirdChild = new TestChildNode();
+        TestChildNode forthChild = new TestChildNode();
+        TestRootNode rootNode = new TestRoot2Node(new TestChildNode[]{firstChild, secondChild}, new TestChildNode[]{thirdChild, forthChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(rootNode, firstChild.getParent());
+        Assert.assertEquals(rootNode, secondChild.getParent());
+        Assert.assertEquals(rootNode, thirdChild.getParent());
+        Assert.assertEquals(rootNode, forthChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(firstChild, iterator.next());
+        Assert.assertEquals(secondChild, iterator.next());
+        Assert.assertEquals(thirdChild, iterator.next());
+        Assert.assertEquals(forthChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(2 * 42, result);
+    }
+
+    class TestRoot2Node extends TestRootNode {
+        @Children private final TestChildNode[] children1;
+        @Children private final TestChildNode[] children2;
+
+        public TestRoot2Node(TestChildNode[] children1, TestChildNode[] children2) {
+            super(new TestChildNode[0]);
+            this.children1 = children1;
+            this.children2 = children2;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children1.length; ++i) {
+                sum += children1[i].execute();
+            }
+            for (int i = 0; i < children2.length; ++i) {
+                sum += children2[i].execute();
+            }
+            return sum;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FinalFieldTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Using Final Fields in Node Classes</h3>
+ *
+ * <p>
+ * The usage of final fields in node classes is highly encouraged. It is beneficial for performance
+ * to declare every field that is not pointing to a child node as final. This gives the Truffle
+ * runtime an increased opportunity to optimize this node.
+ * </p>
+ *
+ * <p>
+ * If a node has a value which may change at run time, but will rarely do so, it is recommended to
+ * speculate on the field being final. This involves starting executing with a node where this field
+ * is final and only if this turns out to be no longer the case, the node is replaced with an
+ * alternative implementation of the operation (see {@link ReplaceTest}).
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.ReplaceTest}.
+ * </p>
+ */
+public class FinalFieldTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode(new TestChildNode[]{new TestChildNode(20), new TestChildNode(22)});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    private static class TestRootNode extends RootNode {
+
+        @Children private final TestChildNode[] children;
+
+        public TestRootNode(TestChildNode[] children) {
+            super(null);
+            this.children = children;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    private static class TestChildNode extends Node {
+
+        private final int value;
+
+        public TestChildNode(int value) {
+            super(null);
+            this.value = value;
+        }
+
+        public int execute() {
+            return value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Specializing Frame Slot Types</h3>
+ *
+ * <p>
+ * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run
+ * time to a more generic type if necessary. The new type of a frame slot can be set using the
+ * {@link FrameSlot#setKind(FrameSlotKind)} method.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}.
+ * </p>
+ */
+public class FrameSlotTypeSpecializationTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
+        Object result = target.call();
+        Assert.assertEquals("42", result);
+        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            left.execute(frame);
+            return right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+
+        protected TestChildNode() {
+            super(null);
+        }
+
+        abstract Object execute(VirtualFrame frame);
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class StringTestChildNode extends TestChildNode {
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return "42";
+        }
+
+    }
+
+    class IntAssignLocal extends FrameSlotNode {
+
+        @Child private TestChildNode value;
+
+        IntAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = value;
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            if (o instanceof Integer) {
+                frame.setInt(slot, (Integer) o);
+            } else {
+                slot.setKind(FrameSlotKind.Object);
+                frame.setObject(slot, o);
+                this.replace(new ObjectAssignLocal(slot, value));
+            }
+            return null;
+        }
+    }
+
+    class ObjectAssignLocal extends FrameSlotNode {
+
+        @Child private TestChildNode value;
+
+        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = value;
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            slot.setKind(FrameSlotKind.Object);
+            frame.setObject(slot, o);
+            return null;
+        }
+    }
+
+    class IntReadLocal extends FrameSlotNode {
+
+        IntReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return this.replace(new ObjectReadLocal(slot)).execute(frame);
+            }
+        }
+    }
+
+    class ObjectReadLocal extends FrameSlotNode {
+
+        ObjectReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                return frame.getObject(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Storing Values in Frame Slots</h3>
+ *
+ * <p>
+ * The frame is the preferred data structure for passing values between nodes. It can in particular
+ * be used for storing the values of local variables of the guest language. The
+ * {@link FrameDescriptor} represents the current structure of the frame. The method
+ * {@link FrameDescriptor#addFrameSlot(Object, FrameSlotKind)} can be used to create predefined
+ * frame slots. The setter and getter methods in the {@link Frame} class can be used to access the
+ * current value of a particular frame slot. Values can be removed from a frame via the
+ * {@link FrameDescriptor#removeFrameSlot(Object)} method.
+ * </p>
+ *
+ * <p>
+ * There are five primitive types for slots available: {@link java.lang.Boolean},
+ * {@link java.lang.Integer}, {@link java.lang.Long}, {@link java.lang.Float}, and
+ * {@link java.lang.Double} . It is encouraged to use those types whenever possible. Dynamically
+ * typed languages can speculate on the type of a value fitting into a primitive (see
+ * {@link FrameSlotTypeSpecializationTest}). When a frame slot is of one of those particular
+ * primitive types, its value may only be accessed with the respectively typed getter method (
+ * {@link Frame#getBoolean}, {@link Frame#getInt}, {@link Frame#getLong}, {@link Frame#getFloat}, or
+ * {@link Frame#getDouble}) or setter method ({@link Frame#setBoolean}, {@link Frame#setInt},
+ * {@link Frame#setLong}, {@link Frame#setFloat}, or {@link Frame#setDouble}) in the {@link Frame}
+ * class.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}.
+ * </p>
+ */
+public class FrameTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        String varName = "localVar";
+        FrameSlot slot = frameDescriptor.addFrameSlot(varName, FrameSlotKind.Int);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new AssignLocal(slot), new ReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+        frameDescriptor.removeFrameSlot(varName);
+        boolean slotMissing = false;
+        try {
+            result = target.call();
+        } catch (IllegalArgumentException iae) {
+            slotMissing = true;
+        }
+        Assert.assertTrue(slotMissing);
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return left.execute(frame) + right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+
+        public TestChildNode() {
+            super(null);
+        }
+
+        abstract int execute(VirtualFrame frame);
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class AssignLocal extends FrameSlotNode {
+
+        AssignLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            frame.setInt(slot, 42);
+            return 0;
+        }
+    }
+
+    class ReadLocal extends FrameSlotNode {
+
+        ReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InterfaceChildFieldTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Test child fields declared with interface types instead of {@link Node} subclasses.
+ */
+public class InterfaceChildFieldTest {
+
+    @Test
+    public void testChild() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildInterface leftChild = new TestLeafNode();
+        TestChildInterface rightChild = new TestLeafNode();
+        TestChildNode parent = new TestChildNode(leftChild, rightChild);
+        TestRootNode rootNode = new TestRootNode(parent);
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Iterator<Node> iterator = parent.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+
+        Assert.assertEquals(4, NodeUtil.countNodes(rootNode));
+        Assert.assertEquals(4, NodeUtil.countNodes(NodeUtil.cloneNode(rootNode)));
+    }
+
+    @Test
+    public void testChildren() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestChildInterface[] children = new TestChildInterface[5];
+        for (int i = 0; i < children.length; i++) {
+            children[i] = new TestLeafNode();
+        }
+        TestChildrenNode parent = new TestChildrenNode(children);
+        TestRootNode rootNode = new TestRootNode(parent);
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Iterator<Node> iterator = parent.getChildren().iterator();
+        for (int i = 0; i < children.length; i++) {
+            Assert.assertEquals(children[i], iterator.next());
+        }
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        Assert.assertEquals(105, result);
+
+        Assert.assertEquals(2 + children.length, NodeUtil.countNodes(rootNode));
+        Assert.assertEquals(2 + children.length, NodeUtil.countNodes(NodeUtil.cloneNode(rootNode)));
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child private TestChildInterface child;
+
+        public TestRootNode(TestChildInterface child) {
+            super(null);
+            this.child = child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child.executeIntf();
+        }
+    }
+
+    interface TestChildInterface extends NodeInterface {
+        int executeIntf();
+    }
+
+    class TestLeafNode extends Node implements TestChildInterface {
+        public TestLeafNode() {
+            super(null);
+        }
+
+        public int executeIntf() {
+            return this.replace(new TestLeaf2Node()).executeIntf();
+        }
+    }
+
+    class TestLeaf2Node extends Node implements TestChildInterface {
+        public TestLeaf2Node() {
+            super(null);
+        }
+
+        public int executeIntf() {
+            return 21;
+        }
+    }
+
+    class TestChildNode extends Node implements TestChildInterface {
+
+        @Child private TestChildInterface left;
+        @Child private TestChildInterface right;
+
+        public TestChildNode(TestChildInterface left, TestChildInterface right) {
+            super(null);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public int executeIntf() {
+            return left.executeIntf() + right.executeIntf();
+        }
+    }
+
+    class TestChildrenNode extends Node implements TestChildInterface {
+
+        @Children private final TestChildInterface[] children;
+
+        public TestChildrenNode(TestChildInterface[] children) {
+            super(null);
+            this.children = children;
+        }
+
+        @Override
+        public int executeIntf() {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].executeIntf();
+            }
+            return sum;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReplaceTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Replacing Nodes at Run Time</h3>
+ *
+ * <p>
+ * The structure of the Truffle tree can be changed at run time by replacing nodes using the
+ * {@link Node#replace(Node)} method. This method will automatically change the child pointer in the
+ * parent of the node and replace it with a pointer to the new node.
+ * </p>
+ *
+ * <p>
+ * Replacing nodes is a costly operation, so it should not happen too often. The convention is that
+ * the implementation of the Truffle nodes should ensure that there are maximal a small (and
+ * constant) number of node replacements per Truffle node.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at {@link com.oracle.truffle.api.test.CallTest}.
+ * </p>
+ */
+public class ReplaceTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        UnresolvedNode leftChild = new UnresolvedNode("20");
+        UnresolvedNode rightChild = new UnresolvedNode("22");
+        TestRootNode rootNode = new TestRootNode(new ValueNode[]{leftChild, rightChild});
+        CallTarget target = runtime.createCallTarget(rootNode);
+        assertEquals(rootNode, leftChild.getParent());
+        assertEquals(rootNode, rightChild.getParent());
+        Iterator<Node> iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(leftChild, iterator.next());
+        Assert.assertEquals(rightChild, iterator.next());
+        Assert.assertFalse(iterator.hasNext());
+        Object result = target.call();
+        assertEquals(42, result);
+        assertEquals(42, target.call());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
+        Assert.assertEquals(ResolvedNode.class, iterator.next().getClass());
+        Assert.assertFalse(iterator.hasNext());
+        iterator = rootNode.getChildren().iterator();
+        Assert.assertEquals(rootNode, iterator.next().getParent());
+        Assert.assertEquals(rootNode, iterator.next().getParent());
+        Assert.assertFalse(iterator.hasNext());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Children private final ValueNode[] children;
+
+        public TestRootNode(ValueNode[] children) {
+            super(null);
+            this.children = children;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            int sum = 0;
+            for (int i = 0; i < children.length; ++i) {
+                sum += children[i].execute();
+            }
+            return sum;
+        }
+    }
+
+    abstract class ValueNode extends Node {
+
+        public ValueNode() {
+            super(null);
+        }
+
+        abstract int execute();
+    }
+
+    class UnresolvedNode extends ValueNode {
+
+        private final String value;
+
+        public UnresolvedNode(String value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute() {
+            int intValue = Integer.parseInt(value);
+            ResolvedNode newNode = this.replace(new ResolvedNode(intValue));
+            return newNode.execute();
+        }
+    }
+
+    class ResolvedNode extends ValueNode {
+
+        private final int value;
+
+        ResolvedNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute() {
+            return value;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Specializing Return Types</h3>
+ *
+ * <p>
+ * In order to avoid boxing and/or type casts on the return value of a node, the return value the
+ * method for executing a node can have a specific type and need not be of type
+ * {@link java.lang.Object}. For dynamically typed languages, this return type is something that
+ * should be speculated on. When the speculation fails and the child node cannot return the
+ * appropriate type of value, it can use an {@link UnexpectedResultException} to still pass the
+ * result to the caller. In such a case, the caller must rewrite itself to a more general version in
+ * order to avoid future failures of this kind.
+ * </p>
+ */
+public class ReturnTypeSpecializationTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
+        TestRootNode rootNode = new TestRootNode(frameDescriptor, new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
+        Object result = target.call();
+        Assert.assertEquals("42", result);
+        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
+    }
+
+    class TestRootNode extends RootNode {
+
+        @Child TestChildNode left;
+        @Child TestChildNode right;
+
+        public TestRootNode(FrameDescriptor descriptor, TestChildNode left, TestChildNode right) {
+            super(null, descriptor);
+            this.left = left;
+            this.right = right;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            left.execute(frame);
+            return right.execute(frame);
+        }
+    }
+
+    abstract class TestChildNode extends Node {
+
+        public TestChildNode() {
+            super(null);
+        }
+
+        abstract Object execute(VirtualFrame frame);
+
+        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            Object result = execute(frame);
+            if (result instanceof Integer) {
+                return (Integer) result;
+            }
+            throw new UnexpectedResultException(result);
+        }
+    }
+
+    abstract class FrameSlotNode extends TestChildNode {
+
+        protected final FrameSlot slot;
+
+        public FrameSlotNode(FrameSlot slot) {
+            this.slot = slot;
+        }
+    }
+
+    class StringTestChildNode extends TestChildNode {
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            return "42";
+        }
+
+    }
+
+    class IntAssignLocal extends FrameSlotNode {
+
+        @Child private TestChildNode value;
+
+        IntAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = value;
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                int result = value.executeInt(frame);
+                frame.setInt(slot, result);
+            } catch (UnexpectedResultException e) {
+                slot.setKind(FrameSlotKind.Object);
+                frame.setObject(slot, e.getResult());
+                replace(new ObjectAssignLocal(slot, value));
+            }
+            return null;
+        }
+    }
+
+    class ObjectAssignLocal extends FrameSlotNode {
+
+        @Child private TestChildNode value;
+
+        ObjectAssignLocal(FrameSlot slot, TestChildNode value) {
+            super(slot);
+            this.value = value;
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            Object o = value.execute(frame);
+            slot.setKind(FrameSlotKind.Object);
+            frame.setObject(slot, o);
+            return null;
+        }
+    }
+
+    class IntReadLocal extends FrameSlotNode {
+
+        IntReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return replace(new ObjectReadLocal(slot)).execute(frame);
+            }
+        }
+
+        @Override
+        int executeInt(VirtualFrame frame) throws UnexpectedResultException {
+            try {
+                return frame.getInt(slot);
+            } catch (FrameSlotTypeException e) {
+                return replace(new ObjectReadLocal(slot)).executeInt(frame);
+            }
+        }
+    }
+
+    class ObjectReadLocal extends FrameSlotNode {
+
+        ObjectReadLocal(FrameSlot slot) {
+            super(slot);
+        }
+
+        @Override
+        Object execute(VirtualFrame frame) {
+            try {
+                return frame.getObject(slot);
+            } catch (FrameSlotTypeException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/RootNodeTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * <h3>Creating a Root Node</h3>
+ *
+ * <p>
+ * A Truffle root node is the entry point into a Truffle tree that represents a guest language
+ * method. It contains a {@link RootNode#execute(VirtualFrame)} method that can return a
+ * {@link java.lang.Object} value as the result of the guest language method invocation. This method
+ * must however never be called directly. Instead, the Truffle runtime must be used to create a
+ * {@link CallTarget} object from a root node using the
+ * {@link TruffleRuntime#createCallTarget(RootNode)} method. This call target object can then be
+ * executed using the {@link CallTarget#call(Object...)} method or one of its overloads.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.ChildNodeTest}.
+ * </p>
+ */
+public class RootNodeTest {
+
+    @Test
+    public void test() {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode = new TestRootNode();
+        CallTarget target = runtime.createCallTarget(rootNode);
+        Object result = target.call();
+        Assert.assertEquals(42, result);
+    }
+
+    class TestRootNode extends RootNode {
+
+        public TestRootNode() {
+            super(null);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return 42;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ThreadSafetyTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Test node rewriting in a tree shared across multiple threads (run with -ea).
+ */
+public class ThreadSafetyTest {
+
+    @Test
+    @Ignore("sporadic failures with \"expected:<1000000> but was:<999999>\"")
+    public void test() throws InterruptedException {
+        TruffleRuntime runtime = Truffle.getRuntime();
+        TestRootNode rootNode1 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new ConstNode(42)))))));
+        final CallTarget target1 = runtime.createCallTarget(rootNode1);
+        NodeUtil.verify(rootNode1);
+
+        RecursiveCallNode callNode = new RecursiveCallNode(new ConstNode(42));
+        TestRootNode rootNode2 = new TestRootNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(new RewritingNode(callNode))))));
+        final CallTarget target2 = runtime.createCallTarget(rootNode2);
+        callNode.setCallNode(runtime.createDirectCallNode(target2));
+        NodeUtil.verify(rootNode2);
+
+        testTarget(target1, 47, 1_000_000);
+        testTarget(target2, 72, 1_000_000);
+    }
+
+    private static void testTarget(final CallTarget target, final int expectedResult, final int numberOfIterations) throws InterruptedException {
+        ExecutorService executorService = Executors.newFixedThreadPool(20);
+        final AtomicInteger ai = new AtomicInteger();
+        for (int i = 0; i < numberOfIterations; i++) {
+            executorService.submit(new Runnable() {
+                public void run() {
+                    try {
+                        Object result = target.call(new Object[]{5});
+                        assertEquals(expectedResult, result);
+                        ai.incrementAndGet();
+                    } catch (Throwable t) {
+                        t.printStackTrace(System.out);
+                    }
+                }
+            });
+        }
+        executorService.shutdown();
+        executorService.awaitTermination(90, TimeUnit.SECONDS);
+        assertTrue("test did not terminate", executorService.isTerminated());
+        assertEquals(numberOfIterations, ai.get());
+    }
+
+    static class TestRootNode extends RootNode {
+
+        @Child private ValueNode child;
+
+        public TestRootNode(ValueNode child) {
+            super(null);
+            this.child = child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return child.execute(frame);
+        }
+    }
+
+    abstract static class ValueNode extends Node {
+
+        public ValueNode() {
+            super(null);
+        }
+
+        abstract int execute(VirtualFrame frame);
+    }
+
+    static class RewritingNode extends ValueNode {
+
+        @Child private ValueNode child;
+        private final Random random;
+
+        public RewritingNode(ValueNode child) {
+            this(child, new Random());
+        }
+
+        public RewritingNode(ValueNode child, Random random) {
+            this.child = child;
+            this.random = random;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            boolean replace = random.nextBoolean();
+            if (replace) {
+                ValueNode newNode = this.replace(new OtherRewritingNode(child, random));
+                return newNode.execute(frame);
+            }
+            return 1 + child.execute(frame);
+        }
+    }
+
+    static class OtherRewritingNode extends ValueNode {
+
+        @Child private ValueNode child;
+        private final Random random;
+
+        public OtherRewritingNode(ValueNode child, Random random) {
+            this.child = child;
+            this.random = random;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            boolean replace = random.nextBoolean();
+            if (replace) {
+                ValueNode newNode = this.replace(new RewritingNode(child, random));
+                return newNode.execute(frame);
+            }
+            return 1 + child.execute(frame);
+        }
+    }
+
+    static class ConstNode extends ValueNode {
+
+        private final int value;
+
+        ConstNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            return value;
+        }
+    }
+
+    static class RecursiveCallNode extends ValueNode {
+        @Child DirectCallNode callNode;
+        @Child private ValueNode valueNode;
+
+        RecursiveCallNode(ValueNode value) {
+            this.valueNode = value;
+        }
+
+        @Override
+        int execute(VirtualFrame frame) {
+            int arg = (Integer) frame.getArguments()[0];
+            if (arg > 0) {
+                return (int) callNode.call(frame, new Object[]{(arg - 1)});
+            } else {
+                return valueNode.execute(frame);
+            }
+        }
+
+        void setCallNode(DirectCallNode callNode) {
+            this.callNode = insert(callNode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TruffleRuntimeTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * <h3>Accessing the Truffle Runtime</h3>
+ *
+ * <p>
+ * The Truffle runtime can be accessed at any point in time globally using the static method
+ * {@link Truffle#getRuntime()}. This method is guaranteed to return a non-null Truffle runtime
+ * object with an identifying name. A Java Virtual Machine implementation can chose to replace the
+ * default implementation of the {@link TruffleRuntime} interface with its own implementation for
+ * providing improved performance.
+ * </p>
+ *
+ * <p>
+ * The next part of the Truffle API introduction is at
+ * {@link com.oracle.truffle.api.test.RootNodeTest}.
+ * </p>
+ */
+public class TruffleRuntimeTest {
+
+    private TruffleRuntime runtime;
+
+    @Before
+    public void setUp() {
+        this.runtime = Truffle.getRuntime();
+    }
+
+    private static RootNode createTestRootNode() {
+        return new RootNode() {
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return 42;
+            }
+        };
+    }
+
+    // @Test
+    public void verifyTheRealRuntimeIsUsedOnRealGraal() {
+        TruffleRuntime r = Truffle.getRuntime();
+        final String name = r.getClass().getName();
+        if (name.endsWith("DefaultTruffleRuntime")) {
+            fail("Wrong name " + name + " with following System.getProperties:\n" + System.getProperties().toString());
+        }
+    }
+
+    @Test
+    public void test() {
+        assertNotNull(runtime);
+        assertNotNull(runtime.getName());
+    }
+
+    @Test
+    public void testCreateCallTarget() {
+        RootNode rootNode = createTestRootNode();
+        RootCallTarget target = runtime.createCallTarget(rootNode);
+        assertNotNull(target);
+        assertEquals(target.call(), 42);
+        assertSame(rootNode, target.getRootNode());
+    }
+
+    @Test
+    public void testGetCallTargets1() {
+        RootNode rootNode = createTestRootNode();
+        RootCallTarget target = runtime.createCallTarget(rootNode);
+        assertTrue(runtime.getCallTargets().contains(target));
+    }
+
+    @Test
+    public void testGetCallTargets2() {
+        RootNode rootNode = createTestRootNode();
+        RootCallTarget target1 = runtime.createCallTarget(rootNode);
+        RootCallTarget target2 = runtime.createCallTarget(rootNode);
+        assertTrue(runtime.getCallTargets().contains(target1));
+        assertTrue(runtime.getCallTargets().contains(target2));
+    }
+
+    /*
+     * This test case documents the use case for profilers and debuggers where they need to access
+     * multiple call targets for the same source section. This case may happen when the optimization
+     * system decides to duplicate call targets to achieve better performance.
+     */
+    @Test
+    public void testGetCallTargets3() {
+        Source source1 = Source.fromText("a\nb\n", "");
+        SourceSection sourceSection1 = source1.createSection("foo", 1);
+        SourceSection sourceSection2 = source1.createSection("bar", 2);
+
+        RootNode rootNode1 = createTestRootNode();
+        rootNode1.assignSourceSection(sourceSection1);
+        RootNode rootNode2 = createTestRootNode();
+        rootNode2.assignSourceSection(sourceSection2);
+        RootNode rootNode2Copy = NodeUtil.cloneNode(rootNode2);
+
+        assertSame(rootNode2.getSourceSection(), rootNode2Copy.getSourceSection());
+
+        RootCallTarget target1 = runtime.createCallTarget(rootNode1);
+        RootCallTarget target2 = runtime.createCallTarget(rootNode2);
+        RootCallTarget target2Copy = runtime.createCallTarget(rootNode2Copy);
+
+        Map<SourceSection, List<RootCallTarget>> groupedTargets = groupUniqueCallTargets();
+
+        List<RootCallTarget> targets1 = groupedTargets.get(sourceSection1);
+        assertEquals(1, targets1.size());
+        assertEquals(target1, targets1.get(0));
+
+        List<RootCallTarget> targets2 = groupedTargets.get(sourceSection2);
+        assertEquals(2, targets2.size());
+        // order of targets2 is not guaranteed
+        assertTrue(target2 == targets2.get(0) ^ target2Copy == targets2.get(0));
+        assertTrue(target2 == targets2.get(1) ^ target2Copy == targets2.get(1));
+    }
+
+    private static Map<SourceSection, List<RootCallTarget>> groupUniqueCallTargets() {
+        Map<SourceSection, List<RootCallTarget>> groupedTargets = new HashMap<>();
+        for (RootCallTarget target : Truffle.getRuntime().getCallTargets()) {
+            SourceSection section = target.getRootNode().getSourceSection();
+            if (section == null) {
+                // can not identify root node to a unique call target. Print warning?
+                continue;
+            }
+            List<RootCallTarget> targets = groupedTargets.get(section);
+            if (targets == null) {
+                targets = new ArrayList<>();
+                groupedTargets.put(section, targets);
+            }
+            targets.add(target);
+        }
+        return groupedTargets;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.instrument;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdvancedInstrumentCounterRoot;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode;
+
+/**
+ * Tests the kind of instrumentation where a client can provide an AST fragment to be
+ * <em>spliced</em> directly into the AST.
+ */
+public class AdvancedInstrumentTest {
+
+    @Test
+    public void testAdvancedInstrumentListener() {
+        // Create a simple addition AST
+        final TruffleRuntime runtime = Truffle.getRuntime();
+        final TestValueNode leftValueNode = new TestValueNode(6);
+        final TestValueNode rightValueNode = new TestValueNode(7);
+        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
+        final TestRootNode rootNode = new TestRootNode(addNode);
+        final CallTarget callTarget1 = runtime.createCallTarget(rootNode);
+
+        // Ensure it executes correctly
+        assertEquals(13, callTarget1.call());
+
+        // Probe the addition node
+        final Probe probe = addNode.probe();
+
+        assertEquals(13, callTarget1.call());
+
+        // Attach a null factory; it never actually attaches a node.
+        final Instrument instrument = Instrument.create(null, new AdvancedInstrumentRootFactory() {
+
+            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
+                return null;
+            }
+        }, null, "test AdvancedInstrument");
+        probe.attach(instrument);
+
+        assertEquals(13, callTarget1.call());
+
+        final TestAdvancedInstrumentCounterRoot counter = new TestAdvancedInstrumentCounterRoot();
+
+        // Attach a factory that splices an execution counter into the AST.
+        probe.attach(Instrument.create(null, new AdvancedInstrumentRootFactory() {
+
+            public AdvancedInstrumentRoot createInstrumentRoot(Probe p, Node n) {
+                return counter;
+            }
+        }, null, "test AdvancedInstrument"));
+        assertEquals(0, counter.getCount());
+
+        assertEquals(13, callTarget1.call());
+
+        assertEquals(1, counter.getCount());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.instrument;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeFailure.Reason;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestAdditionNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestLanguageWrapperNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestRootNode;
+import com.oracle.truffle.api.test.instrument.InstrumentationTestNodes.TestValueNode;
+
+/**
+ * <h3>AST Instrumentation</h3>
+ *
+ * Instrumentation allows the insertion into Truffle ASTs language-specific instances of
+ * {@link WrapperNode} that propagate execution events through a {@link Probe} to any instances of
+ * {@link Instrument} that might be attached to the particular probe by tools.
+ * <ol>
+ * <li>Creates a simple add AST</li>
+ * <li>Verifies its structure</li>
+ * <li>"Probes" the add node by adding a {@link WrapperNode} and associated {@link Probe}</li>
+ * <li>Attaches a simple {@link Instrument} to the node via the Probe's {@link ProbeNode}</li>
+ * <li>Verifies the structure of the probed AST</li>
+ * <li>Verifies the execution of the probed AST</li>
+ * <li>Verifies the results observed by the instrument.</li>
+ * </ol>
+ * To do these tests, several required classes have been implemented in their most basic form, only
+ * implementing the methods necessary for the tests to pass, with stubs elsewhere.
+ */
+public class InstrumentationTest {
+
+    private static final SyntaxTag ADD_TAG = new SyntaxTag() {
+
+        @Override
+        public String name() {
+            return "Addition";
+        }
+
+        @Override
+        public String getDescription() {
+            return "Test Language Addition Node";
+        }
+    };
+
+    private static final SyntaxTag VALUE_TAG = new SyntaxTag() {
+
+        @Override
+        public String name() {
+            return "Value";
+        }
+
+        @Override
+        public String getDescription() {
+            return "Test Language Value Node";
+        }
+    };
+
+    @Test
+    public void testInstrumentationStructure() {
+        // Create a simple addition AST
+        final TruffleRuntime runtime = Truffle.getRuntime();
+        final TestValueNode leftValueNode = new TestValueNode(6);
+        final TestValueNode rightValueNode = new TestValueNode(7);
+        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
+
+        try {
+            addNode.probe();
+        } catch (ProbeException e) {
+            assertEquals(e.getFailure().getReason(), Reason.NO_PARENT);
+        }
+        final TestRootNode rootNode = new TestRootNode(addNode);
+
+        // Creating a call target sets the parent pointers in this tree and is necessary prior to
+        // checking any parent/child relationships
+        final CallTarget callTarget1 = runtime.createCallTarget(rootNode);
+
+        // Check the tree structure
+        assertEquals(addNode, leftValueNode.getParent());
+        assertEquals(addNode, rightValueNode.getParent());
+        Iterator<Node> iterator = addNode.getChildren().iterator();
+        assertEquals(leftValueNode, iterator.next());
+        assertEquals(rightValueNode, iterator.next());
+        assertFalse(iterator.hasNext());
+        assertEquals(rootNode, addNode.getParent());
+        iterator = rootNode.getChildren().iterator();
+        assertEquals(addNode, iterator.next());
+        assertFalse(iterator.hasNext());
+
+        // Ensure it executes correctly
+        assertEquals(13, callTarget1.call());
+
+        // Probe the addition node
+        addNode.probe();
+
+        // Check the modified tree structure
+        assertEquals(addNode, leftValueNode.getParent());
+        assertEquals(addNode, rightValueNode.getParent());
+        iterator = addNode.getChildren().iterator();
+        assertEquals(leftValueNode, iterator.next());
+        assertEquals(rightValueNode, iterator.next());
+        assertFalse(iterator.hasNext());
+
+        // Ensure there's a WrapperNode correctly inserted into the AST
+        iterator = rootNode.getChildren().iterator();
+        Node wrapperNode = iterator.next();
+        assertTrue(wrapperNode instanceof TestLanguageWrapperNode);
+        assertFalse(iterator.hasNext());
+        assertEquals(rootNode, wrapperNode.getParent());
+
+        // Check that the WrapperNode has both the probe and the wrapped node as children
+        iterator = wrapperNode.getChildren().iterator();
+        assertEquals(addNode, iterator.next());
+        ProbeNode probeNode = (ProbeNode) iterator.next();
+        assertTrue(probeNode.getProbe() != null);
+        assertFalse(iterator.hasNext());
+
+        // Check that you can't probe the WrapperNodes
+        TestLanguageWrapperNode wrapper = (TestLanguageWrapperNode) wrapperNode;
+        try {
+            wrapper.probe();
+            fail();
+        } catch (ProbeException e) {
+            assertEquals(e.getFailure().getReason(), Reason.WRAPPER_NODE);
+        }
+
+        // Check that the "probed" AST still executes correctly
+        assertEquals(13, callTarget1.call());
+    }
+
+    @Test
+    public void testListeners() {
+
+        // Create a simple addition AST
+        final TruffleRuntime runtime = Truffle.getRuntime();
+        final TestValueNode leftValueNode = new TestValueNode(6);
+        final TestValueNode rightValueNode = new TestValueNode(7);
+        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
+        final TestRootNode rootNode = new TestRootNode(addNode);
+
+        // Creating a call target sets the parent pointers in this tree and is necessary prior to
+        // checking any parent/child relationships
+        final CallTarget callTarget = runtime.createCallTarget(rootNode);
+        // Probe the addition node
+        final Probe probe = addNode.probe();
+
+        // Check instrumentation with the simplest kind of counters.
+        // They should all be removed when the check is finished.
+        checkCounters(probe, callTarget, rootNode, new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter(), new TestSimpleInstrumentCounter());
+
+        // Now try with the more complex flavor of listener
+        checkCounters(probe, callTarget, rootNode, new TestStandardInstrumentCounter(), new TestStandardInstrumentCounter(), new TestStandardInstrumentCounter());
+    }
+
+    private static void checkCounters(Probe probe, CallTarget callTarget, RootNode rootNode, TestCounter counterA, TestCounter counterB, TestCounter counterC) {
+
+        // Attach a counting instrument to the probe
+        counterA.attach(probe);
+
+        // Attach a second counting instrument to the probe
+        counterB.attach(probe);
+
+        // Run it again and check that the two instruments are working
+        assertEquals(13, callTarget.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 1);
+        assertEquals(counterB.leaveCount(), 1);
+
+        // Remove counterA
+        counterA.dispose();
+
+        // Run it again and check that instrument B is still working but not A
+        assertEquals(13, callTarget.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 2);
+        assertEquals(counterB.leaveCount(), 2);
+
+        // Simulate a split by cloning the AST
+        final CallTarget callTarget2 = Truffle.getRuntime().createCallTarget((TestRootNode) rootNode.copy());
+        // Run the clone and check that instrument B is still working but not A
+        assertEquals(13, callTarget2.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 3);
+        assertEquals(counterB.leaveCount(), 3);
+
+        // Run the original and check that instrument B is still working but not A
+        assertEquals(13, callTarget2.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 4);
+        assertEquals(counterB.leaveCount(), 4);
+
+        // Attach a second instrument to the probe
+        counterC.attach(probe);
+
+        // Run the original and check that instruments B,C working but not A
+        assertEquals(13, callTarget.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 5);
+        assertEquals(counterB.leaveCount(), 5);
+        assertEquals(counterC.enterCount(), 1);
+        assertEquals(counterC.leaveCount(), 1);
+
+        // Run the clone and check that instruments B,C working but not A
+        assertEquals(13, callTarget2.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 6);
+        assertEquals(counterB.leaveCount(), 6);
+        assertEquals(counterC.enterCount(), 2);
+        assertEquals(counterC.leaveCount(), 2);
+
+        // Remove instrumentC
+        counterC.dispose();
+
+        // Run the original and check that instrument B working but not A,C
+        assertEquals(13, callTarget.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 7);
+        assertEquals(counterB.leaveCount(), 7);
+        assertEquals(counterC.enterCount(), 2);
+        assertEquals(counterC.leaveCount(), 2);
+
+        // Run the clone and check that instrument B working but not A,C
+        assertEquals(13, callTarget2.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 8);
+        assertEquals(counterB.leaveCount(), 8);
+        assertEquals(counterC.enterCount(), 2);
+        assertEquals(counterC.leaveCount(), 2);
+
+        // Remove instrumentB
+        counterB.dispose();
+
+        // Run both the original and clone, check that no instruments working
+        assertEquals(13, callTarget.call());
+        assertEquals(13, callTarget2.call());
+        assertEquals(counterA.enterCount(), 1);
+        assertEquals(counterA.leaveCount(), 1);
+        assertEquals(counterB.enterCount(), 8);
+        assertEquals(counterB.leaveCount(), 8);
+        assertEquals(counterC.enterCount(), 2);
+        assertEquals(counterC.leaveCount(), 2);
+    }
+
+    @Test
+    public void testTagging() {
+        // Applies appropriate tags
+        final TestASTProber astProber = new TestASTProber();
+        Probe.registerASTProber(astProber);
+
+        // Listens for probes and tags being added
+        final TestProbeListener probeListener = new TestProbeListener();
+        Probe.addProbeListener(probeListener);
+
+        // Counts all entries to all instances of addition nodes
+        final TestMultiCounter additionCounter = new TestMultiCounter();
+
+        // Counts all entries to all instances of value nodes
+        final TestMultiCounter valueCounter = new TestMultiCounter();
+
+        // Create a simple addition AST
+        final TruffleRuntime runtime = Truffle.getRuntime();
+        final TestValueNode leftValueNode = new TestValueNode(6);
+        final TestValueNode rightValueNode = new TestValueNode(7);
+        final TestAdditionNode addNode = new TestAdditionNode(leftValueNode, rightValueNode);
+
+        final TestRootNode rootNode = new TestRootNode(addNode);
+
+        final CallTarget callTarget = runtime.createCallTarget(rootNode);
+
+        // Check that the prober added probes to the tree
+        assertEquals(probeListener.probeCount, 3);
+        assertEquals(probeListener.tagCount, 3);
+
+        assertEquals(Probe.findProbesTaggedAs(ADD_TAG).size(), 1);
+        assertEquals(Probe.findProbesTaggedAs(VALUE_TAG).size(), 2);
+
+        // Check that it executes correctly
+        assertEquals(13, callTarget.call());
+
+        // Dynamically attach a counter for all executions of all Addition nodes
+        for (Probe probe : Probe.findProbesTaggedAs(ADD_TAG)) {
+            additionCounter.attachCounter(probe);
+        }
+        // Dynamically attach a counter for all executions of all Value nodes
+        for (Probe probe : Probe.findProbesTaggedAs(VALUE_TAG)) {
+            valueCounter.attachCounter(probe);
+        }
+
+        // Counters initialized at 0
+        assertEquals(additionCounter.count, 0);
+        assertEquals(valueCounter.count, 0);
+
+        // Execute again
+        assertEquals(13, callTarget.call());
+
+        // There are two value nodes in the AST, but only one addition node
+        assertEquals(additionCounter.count, 1);
+        assertEquals(valueCounter.count, 2);
+
+        Probe.unregisterASTProber(astProber);
+    }
+
+    private interface TestCounter {
+
+        int enterCount();
+
+        int leaveCount();
+
+        void attach(Probe probe);
+
+        void dispose();
+    }
+
+    /**
+     * A counter for the number of times execution enters and leaves a probed AST node.
+     */
+    private class TestSimpleInstrumentCounter implements TestCounter {
+
+        public int enterCount = 0;
+        public int leaveCount = 0;
+        public final Instrument instrument;
+
+        public TestSimpleInstrumentCounter() {
+            this.instrument = Instrument.create(new SimpleInstrumentListener() {
+
+                public void enter(Probe probe) {
+                    enterCount++;
+                }
+
+                public void returnVoid(Probe probe) {
+                    leaveCount++;
+                }
+
+                public void returnValue(Probe probe, Object result) {
+                    leaveCount++;
+                }
+
+                public void returnExceptional(Probe probe, Exception exception) {
+                    leaveCount++;
+                }
+
+            }, "Instrumentation Test Counter");
+        }
+
+        @Override
+        public int enterCount() {
+            return enterCount;
+        }
+
+        @Override
+        public int leaveCount() {
+            return leaveCount;
+        }
+
+        @Override
+        public void attach(Probe probe) {
+            probe.attach(instrument);
+        }
+
+        @Override
+        public void dispose() {
+            instrument.dispose();
+        }
+    }
+
+    /**
+     * A counter for the number of times execution enters and leaves a probed AST node.
+     */
+    private class TestStandardInstrumentCounter implements TestCounter {
+
+        public int enterCount = 0;
+        public int leaveCount = 0;
+        public final Instrument instrument;
+
+        public TestStandardInstrumentCounter() {
+            this.instrument = Instrument.create(new StandardInstrumentListener() {
+
+                public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+                    enterCount++;
+                }
+
+                public void returnVoid(Probe probe, Node node, VirtualFrame vFrame) {
+                    leaveCount++;
+                }
+
+                public void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) {
+                    leaveCount++;
+                }
+
+                public void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+                    leaveCount++;
+                }
+
+            }, "Instrumentation Test Counter");
+        }
+
+        @Override
+        public int enterCount() {
+            return enterCount;
+        }
+
+        @Override
+        public int leaveCount() {
+            return leaveCount;
+        }
+
+        @Override
+        public void attach(Probe probe) {
+            probe.attach(instrument);
+        }
+
+        @Override
+        public void dispose() {
+            instrument.dispose();
+        }
+    }
+
+    /**
+     * Tags selected nodes on newly constructed ASTs.
+     */
+    private static final class TestASTProber implements NodeVisitor, ASTProber {
+
+        @Override
+        public boolean visit(Node node) {
+            if (node instanceof TestLanguageNode) {
+
+                final TestLanguageNode testNode = (TestLanguageNode) node;
+
+                if (node instanceof TestValueNode) {
+                    testNode.probe().tagAs(VALUE_TAG, null);
+
+                } else if (node instanceof TestAdditionNode) {
+                    testNode.probe().tagAs(ADD_TAG, null);
+
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public void probeAST(Node node) {
+            node.accept(this);
+        }
+    }
+
+    /**
+     * Counts the number of "enter" events at probed nodes using the simplest AST listener.
+     */
+    static final class TestSimpleInstrumentListener extends DefaultSimpleInstrumentListener {
+
+        public int counter = 0;
+
+        @Override
+        public void enter(Probe probe) {
+            counter++;
+        }
+    }
+
+    /**
+     * Counts the number of "enter" events at probed nodes using the AST listener.
+     */
+    static final class TestASTInstrumentListener extends DefaultStandardInstrumentListener {
+
+        public int counter = 0;
+
+        @Override
+        public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+            counter++;
+        }
+    }
+
+    /**
+     * A counter that can count executions at multiple nodes; it attaches a separate instrument at
+     * each Probe, but keeps a total count.
+     */
+    private static final class TestMultiCounter {
+
+        public int count = 0;
+
+        public void attachCounter(Probe probe) {
+
+            // Attach a new instrument for every Probe
+            // where we want to count executions.
+            // it will get copied when ASTs cloned, so
+            // keep the count in this outer class.
+            probe.attach(Instrument.create(new DefaultSimpleInstrumentListener() {
+
+                @Override
+                public void enter(Probe p) {
+                    count++;
+                }
+            }, "Instrumentation Test MultiCounter"));
+        }
+    }
+
+    private static final class TestProbeListener extends DefaultProbeListener {
+
+        public int probeCount = 0;
+        public int tagCount = 0;
+
+        @Override
+        public void newProbeInserted(Probe probe) {
+            probeCount++;
+        }
+
+        @Override
+        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+            tagCount++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/InstrumentationTestNodes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Tests instrumentation where a client can attach a node that gets attached into the AST.
+ */
+class InstrumentationTestNodes {
+
+    abstract static class TestLanguageNode extends Node {
+        public abstract Object execute(VirtualFrame vFrame);
+
+        @Override
+        public boolean isInstrumentable() {
+            return true;
+        }
+
+        @Override
+        public WrapperNode createWrapperNode() {
+            return new TestLanguageWrapperNode(this);
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    static class TestLanguageWrapperNode extends TestLanguageNode implements WrapperNode {
+        @Child private TestLanguageNode child;
+        @Child private ProbeNode probeNode;
+
+        public TestLanguageWrapperNode(TestLanguageNode child) {
+            assert !(child instanceof TestLanguageWrapperNode);
+            this.child = child;
+        }
+
+        @Override
+        public String instrumentationInfo() {
+            return "Wrapper node for testing";
+        }
+
+        @Override
+        public boolean isInstrumentable() {
+            return false;
+        }
+
+        @Override
+        public void insertProbe(ProbeNode newProbeNode) {
+            this.probeNode = newProbeNode;
+        }
+
+        @Override
+        public Probe getProbe() {
+            return probeNode.getProbe();
+        }
+
+        @Override
+        public Node getChild() {
+            return child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame vFrame) {
+            probeNode.enter(child, vFrame);
+            Object result;
+            try {
+                result = child.execute(vFrame);
+                probeNode.returnValue(child, vFrame, result);
+            } catch (KillException e) {
+                throw (e);
+            } catch (Exception e) {
+                probeNode.returnExceptional(child, vFrame, e);
+                throw (e);
+            }
+            return result;
+        }
+    }
+
+    /**
+     * A simple node for our test language to store a value.
+     */
+    static class TestValueNode extends TestLanguageNode {
+        private final int value;
+
+        public TestValueNode(int value) {
+            this.value = value;
+        }
+
+        @Override
+        public Object execute(VirtualFrame vFrame) {
+            return new Integer(this.value);
+        }
+    }
+
+    /**
+     * A node for our test language that adds up two {@link TestValueNode}s.
+     */
+    static class TestAdditionNode extends TestLanguageNode {
+        @Child private TestLanguageNode leftChild;
+        @Child private TestLanguageNode rightChild;
+
+        public TestAdditionNode(TestValueNode leftChild, TestValueNode rightChild) {
+            this.leftChild = insert(leftChild);
+            this.rightChild = insert(rightChild);
+        }
+
+        @Override
+        public Object execute(VirtualFrame vFrame) {
+            return new Integer(((Integer) leftChild.execute(vFrame)).intValue() + ((Integer) rightChild.execute(vFrame)).intValue());
+        }
+    }
+
+    /**
+     * Truffle requires that all guest languages to have a {@link RootNode} which sits atop any AST
+     * of the guest language. This is necessary since creating a {@link CallTarget} is how Truffle
+     * completes an AST. The root nodes serves as our entry point into a program.
+     */
+    static class TestRootNode extends RootNode {
+        @Child private TestLanguageNode body;
+
+        /**
+         * This constructor emulates the global machinery that applies registered probers to every
+         * newly created AST. Global registry is not used, since that would interfere with other
+         * tests run in the same environment.
+         */
+        public TestRootNode(TestLanguageNode body) {
+            super(null);
+            this.body = body;
+        }
+
+        @Override
+        public Object execute(VirtualFrame vFrame) {
+            return body.execute(vFrame);
+        }
+
+        @Override
+        public boolean isCloningAllowed() {
+            return true;
+        }
+
+        @Override
+        public void applyInstrumentation() {
+            Probe.applyASTProbers(body);
+        }
+    }
+
+    static class TestAdvancedInstrumentCounterRoot extends AdvancedInstrumentRoot {
+
+        private long count;
+
+        @Override
+        public Object executeRoot(Node node, VirtualFrame vFrame) {
+            count++;
+            return null;
+        }
+
+        public long getCount() {
+            return count;
+        }
+
+        public String instrumentationInfo() {
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/NodeUtilTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class NodeUtilTest {
+
+    @Test
+    public void testRecursiveIterator1() {
+        TestRootNode root = new TestRootNode();
+        root.child0 = new TestNode();
+        root.adoptChildren();
+
+        int count = iterate(NodeUtil.makeRecursiveIterator(root));
+
+        assertThat(count, is(2));
+        assertThat(root.visited, is(0));
+        assertThat(root.child0.visited, is(1));
+    }
+
+    private static int iterate(Iterator<Node> iterator) {
+        int iterationCount = 0;
+        while (iterator.hasNext()) {
+            Node node = iterator.next();
+            if (node == null) {
+                continue;
+            }
+            if (node instanceof TestNode) {
+                ((TestNode) node).visited = iterationCount;
+            } else if (node instanceof TestRootNode) {
+                ((TestRootNode) node).visited = iterationCount;
+            } else {
+                throw new AssertionError();
+            }
+            iterationCount++;
+        }
+        return iterationCount;
+    }
+
+    private static class TestNode extends Node {
+
+        @Child TestNode child0;
+        @Child TestNode child1;
+
+        private int visited;
+
+        public TestNode() {
+        }
+
+    }
+
+    private static class TestRootNode extends RootNode {
+
+        @Child TestNode child0;
+
+        private int visited;
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return null;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/SafeReplaceTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Tests optional method for ensuring that a node replacement is type safe. Ordinary node
+ * replacement is performed by unsafe assignment of a parent node's child field.
+ */
+public class SafeReplaceTest {
+
+    @Test
+    public void testCorrectReplacement() {
+        TestRootNode root = new TestRootNode();
+        final TestNode oldChild = new TestNode();
+        final TestNode newChild = new TestNode();
+        root.child = oldChild;
+        assertFalse(oldChild.isSafelyReplaceableBy(newChild));  // No parent node
+        root.adoptChildren();
+        assertTrue(oldChild.isSafelyReplaceableBy(newChild));   // Now adopted by parent
+        // new node
+        oldChild.replace(newChild);
+        root.execute(null);
+        assertEquals(root.executed, 1);
+        assertEquals(oldChild.executed, 0);
+        assertEquals(newChild.executed, 1);
+    }
+
+    @Test
+    public void testIncorrectReplacement() {
+        TestRootNode root = new TestRootNode();
+        final TestNode oldChild = new TestNode();
+        root.child = oldChild;
+        root.adoptChildren();
+        final TestNode newChild = new TestNode();
+        final TestNode strayChild = new TestNode();
+        assertFalse(strayChild.isSafelyReplaceableBy(newChild)); // Stray not a child of parent
+        final WrongTestNode wrongTypeNewChild = new WrongTestNode();
+        assertFalse(oldChild.isSafelyReplaceableBy(wrongTypeNewChild));
+    }
+
+    private static class TestNode extends Node {
+
+        private int executed;
+
+        public Object execute() {
+            executed++;
+            return null;
+        }
+    }
+
+    private static class TestRootNode extends RootNode {
+
+        @Child TestNode child;
+
+        private int executed;
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            executed++;
+            child.execute();
+            return null;
+        }
+    }
+
+    private static class WrongTestNode extends Node {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderDeserializerTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes.serial;
+
+import java.nio.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.serial.*;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithOneChild;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoChilds;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode;
+
+public class PostOrderDeserializerTest {
+
+    private PostOrderDeserializer d;
+    private TestSerializerConstantPool cp;
+
+    @Before
+    public void setUp() {
+        cp = new TestSerializerConstantPool();
+        d = new PostOrderDeserializer(cp);
+    }
+
+    @After
+    public void tearDown() {
+        d = null;
+        cp = null;
+    }
+
+    private Node deserialize(byte[] bytes) {
+        return d.deserialize(bytes, Node.class);
+    }
+
+    @Test
+    public void testNull() {
+        createCP();
+        Node ast = deserialize(createBytes(VariableLengthIntBuffer.NULL));
+        Assert.assertNull(ast);
+    }
+
+    @Test
+    public void testSingleNode() {
+        createCP(EmptyNode.class);
+        Node expectedAst = new EmptyNode();
+        Node ast = deserialize(createBytes(0));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testThreeChilds() {
+        createCP(EmptyNode.class, NodeWithThreeChilds.class);
+        Node expectedAst = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode());
+        Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 0, 1));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testFields() {
+        createCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
+                        (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1);
+        NodeWithFields expectedAst = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE,
+                        Double.MAX_VALUE, Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE);
+        Node ast = deserialize(createBytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testFieldsNull() {
+        createCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D);
+        NodeWithFields expectedAst = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null);
+        int nil = VariableLengthIntBuffer.NULL;
+        Node ast = deserialize(createBytes(0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testNullChilds() {
+        createCP(Node[].class, NodeWithArray.class);
+        Node expectedAst = new NodeWithArray(null);
+        Node ast = deserialize(createBytes(0, VariableLengthIntBuffer.NULL, 1));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testNChilds() {
+        Node expectedAst = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()});
+        createCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class);
+        Node ast = deserialize(createBytes(0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4));
+
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void test2xNChilds() {
+        Node expectedAst = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")});
+        createCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class);
+        Node ast = deserialize(createBytes(0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9));
+
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testBug0() {
+        Node expectedAst = new NodeWithArray(new Node[]{new NodeWithOneChild(new EmptyNode())});
+
+        createCP(Node[].class, 1, EmptyNode.class, NodeWithOneChild.class, NodeWithArray.class);
+        Node ast = deserialize(createBytes(0, 1, 2, 3, 4));
+        assertAST(expectedAst, ast);
+    }
+
+    @Test
+    public void testBug1() {
+        Node expectedAst = new NodeWithArray(new Node[]{new NodeWithTwoChilds(new EmptyNode(), new EmptyNode())});
+
+        createCP(Node[].class, 1, EmptyNode.class, NodeWithTwoChilds.class, NodeWithArray.class);
+        Node ast = deserialize(createBytes(0, 1, 2, 2, 3, 4));
+        assertAST(expectedAst, ast);
+    }
+
+    private static void assertAST(Node expectedAst, Node actualAst) {
+        if (expectedAst == null) {
+            Assert.assertNull(actualAst);
+            return;
+        }
+
+        expectedAst.adoptChildren();
+
+        Assert.assertNotNull(actualAst);
+        // fields are asserted using the corresponding equals implementation
+        Assert.assertEquals(expectedAst, actualAst);
+
+        Iterable<Node> expectedChildIterator = expectedAst.getChildren();
+        Iterator<Node> actualChildIterator = actualAst.getChildren().iterator();
+        for (Node node : expectedChildIterator) {
+            Assert.assertTrue(actualChildIterator.hasNext());
+            assertAST(node, actualChildIterator.next());
+        }
+        Assert.assertFalse(actualChildIterator.hasNext());
+    }
+
+    private static byte[] createBytes(int... refs) {
+        VariableLengthIntBuffer buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
+        for (int i = 0; i < refs.length; i++) {
+            buf.put(refs[i]);
+        }
+        return buf.getBytes();
+    }
+
+    private void createCP(Object... cpData) {
+        for (int i = 0; i < cpData.length; i++) {
+            Object object = cpData[i];
+
+            cp.putObject(object.getClass(), object);
+
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/PostOrderSerializerTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes.serial;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.serial.*;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.EmptyNode;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithArray;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithFields;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithThreeChilds;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.NodeWithTwoArray;
+import com.oracle.truffle.api.test.nodes.serial.TestNodes.StringNode;
+
+public class PostOrderSerializerTest {
+
+    private PostOrderSerializer s;
+    private TestSerializerConstantPool cp;
+
+    @Before
+    public void setUp() {
+        cp = new TestSerializerConstantPool();
+        s = new PostOrderSerializer(cp);
+    }
+
+    @After
+    public void tearDown() {
+        cp = null;
+        s = null;
+    }
+
+    @Test
+    public void testNull() {
+        Node ast = null;
+        assertBytes(s.serialize(ast), VariableLengthIntBuffer.NULL);
+        assertCP();
+    }
+
+    @Test
+    public void testSingleEmptyNode() {
+        Node ast = new EmptyNode();
+        assertBytes(s.serialize(ast), 0);
+        assertCP(EmptyNode.class);
+    }
+
+    @Test
+    public void testThreeChilds() {
+        Node ast = new NodeWithThreeChilds(new EmptyNode(), null, new EmptyNode());
+        assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 0, 1);
+        assertCP(EmptyNode.class, NodeWithThreeChilds.class);
+    }
+
+    @Test
+    public void testFields() {
+        NodeWithFields ast = new NodeWithFields("test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
+                        Character.MIN_VALUE, Character.MAX_VALUE, Short.MIN_VALUE, Short.MAX_VALUE, Byte.MIN_VALUE, Byte.MAX_VALUE, Boolean.TRUE, Boolean.FALSE);
+        assertBytes(s.serialize(ast), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10);
+        assertCP(NodeWithFields.class, "test", Integer.MIN_VALUE, Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE,
+                        (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, (int) Short.MIN_VALUE, (int) Short.MAX_VALUE, (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 1);
+    }
+
+    @Test
+    public void testFieldsNull() {
+        NodeWithFields ast = new NodeWithFields("test", 0, null, 0L, null, 0f, null, 0d, null, (char) 0, null, (short) 0, null, (byte) 0, null, false, null);
+        int nil = VariableLengthIntBuffer.NULL;
+        assertBytes(s.serialize(ast), 0, 1, 2, nil, 3, nil, 4, nil, 5, nil, 2, nil, 2, nil, 2, nil, 2, nil);
+        assertCP(NodeWithFields.class, "test", 0, 0L, 0.0F, 0.0D);
+    }
+
+    @Test
+    public void testNChilds() {
+        Node ast = new NodeWithArray(new Node[]{new EmptyNode(), new NodeWithArray(new Node[]{new EmptyNode(), new EmptyNode(), new EmptyNode()}), new EmptyNode(), new EmptyNode()});
+        assertBytes(s.serialize(ast), 0, 1, 2, 0, 3, 2, 2, 2, 4, 2, 2, 4);
+        assertCP(Node[].class, 4, EmptyNode.class, 3, NodeWithArray.class);
+    }
+
+    @Test
+    public void testNullChilds() {
+        Node ast = new NodeWithArray(null);
+        assertBytes(s.serialize(ast), 0, VariableLengthIntBuffer.NULL, 1);
+        assertCP(Node[].class, NodeWithArray.class);
+    }
+
+    @Test
+    public void test2xNChilds() {
+        Node ast = new NodeWithTwoArray(new Node[]{new StringNode("a0"), new StringNode("a1")}, new Node[]{new StringNode("b0"), new StringNode("b1"), new StringNode("b2")});
+        assertBytes(s.serialize(ast), 0, 1, 2, 3, 2, 4, 0, 5, 2, 6, 2, 7, 2, 8, 9);
+        assertCP(Node[].class, 2, StringNode.class, "a0", "a1", 3, "b0", "b1", "b2", NodeWithTwoArray.class);
+    }
+
+    private static void assertBytes(byte[] actualBytes, int... expectedIndexes) {
+        VariableLengthIntBuffer buf = new VariableLengthIntBuffer(actualBytes);
+        for (int i = 0; i < expectedIndexes.length; i++) {
+            Assert.assertTrue("Unexpected EOF " + i, buf.hasRemaining());
+            Assert.assertEquals("Index at pos " + i + ".", expectedIndexes[i], buf.get());
+        }
+        Assert.assertFalse(buf.hasRemaining());
+    }
+
+    private void assertCP(Object... object) {
+        for (int i = 0; i < object.length; i++) {
+            Object cpvalue = object[i];
+            Assert.assertNotNull("CP at index " + i, cpvalue);
+            Assert.assertEquals("CP at index " + i, cpvalue, cp.getObject(cpvalue.getClass(), i));
+        }
+        Assert.assertEquals(object.length, cp.getIndex());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestNodes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes.serial;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+final class TestNodes {
+
+    private TestNodes() {
+    }
+
+    static class StringNode extends Node {
+
+        private final String name;
+
+        public StringNode(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(name);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            } else if (obj.getClass() != getClass()) {
+                return false;
+            } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) {
+                return false;
+            } else if (!Objects.equals(name, ((StringNode) obj).name)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    static class EmptyNode extends Node {
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) {
+                return false;
+            } else if (obj.getClass() != getClass()) {
+                return false;
+            } else if ((((Node) obj).getParent() != null) && !((Node) obj).getParent().equals(getParent())) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    static class NodeWithOneChild extends EmptyNode {
+
+        @Child Node child;
+
+        public NodeWithOneChild(Node child) {
+            this.child = child;
+        }
+
+    }
+
+    static class NodeWithTwoChilds extends EmptyNode {
+
+        @Child Node child1;
+        @Child Node child2;
+
+        public NodeWithTwoChilds(Node child1, Node child2) {
+            this.child1 = child1;
+            this.child2 = child2;
+        }
+
+    }
+
+    static class NodeWithThreeChilds extends EmptyNode {
+
+        @Child Node child1;
+        @Child Node child2;
+        @Child Node child3;
+
+        public NodeWithThreeChilds(Node child1, Node child2, Node child3) {
+            this.child1 = child1;
+            this.child2 = child2;
+            this.child3 = child3;
+        }
+
+    }
+
+    static class NodeWithArray extends EmptyNode {
+
+        @Children private final Node[] childNodes;
+
+        NodeWithArray(Node[] children) {
+            this.childNodes = children;
+        }
+
+        Node[] getChildNodes() {
+            return childNodes;
+        }
+    }
+
+    static class NodeWithTwoArray extends EmptyNode {
+
+        @Children private final Node[] childNodes1;
+        @Children private final Node[] childNodes2;
+
+        NodeWithTwoArray(Node[] childs1, Node[] childs2) {
+            this.childNodes1 = childs1;
+            this.childNodes2 = childs2;
+        }
+
+        Node[] getChildNodes1() {
+            return childNodes1;
+        }
+
+        Node[] getChildNodes2() {
+            return childNodes2;
+        }
+    }
+
+    static class NodeWithFields extends EmptyNode {
+
+        String stringField;
+        int integerField;
+        Integer integerObjectField;
+        long longField;
+        Long longObjectField;
+        float floatField;
+        Float floatObjectField;
+        double doubleField;
+        Double doubleObjectField;
+        char charField;
+        Character charObjectField;
+        short shortField;
+        Short shortObjecField;
+        byte byteField;
+        Byte byteObjectField;
+        boolean booleanField;
+        Boolean booleanObjectfield;
+
+        public NodeWithFields(String stringField, int integerField, Integer integerObjectField, long longField, Long longObjectField, float floatField, Float floatObjectField, double doubleField,
+                        Double doubleObjectField, char charField, Character charObjectField, short shortField, Short shortObjecField, byte byteField, Byte byteObjectField, boolean booleanField,
+                        Boolean booleanObjectfield) {
+            this.stringField = stringField;
+            this.integerField = integerField;
+            this.integerObjectField = integerObjectField;
+            this.longField = longField;
+            this.longObjectField = longObjectField;
+            this.floatField = floatField;
+            this.floatObjectField = floatObjectField;
+            this.doubleField = doubleField;
+            this.doubleObjectField = doubleObjectField;
+            this.charField = charField;
+            this.charObjectField = charObjectField;
+            this.shortField = shortField;
+            this.shortObjecField = shortObjecField;
+            this.byteField = byteField;
+            this.byteObjectField = byteObjectField;
+            this.booleanField = booleanField;
+            this.booleanObjectfield = booleanObjectfield;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField,
+                            shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj.getClass() != getClass()) {
+                return false;
+            }
+            NodeWithFields o = (NodeWithFields) obj;
+            return Objects.deepEquals(fieldArray(), o.fieldArray());
+        }
+
+        private Object[] fieldArray() {
+            return array(stringField, integerField, integerObjectField, longField, longObjectField, floatField, floatObjectField, doubleField, doubleObjectField, charField, charObjectField,
+                            shortField, shortObjecField, byteField, byteObjectField, booleanField, booleanObjectfield);
+        }
+
+        private static Object[] array(Object... values) {
+            return values;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/TestSerializerConstantPool.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes.serial;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.serial.*;
+
+class TestSerializerConstantPool implements SerializerConstantPool {
+
+    private final Map<Integer, Object> int2object = new HashMap<>();
+    private final Map<Object, Integer> object2int = new HashMap<>();
+
+    private int index;
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    @Override
+    public double getDouble(int cpi) {
+        return (Double) int2object.get(cpi);
+    }
+
+    @Override
+    public float getFloat(int cpi) {
+        return (Float) int2object.get(cpi);
+    }
+
+    @Override
+    public Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException {
+        return int2object.get(cpi);
+    }
+
+    @Override
+    public int putDouble(double value) {
+        return put(value);
+    }
+
+    public int putFloat(float value) {
+        return put(value);
+    }
+
+    public int putObject(java.lang.Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException {
+        return put(value);
+    }
+
+    @Override
+    public int putClass(Class<?> clazz) {
+        return put(clazz);
+    }
+
+    private int put(Object o) {
+        Integer currentIndex = object2int.get(o);
+        if (currentIndex == null) {
+            int2object.put(index, o);
+            object2int.put(o, index);
+            return index++;
+        } else {
+            return currentIndex;
+        }
+    }
+
+    @Override
+    public Class<?> getClass(int idx) {
+        return (Class<?>) int2object.get(idx);
+    }
+
+    @Override
+    public int putInt(int constant) {
+        return put(constant);
+    }
+
+    @Override
+    public int getInt(int idx) {
+        return (Integer) int2object.get(idx);
+    }
+
+    @Override
+    public long getLong(int idx) {
+        return (Long) int2object.get(idx);
+    }
+
+    @Override
+    public int putLong(long value) {
+        return put(value);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/nodes/serial/VariableLengthIntBufferTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.nodes.serial;
+
+import java.nio.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.serial.*;
+
+public class VariableLengthIntBufferTest {
+
+    private VariableLengthIntBuffer buf;
+
+    @Before
+    public void setUp() {
+        buf = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
+    }
+
+    @After
+    public void tearDown() {
+        buf = null;
+    }
+
+    @Test
+    public void testPutNull() {
+        buf.put(VariableLengthIntBuffer.NULL);
+        assertBytes(0xFF);
+    }
+
+    @Test
+    public void testPutByteCornerCase0() {
+        buf.put(0x00); // 0
+        assertBytes(0x00);
+    }
+
+    @Test
+    public void testPutByteCornerCase1() {
+        buf.put(0x7F); // 127
+        assertBytes(0x7F);
+    }
+
+    @Test
+    public void testPutByteCornerCase2() {
+        buf.put(0x3FFF_FFFF);
+        assertBytes(0xBF, 0xFF, 0xFF, 0xFF);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPutByteCornerCase3() {
+        buf.put(0x4000_0000); // out of encodeable
+    }
+
+    @Test
+    public void testGetNull() {
+        create(0xFF);
+        assertGet(VariableLengthIntBuffer.NULL);
+    }
+
+    @Test
+    public void testGetCornerCase0() {
+        create(0x00);
+        assertGet(0x00);
+    }
+
+    @Test
+    public void testGetCornerCase1() {
+        create(0x7F);
+        assertGet(0x7F);
+    }
+
+    @Test
+    public void testGetCornerCase2() {
+        create(0xBF, 0xFF, 0xFF, 0xFF);
+        assertGet(0x3FFF_FFFF);
+    }
+
+    @Test(expected = AssertionError.class)
+    public void testGetCornerCase3() {
+        create(0xFF, 0xFF, 0xFF, 0xFF);
+        assertGet(0x0);
+    }
+
+    private void create(int... bytes) {
+        byte[] convBytes = new byte[bytes.length];
+        for (int i = 0; i < bytes.length; i++) {
+            convBytes[i] = (byte) bytes[i];
+        }
+        buf = new VariableLengthIntBuffer(convBytes);
+    }
+
+    private void assertGet(int expected) {
+        Assert.assertEquals(expected, buf.get());
+    }
+
+    private void assertBytes(int... expectedBytes) {
+        byte[] actualBytes = buf.getBytes();
+        Assert.assertEquals(expectedBytes.length, actualBytes.length);
+        for (int i = 0; i < expectedBytes.length; i++) {
+            Assert.assertTrue(actualBytes[i] == (byte) expectedBytes[i]);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/package-info.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * <p>This package contains basic tests of the Truffle API and serves at the same
+ * time as an introduction to the Truffle API for language implementors. Every test gives an example on how to use the construct explained in the class description.</p>
+ *
+ * <p>
+ * Truffle is a language implementation framework. A guest language method is represented as a tree of executable nodes.
+ * The framework provides mechanisms for those trees to call each other. Additionally it contains dedicated data structures for storing data local to a tree invocation.
+ * </p>
+ *
+ * <p>
+ * This introduction to Truffle contains items in the following recommended order:
+ *
+ * <ul>
+ * <li>How to get access to the Truffle runtime? {@link com.oracle.truffle.api.test.TruffleRuntimeTest}</li>
+ * <li>How to create a root node? {@link com.oracle.truffle.api.test.RootNodeTest}</li>
+ * <li>How to create a child node and link it with its parent? {@link com.oracle.truffle.api.test.ChildNodeTest}</li>
+ * <li>How to create an array of child nodes? {@link com.oracle.truffle.api.test.ChildrenNodesTest}</li>
+ * <li>Why are final fields in node classes important? {@link com.oracle.truffle.api.test.FinalFieldTest}</li>
+ * <li>How to replace one node with another node and what for? {@link com.oracle.truffle.api.test.ReplaceTest}</li>
+ * <li>How to let one Truffle tree invoke another one? {@link com.oracle.truffle.api.test.CallTest}</li>
+ * <li>How to pass arguments when executing a tree? {@link com.oracle.truffle.api.test.ArgumentsTest}</li>
+ * <li>How to use frames and frame slots to store values local to an activation? {@link com.oracle.truffle.api.test.FrameTest}</li>
+ * <li>How to use type specialization and speculation for frame slots? {@link com.oracle.truffle.api.test.FrameSlotTypeSpecializationTest}</li>
+ * <li>How to use type specialization and speculation for node return values? {@link com.oracle.truffle.api.test.ReturnTypeSpecializationTest}</li>
+ * <li>How to "instrument" an AST with nodes that can provide access to runtime state from external tools {@link com.oracle.truffle.api.test.instrument.InstrumentationTest}</li>
+ * </ul>
+ *
+ *
+ */
+package com.oracle.truffle.api.test;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/BytesSourceSectionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.source;
+
+import static org.junit.Assert.*;
+
+import java.nio.charset.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.source.*;
+
+public class BytesSourceSectionTest {
+
+    @Test
+    public void testSectionsFromLineNumberASCII() {
+        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.US_ASCII);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 1).getCode());
+        assertEquals("bar", source.createSection("identifier", 2).getCode());
+        assertEquals("baz", source.createSection("identifier", 3).getCode());
+    }
+
+    @Test
+    public void testSectionsFromOffsetsASCII() {
+        final byte[] bytes = "foo\nbar\nbaz\n".getBytes(StandardCharsets.US_ASCII);
+        final Source source = Source.fromBytes(bytes, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
+        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
+        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
+    }
+
+    @Test
+    public void testOffset() {
+        final byte[] bytes = "xxxfoo\nbar\nbaz\nxxx".getBytes(StandardCharsets.US_ASCII);
+        final Source source = Source.fromBytes(bytes, 3, bytes.length - 6, "description", new BytesDecoder.UTF8BytesDecoder());
+        assertEquals("foo", source.createSection("identifier", 0, 3).getCode());
+        assertEquals("bar", source.createSection("identifier", 4, 3).getCode());
+        assertEquals("baz", source.createSection("identifier", 8, 3).getCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceSectionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.source;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.source.*;
+
+public class SourceSectionTest {
+
+    private final Source emptySource = Source.fromText("", null);
+
+    private final Source emptyLineSource = Source.fromText("\n", null);
+
+    private final Source shortSource = Source.fromText("01", null);
+
+    private final Source longSource = Source.fromText("01234\n67\n9\n", null);
+
+    public void emptySourceTest0() {
+        SourceSection section = emptySource.createSection("test", 0, 0);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "");
+    }
+
+    @Test
+    public void emptyLineTest0() {
+        SourceSection section = emptyLineSource.createSection("test", 0, 0);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "");
+        assertEquals(section.getCharIndex(), 0);
+        assertEquals(section.getCharLength(), 0);
+        assertEquals(section.getStartLine(), 1);
+        assertEquals(section.getStartColumn(), 1);
+    }
+
+    @Ignore
+    @Test
+    public void emptyLineTest0a() {
+        SourceSection section = emptyLineSource.createSection("test", 0, 0);
+        assertEquals(section.getEndLine(), 1);
+        assertEquals(section.getEndColumn(), 1);
+    }
+
+    @Test
+    public void emptyLineTest1() {
+        SourceSection section = emptyLineSource.createSection("test", 0, 1);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "\n");
+        assertEquals(section.getCharIndex(), 0);
+        assertEquals(section.getCharLength(), 1);
+        assertEquals(section.getStartLine(), 1);
+        assertEquals(section.getStartColumn(), 1);
+        assertEquals(section.getEndLine(), 1);
+        assertEquals(section.getEndColumn(), 1);
+    }
+
+    @Ignore
+    @Test
+    public void emptyLineTest2() {
+        SourceSection section = emptyLineSource.createSection("test", 1, 0);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "");
+        assertEquals(section.getCharIndex(), 1);
+        assertEquals(section.getCharLength(), 0);
+        assertEquals(section.getStartLine(), 1);
+        assertEquals(section.getStartColumn(), 1);
+        assertEquals(section.getEndLine(), 1);
+        assertEquals(section.getEndColumn(), 1);
+    }
+
+    @Test
+    public void emptySectionTest2() {
+        SourceSection section = shortSource.createSection("test", 0, 0);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "");
+    }
+
+    @Test
+    public void emptySectionTest3() {
+        SourceSection section = longSource.createSection("test", 0, 0);
+        assertNotNull(section);
+        assertEquals(section.getCode(), "");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTagTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.source;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.source.*;
+
+public class SourceTagTest {
+
+    @Test
+    public void sourceTagTest() {
+
+        // Private tag
+        final SourceTag testTag = new SourceTag() {
+
+            public String name() {
+                return null;
+            }
+
+            public String getDescription() {
+                return null;
+            }
+        };
+
+        // No sources exist with the private tag
+        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
+
+        // Create a new source
+        final Source source = Source.fromText("test1 source", "test1 source");
+
+        // Initially has only the default tag
+        assertEquals(source.getSourceTags().size(), 1);
+
+        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
+        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
+        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
+
+        assertFalse(source.isTaggedAs(testTag));
+        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 0);
+
+        // Add a private tag
+        source.tagAs(testTag);
+
+        // Now there are exactly two tags
+        assertEquals(source.getSourceTags().size(), 2);
+
+        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
+        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
+        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
+
+        assertTrue(source.getSourceTags().contains(testTag));
+        assertTrue(source.isTaggedAs(testTag));
+        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
+        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
+
+        // Add the private tag again
+        source.tagAs(testTag);
+
+        // Nothing has changed
+        assertEquals(source.getSourceTags().size(), 2);
+
+        assertTrue(source.getSourceTags().contains(Source.Tags.FROM_LITERAL));
+        assertTrue(source.isTaggedAs(Source.Tags.FROM_LITERAL));
+        assertTrue(Source.findSourcesTaggedAs(Source.Tags.FROM_LITERAL).contains(source));
+
+        assertTrue(source.getSourceTags().contains(testTag));
+        assertTrue(source.isTaggedAs(testTag));
+        assertEquals(Source.findSourcesTaggedAs(testTag).size(), 1);
+        assertTrue(Source.findSourcesTaggedAs(testTag).contains(source));
+    }
+
+    @Test
+    public void sourceListenerTest() {
+
+        // Private tag
+        final SourceTag testTag = new SourceTag() {
+
+            public String name() {
+                return null;
+            }
+
+            public String getDescription() {
+                return null;
+            }
+        };
+
+        final int[] newSourceEvents = {0};
+        final Source[] newSource = {null};
+
+        final int[] newTagEvents = {0};
+        final Source[] taggedSource = {null};
+        final SourceTag[] newTag = {null};
+
+        Source.addSourceListener(new SourceListener() {
+
+            public void sourceCreated(Source source) {
+                newSourceEvents[0] = newSourceEvents[0] + 1;
+                newSource[0] = source;
+            }
+
+            public void sourceTaggedAs(Source source, SourceTag tag) {
+                newTagEvents[0] = newTagEvents[0] + 1;
+                taggedSource[0] = source;
+                newTag[0] = tag;
+            }
+        });
+
+        // New source has a default tag applied.
+        // Get one event for the new source, another one when it gets tagged
+        final Source source = Source.fromText("testSource", "testSource");
+        assertEquals(newSourceEvents[0], 1);
+        assertEquals(newSource[0], source);
+        assertEquals(newTagEvents[0], 1);
+        assertEquals(taggedSource[0], source);
+        assertEquals(newTag[0], Source.Tags.FROM_LITERAL);
+
+        // reset
+        newSource[0] = null;
+        taggedSource[0] = null;
+        newTag[0] = null;
+
+        // Add a tag; only get one event (the new tag)
+        source.tagAs(testTag);
+        assertEquals(newSourceEvents[0], 1);
+        assertEquals(newSource[0], null);
+        assertEquals(newTagEvents[0], 2);
+        assertEquals(taggedSource[0], source);
+        assertEquals(newTag[0], testTag);
+
+        // Add the same tag; no events, and nothing changes.
+        source.tagAs(testTag);
+        assertEquals(newSourceEvents[0], 1);
+        assertEquals(newSource[0], null);
+        assertEquals(newTagEvents[0], 2);
+        assertEquals(taggedSource[0], source);
+        assertEquals(newTag[0], testTag);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.source;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.source.*;
+
+public class SourceTextTest {
+
+    private final Source emptySource = Source.fromText("", null);
+
+    private final Source emptyLineSource = Source.fromText("\n", null);
+
+    private final Source shortSource = Source.fromText("01", null);
+
+    private final Source longSource = Source.fromText("01234\n67\n9\n", null);
+
+    @Test
+    public void emptyTextTest0() {
+        assertEquals(emptySource.getLineCount(), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest1() {
+        emptySource.getLineNumber(0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest2() {
+        emptySource.getColumnNumber(0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest3() {
+        emptySource.getLineNumber(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest4() {
+        emptySource.getLineStartOffset(0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest5() {
+        emptySource.getLineStartOffset(1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyTextTest6() {
+        emptySource.getLineLength(1);
+    }
+
+    @Test
+    public void emptyLineTest0() {
+        assertEquals(emptyLineSource.getLineCount(), 1);
+        assertEquals(emptyLineSource.getLineNumber(0), 1);
+        assertEquals(emptyLineSource.getLineStartOffset(1), 0);
+        assertEquals(emptyLineSource.getColumnNumber(0), 1);
+        assertEquals(emptyLineSource.getLineLength(1), 0);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyLineTest1() {
+        emptyLineSource.getLineNumber(1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyLineTest2() {
+        emptyLineSource.getLineStartOffset(2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyLineTest3() {
+        emptyLineSource.getColumnNumber(1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void emptyLineTest4() {
+        emptyLineSource.getLineLength(2);
+    }
+
+    @Test
+    public void shortTextTest0() {
+
+        assertEquals(shortSource.getLineCount(), 1);
+
+        assertEquals(shortSource.getLineNumber(0), 1);
+        assertEquals(shortSource.getLineStartOffset(1), 0);
+        assertEquals(shortSource.getColumnNumber(0), 1);
+
+        assertEquals(shortSource.getLineNumber(1), 1);
+        assertEquals(shortSource.getColumnNumber(1), 2);
+
+        assertEquals(shortSource.getLineLength(1), 2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest1() {
+        shortSource.getLineNumber(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest2() {
+        shortSource.getColumnNumber(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest3() {
+        shortSource.getLineNumber(2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest4() {
+        shortSource.getColumnNumber(2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest5() {
+        shortSource.getLineLength(2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void shortTextTest6() {
+        shortSource.getLineLength(2);
+    }
+
+    @Test
+    public void longTextTest0() {
+
+        assertEquals(longSource.getLineCount(), 3);
+
+        assertEquals(longSource.getLineNumber(0), 1);
+        assertEquals(longSource.getLineStartOffset(1), 0);
+        assertEquals(longSource.getColumnNumber(0), 1);
+
+        assertEquals(longSource.getLineNumber(4), 1);
+        assertEquals(longSource.getColumnNumber(4), 5);
+
+        assertEquals(longSource.getLineNumber(5), 1); // newline
+        assertEquals(longSource.getColumnNumber(5), 6); // newline
+        assertEquals(longSource.getLineLength(1), 5);
+
+        assertEquals(longSource.getLineNumber(6), 2);
+        assertEquals(longSource.getLineStartOffset(2), 6);
+        assertEquals(longSource.getColumnNumber(6), 1);
+
+        assertEquals(longSource.getLineNumber(7), 2);
+        assertEquals(longSource.getColumnNumber(7), 2);
+
+        assertEquals(longSource.getLineNumber(8), 2); // newline
+        assertEquals(longSource.getLineNumber(8), 2); // newline
+        assertEquals(longSource.getLineLength(2), 2);
+
+        assertEquals(longSource.getLineNumber(9), 3);
+        assertEquals(longSource.getLineStartOffset(3), 9);
+        assertEquals(longSource.getColumnNumber(9), 1);
+
+        assertEquals(longSource.getLineNumber(10), 3); // newline
+        assertEquals(longSource.getColumnNumber(10), 2); // newline
+        assertEquals(longSource.getLineLength(3), 1);
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void longTextTest1() {
+        longSource.getLineNumber(11);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void longTextTest2() {
+        longSource.getColumnNumber(11);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void longTextTest3() {
+        longSource.getLineStartOffset(4);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AlwaysValidAssumptionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+public class AlwaysValidAssumptionTest {
+
+    @Test
+    public void testCheck() throws InvalidAssumptionException {
+        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
+        assumption.check();
+    }
+
+    @Test
+    public void testIsValid() {
+        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
+        assertTrue(assumption.isValid());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testCannotInvalidate() {
+        final AlwaysValidAssumption assumption = AlwaysValidAssumption.INSTANCE;
+        assumption.invalidate();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/AssumedValueTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+public class AssumedValueTest {
+
+    @Test
+    public void testGet() {
+        final AssumedValue<String> assumedValue = new AssumedValue<>("assumed-value", "1");
+        assertEquals("1", assumedValue.get());
+    }
+
+    @Test
+    public void testSet() {
+        final AssumedValue<String> assumedValue = new AssumedValue<>("assumed-value", "1");
+        assertEquals("1", assumedValue.get());
+        assumedValue.set("2");
+        assertEquals("2", assumedValue.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class BinaryConditionProfileTest {
+
+    @DataPoints public static boolean[] data = new boolean[]{true, false};
+
+    private BinaryConditionProfile profile;
+
+    @Before
+    public void create() {
+        profile = (BinaryConditionProfile) ConditionProfile.createBinaryProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.wasTrue(), is(false));
+        assertThat(profile.wasFalse(), is(false));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        boolean result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertThat(profile.wasTrue(), is(value));
+        assertThat(profile.wasFalse(), is(!value));
+    }
+
+    @Theory
+    public void testProfileTwo(boolean value0, boolean value1) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(profile.wasTrue(), is(value0 || value1));
+        assertThat(profile.wasFalse(), is(!value0 || !value1));
+    }
+
+    @Theory
+    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+        boolean result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+        assertThat(profile.wasTrue(), is(value0 || value1 || value2));
+        assertThat(profile.wasFalse(), is(!value0 || !value1 || !value2));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BranchProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+public class BranchProfileTest {
+
+    @Test
+    public void testEnter() {
+        BranchProfile profile = BranchProfile.create();
+        profile.enter();
+        profile.enter();
+    }
+
+    @Test
+    public void testToString() {
+        BranchProfile profile = BranchProfile.create();
+        assertTrue(profile.toString().contains(profile.getClass().getSimpleName()));
+        assertTrue(profile.toString().contains("not-visited"));
+        assertTrue(profile.toString().contains(Integer.toHexString(profile.hashCode())));
+        profile.enter();
+        assertTrue(profile.toString().contains(profile.getClass().getSimpleName()));
+        assertTrue(profile.toString().contains("visited"));
+        assertTrue(profile.toString().contains(Integer.toHexString(profile.hashCode())));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class CountingConditionProfileTest {
+
+    @DataPoints public static boolean[] data = new boolean[]{true, false};
+
+    private CountingConditionProfile profile;
+
+    @Before
+    public void create() {
+        profile = (CountingConditionProfile) ConditionProfile.createCountingProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.getTrueCount(), is(0));
+        assertThat(profile.getFalseCount(), is(0));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        boolean result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertThat(profile.getTrueCount(), is(value ? 1 : 0));
+        assertThat(profile.getFalseCount(), is(!value ? 1 : 0));
+    }
+
+    @Theory
+    public void testProfileTwo(boolean value0, boolean value1) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0)));
+        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0)));
+    }
+
+    @Theory
+    public void testProfileThree(boolean value0, boolean value1, boolean value2) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+        boolean result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+        assertThat(profile.getTrueCount(), is((value0 ? 1 : 0) + (value1 ? 1 : 0) + (value2 ? 1 : 0)));
+        assertThat(profile.getFalseCount(), is((!value0 ? 1 : 0) + (!value1 ? 1 : 0) + (!value2 ? 1 : 0)));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CyclicAssumptionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.utilities.*;
+
+public class CyclicAssumptionTest {
+
+    @Test
+    public void testIsValid() {
+        final CyclicAssumption assumption = new CyclicAssumption("cyclic-assumption");
+        assertTrue(assumption.getAssumption().isValid());
+    }
+
+    @Test
+    public void testInvalidate() {
+        final CyclicAssumption cyclicAssumption = new CyclicAssumption("cyclic-assumption");
+
+        final Assumption firstAssumption = cyclicAssumption.getAssumption();
+        assertEquals("cyclic-assumption", firstAssumption.getName());
+        assertTrue(firstAssumption.isValid());
+
+        cyclicAssumption.invalidate();
+
+        assertFalse(firstAssumption.isValid());
+
+        final Assumption secondAssumption = cyclicAssumption.getAssumption();
+        assertEquals("cyclic-assumption", secondAssumption.getName());
+        assertTrue(secondAssumption.isValid());
+
+        cyclicAssumption.invalidate();
+
+        assertFalse(firstAssumption.isValid());
+        assertFalse(secondAssumption.isValid());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/ExactClassValueProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class ExactClassValueProfileTest {
+
+    @DataPoint public static final String O1 = new String();
+    @DataPoint public static final String O2 = new String();
+    @DataPoint public static final Object O3 = new Object();
+    @DataPoint public static final Integer O4 = new Integer(1);
+    @DataPoint public static final Integer O5 = null;
+
+    private ExactClassValueProfile profile;
+
+    @Before
+    public void create() {
+        profile = (ExactClassValueProfile) ValueProfile.createClassProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.isGeneric(), is(false));
+        assertThat(profile.isUninitialized(), is(true));
+        assertNull(profile.getCachedClass());
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOne(Object value) {
+        Object result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedClass(), expectedClass(value));
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwo(Object value0, Object value1) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+
+        Object expectedClass = expectedClass(value0) == expectedClass(value1) ? expectedClass(value0) : Object.class;
+
+        assertEquals(profile.getCachedClass(), expectedClass);
+        assertThat(profile.isUninitialized(), is(false));
+        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThree(Object value0, Object value1, Object value2) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+        Object result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+
+        Object expectedClass = expectedClass(value0) == expectedClass(value1) && expectedClass(value1) == expectedClass(value2) ? expectedClass(value0) : Object.class;
+
+        assertEquals(profile.getCachedClass(), expectedClass);
+        assertThat(profile.isUninitialized(), is(false));
+        assertThat(profile.isGeneric(), is(expectedClass == Object.class));
+        profile.toString(); // test that it is not crashing
+    }
+
+    private static Class<?> expectedClass(Object value) {
+        return value == null ? Object.class : value.getClass();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IdentityValueProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class IdentityValueProfileTest {
+
+    @DataPoint public static final String O1 = new String();
+    @DataPoint public static final String O2 = O1;
+    @DataPoint public static final Object O3 = new Object();
+    @DataPoint public static final Integer O4 = new Integer(1);
+    @DataPoint public static final Integer O5 = null;
+
+    private IdentityValueProfile profile;
+
+    @Before
+    public void create() {
+        profile = (IdentityValueProfile) ValueProfile.createIdentityProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.isGeneric(), is(false));
+        assertThat(profile.isUninitialized(), is(true));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOne(Object value) {
+        Object result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwo(Object value0, Object value1) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+
+        if (value0 == value1) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThree(Object value0, Object value1, Object value2) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+        Object result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+
+        if (value0 == value1 && value1 == value2) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/NeverValidAssumptionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+public class NeverValidAssumptionTest {
+
+    @Test
+    public void testCheck() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+
+        try {
+            assumption.check();
+            fail();
+        } catch (InvalidAssumptionException e) {
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+    @Test
+    public void testIsValid() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+        assertFalse(assumption.isValid());
+    }
+
+    @Test
+    public void testInvalidateDoesNothing() {
+        final NeverValidAssumption assumption = NeverValidAssumption.INSTANCE;
+        assumption.invalidate();
+        assumption.invalidate();
+        assumption.invalidate();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/PrimitiveValueProfileTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,945 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+import org.junit.experimental.theories.*;
+import org.junit.runner.*;
+
+import com.oracle.truffle.api.utilities.*;
+
+@RunWith(Theories.class)
+public class PrimitiveValueProfileTest {
+
+    @DataPoint public static final String O1 = new String();
+    @DataPoint public static final String O2 = O1;
+    @DataPoint public static final Object O3 = new Object();
+    @DataPoint public static final Object O4 = null;
+
+    @DataPoint public static final byte B1 = Byte.MIN_VALUE;
+    @DataPoint public static final byte B2 = 0;
+    @DataPoint public static final byte B3 = 14;
+    @DataPoint public static final byte B4 = Byte.MAX_VALUE;
+
+    @DataPoint public static final short S1 = Short.MIN_VALUE;
+    @DataPoint public static final short S2 = 0;
+    @DataPoint public static final short S3 = 14;
+    @DataPoint public static final short S4 = Short.MAX_VALUE;
+
+    @DataPoint public static final int I1 = Integer.MIN_VALUE;
+    @DataPoint public static final int I2 = 0;
+    @DataPoint public static final int I3 = 14;
+    @DataPoint public static final int I4 = Integer.MAX_VALUE;
+
+    @DataPoint public static final long L1 = Long.MIN_VALUE;
+    @DataPoint public static final long L2 = 0;
+    @DataPoint public static final long L3 = 14;
+    @DataPoint public static final long L4 = Long.MAX_VALUE;
+
+    @DataPoint public static final float F1 = Float.MIN_VALUE;
+    @DataPoint public static final float F2 = -0.0f;
+    @DataPoint public static final float F3 = +0.0f;
+    @DataPoint public static final float F4 = 14.5f;
+    @DataPoint public static final float F5 = Float.MAX_VALUE;
+
+    @DataPoint public static final double D1 = Double.MIN_VALUE;
+    @DataPoint public static final double D2 = -0.0;
+    @DataPoint public static final double D3 = +0.0;
+    @DataPoint public static final double D4 = 14.5;
+    @DataPoint public static final double D5 = Double.MAX_VALUE;
+
+    @DataPoint public static final boolean T1 = false;
+    @DataPoint public static final boolean T2 = true;
+
+    @DataPoint public static final char C1 = Character.MIN_VALUE;
+    @DataPoint public static final char C2 = 0;
+    @DataPoint public static final char C3 = 14;
+    @DataPoint public static final char C4 = Character.MAX_VALUE;
+
+    private static final float FLOAT_DELTA = 0.00001f;
+    private static final double DOUBLE_DELTA = 0.00001;
+
+    private PrimitiveValueProfile profile;
+
+    @Before
+    public void create() {
+        profile = ValueProfile.createPrimitiveProfile();
+    }
+
+    @Test
+    public void testInitial() {
+        assertThat(profile.isGeneric(), is(false));
+        assertThat(profile.isUninitialized(), is(true));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneObject(Object value) {
+        Object result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoObject(Object value0, Object value1) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+
+        if (value0 == value1) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeObject(Object value0, Object value1, Object value2) {
+        Object result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+        Object result2 = profile.profile(value2);
+
+        assertThat(result0, is(value0));
+        assertThat(result1, is(value1));
+        assertThat(result2, is(value2));
+
+        if (value0 == value1 && value1 == value2) {
+            assertThat(profile.getCachedValue(), is(value0));
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneByte(byte value) {
+        byte result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoByte(byte value0, byte value1) {
+        byte result0 = profile.profile(value0);
+        byte result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Byte);
+            assertEquals((byte) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeByte(byte value0, byte value1, byte value2) {
+        byte result0 = profile.profile(value0);
+        byte result1 = profile.profile(value1);
+        byte result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Byte);
+            assertEquals((byte) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneShort(short value) {
+        short result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoShort(short value0, short value1) {
+        short result0 = profile.profile(value0);
+        short result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Short);
+            assertEquals((short) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeShort(short value0, short value1, short value2) {
+        short result0 = profile.profile(value0);
+        short result1 = profile.profile(value1);
+        short result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Short);
+            assertEquals((short) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneInteger(int value) {
+        int result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoInteger(int value0, int value1) {
+        int result0 = profile.profile(value0);
+        int result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Integer);
+            assertEquals((int) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeInteger(int value0, int value1, int value2) {
+        int result0 = profile.profile(value0);
+        int result1 = profile.profile(value1);
+        int result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Integer);
+            assertEquals((int) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneLong(long value) {
+        long result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoLong(long value0, long value1) {
+        long result0 = profile.profile(value0);
+        long result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Long);
+            assertEquals((long) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeLong(long value0, long value1, long value2) {
+        long result0 = profile.profile(value0);
+        long result1 = profile.profile(value1);
+        long result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Long);
+            assertEquals((long) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneFloat(float value) {
+        float result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoFloat(float value0, float value1) {
+        float result0 = profile.profile(value0);
+        float result1 = profile.profile(value1);
+
+        assertEquals(result0, value0, FLOAT_DELTA);
+        assertEquals(result1, value1, FLOAT_DELTA);
+
+        if (PrimitiveValueProfile.exactCompare(value0, value1)) {
+            assertTrue(profile.getCachedValue() instanceof Float);
+            assertEquals((float) profile.getCachedValue(), value0, FLOAT_DELTA);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeFloat(float value0, float value1, float value2) {
+        float result0 = profile.profile(value0);
+        float result1 = profile.profile(value1);
+        float result2 = profile.profile(value2);
+
+        assertEquals(result0, value0, FLOAT_DELTA);
+        assertEquals(result1, value1, FLOAT_DELTA);
+        assertEquals(result2, value2, FLOAT_DELTA);
+
+        if (PrimitiveValueProfile.exactCompare(value0, value1) && PrimitiveValueProfile.exactCompare(value1, value2)) {
+            assertTrue(profile.getCachedValue() instanceof Float);
+            assertEquals((float) profile.getCachedValue(), value0, FLOAT_DELTA);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneDouble(double value) {
+        double result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoDouble(double value0, double value1) {
+        double result0 = profile.profile(value0);
+        double result1 = profile.profile(value1);
+
+        assertEquals(result0, value0, DOUBLE_DELTA);
+        assertEquals(result1, value1, DOUBLE_DELTA);
+
+        if (PrimitiveValueProfile.exactCompare(value0, value1)) {
+            assertTrue(profile.getCachedValue() instanceof Double);
+            assertEquals((double) profile.getCachedValue(), value0, DOUBLE_DELTA);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeDouble(double value0, double value1, double value2) {
+        double result0 = profile.profile(value0);
+        double result1 = profile.profile(value1);
+        double result2 = profile.profile(value2);
+
+        assertEquals(result0, value0, DOUBLE_DELTA);
+        assertEquals(result1, value1, DOUBLE_DELTA);
+        assertEquals(result2, value2, DOUBLE_DELTA);
+
+        if (PrimitiveValueProfile.exactCompare(value0, value1) && PrimitiveValueProfile.exactCompare(value1, value2)) {
+            assertTrue(profile.getCachedValue() instanceof Double);
+            assertEquals((double) profile.getCachedValue(), value0, DOUBLE_DELTA);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneBoolean(boolean value) {
+        boolean result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoBoolean(boolean value0, boolean value1) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Boolean);
+            assertEquals((boolean) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeBoolean(boolean value0, boolean value1, boolean value2) {
+        boolean result0 = profile.profile(value0);
+        boolean result1 = profile.profile(value1);
+        boolean result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Boolean);
+            assertEquals((boolean) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileOneChar(char value) {
+        char result = profile.profile(value);
+
+        assertThat(result, is(value));
+        assertEquals(profile.getCachedValue(), value);
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileTwoChar(char value0, char value1) {
+        char result0 = profile.profile(value0);
+        char result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+
+        if (value0 == value1) {
+            assertTrue(profile.getCachedValue() instanceof Character);
+            assertEquals((char) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testProfileThreeChar(char value0, char value1, char value2) {
+        char result0 = profile.profile(value0);
+        char result1 = profile.profile(value1);
+        char result2 = profile.profile(value2);
+
+        assertEquals(result0, value0);
+        assertEquals(result1, value1);
+        assertEquals(result2, value2);
+
+        if (value0 == value1 && value1 == value2) {
+            assertTrue(profile.getCachedValue() instanceof Character);
+            assertEquals((char) profile.getCachedValue(), value0);
+            assertThat(profile.isGeneric(), is(false));
+        } else {
+            assertThat(profile.isGeneric(), is(true));
+        }
+        assertThat(profile.isUninitialized(), is(false));
+        profile.toString(); // test that it is not crashing
+    }
+
+    @Theory
+    public void testWithBoxedBoxedByte(byte value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Byte);
+        assertEquals((byte) result0, value);
+        assertTrue(result1 instanceof Byte);
+        assertEquals((byte) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedByte(byte value) {
+        byte result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Byte);
+        assertEquals((byte) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedByte(byte value) {
+        Object result0 = profile.profile((Object) value);
+        byte result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Byte);
+        assertEquals((byte) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedShort(short value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Short);
+        assertEquals((short) result0, value);
+        assertTrue(result1 instanceof Short);
+        assertEquals((short) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedShort(short value) {
+        short result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Short);
+        assertEquals((short) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedShort(short value) {
+        Object result0 = profile.profile((Object) value);
+        short result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Short);
+        assertEquals((short) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedInt(int value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Integer);
+        assertEquals((int) result0, value);
+        assertTrue(result1 instanceof Integer);
+        assertEquals((int) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedInt(int value) {
+        int result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Integer);
+        assertEquals((int) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedInt(int value) {
+        Object result0 = profile.profile((Object) value);
+        int result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Integer);
+        assertEquals((int) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedLong(long value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Long);
+        assertEquals((long) result0, value);
+        assertTrue(result1 instanceof Long);
+        assertEquals((long) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedLong(long value) {
+        long result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Long);
+        assertEquals((long) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedLong(long value) {
+        Object result0 = profile.profile((Object) value);
+        long result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Long);
+        assertEquals((long) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedFloat(float value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Float);
+        assertTrue(PrimitiveValueProfile.exactCompare((float) result0, value));
+        assertTrue(result1 instanceof Float);
+        assertTrue(PrimitiveValueProfile.exactCompare((float) result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedFloat(float value) {
+        float result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(PrimitiveValueProfile.exactCompare(result0, value));
+        assertTrue(result1 instanceof Float);
+        assertTrue(PrimitiveValueProfile.exactCompare((float) result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedFloat(float value) {
+        Object result0 = profile.profile((Object) value);
+        float result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Float);
+        assertTrue(PrimitiveValueProfile.exactCompare((float) result0, value));
+        assertTrue(PrimitiveValueProfile.exactCompare(result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedDouble(double value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Double);
+        assertTrue(PrimitiveValueProfile.exactCompare((double) result0, value));
+        assertTrue(result1 instanceof Double);
+        assertTrue(PrimitiveValueProfile.exactCompare((double) result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedDouble(double value) {
+        double result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(PrimitiveValueProfile.exactCompare(result0, value));
+        assertTrue(result1 instanceof Double);
+        assertTrue(PrimitiveValueProfile.exactCompare((double) result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedDouble(double value) {
+        Object result0 = profile.profile((Object) value);
+        double result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Double);
+        assertTrue(PrimitiveValueProfile.exactCompare((double) result0, value));
+        assertTrue(PrimitiveValueProfile.exactCompare(result1, value));
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedBoolean(boolean value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Boolean);
+        assertEquals((boolean) result0, value);
+        assertTrue(result1 instanceof Boolean);
+        assertEquals((boolean) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedBoolean(boolean value) {
+        boolean result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Boolean);
+        assertEquals((boolean) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedBoolean(boolean value) {
+        Object result0 = profile.profile((Object) value);
+        boolean result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Boolean);
+        assertEquals((boolean) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedBoxedChar(char value) {
+        Object result0 = profile.profile((Object) value);
+        Object result1 = profile.profile((Object) value);
+
+        assertTrue(result0 instanceof Character);
+        assertEquals((char) result0, value);
+        assertTrue(result1 instanceof Character);
+        assertEquals((char) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithUnboxedBoxedChar(char value) {
+        char result0 = profile.profile(value);
+        Object result1 = profile.profile((Object) value);
+
+        assertEquals(result0, value);
+        assertTrue(result1 instanceof Character);
+        assertEquals((char) result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBoxedUnboxedCharacter(char value) {
+        Object result0 = profile.profile((Object) value);
+        char result1 = profile.profile(value);
+
+        assertTrue(result0 instanceof Character);
+        assertEquals((char) result0, value);
+        assertEquals(result1, value);
+        assertFalse(profile.isUninitialized());
+        assertFalse(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithByteThenObject(byte value0, Object value1) {
+        byte result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithShortThenObject(short value0, Object value1) {
+        short result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithIntThenObject(int value0, Object value1) {
+        int result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithLongThenObject(long value0, Object value1) {
+        long result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithFloatThenObject(float value0, Object value1) {
+        float result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertTrue(PrimitiveValueProfile.exactCompare(result0, value0));
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithDoubleThenObject(double value0, Object value1) {
+        double result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertTrue(PrimitiveValueProfile.exactCompare(result0, value0));
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithBooleanThenObject(boolean value0, Object value1) {
+        boolean result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Theory
+    public void testWithCharThenObject(char value0, Object value1) {
+        char result0 = profile.profile(value0);
+        Object result1 = profile.profile(value1);
+
+        assertEquals(result0, value0);
+        assertSame(result1, value1);
+        assertFalse(profile.isUninitialized());
+        assertTrue(profile.isGeneric());
+    }
+
+    @Test
+    public void testNegativeZeroFloat() {
+        profile.profile(-0.0f);
+        profile.profile(+0.0f);
+        assertThat(profile.isGeneric(), is(true));
+    }
+
+    @Test
+    public void testNegativeZeroDouble() {
+        profile.profile(-0.0);
+        profile.profile(+0.0);
+        assertThat(profile.isGeneric(), is(true));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/UnionAssumptionTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.utilities;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+
+public class UnionAssumptionTest {
+
+    @Test
+    public void testIsValid() {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+        assertTrue(union.isValid());
+    }
+
+    @Test
+    public void testCheck() throws InvalidAssumptionException {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+        union.check();
+    }
+
+    @Test
+    public void testFirstInvalidateIsValid() {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        first.invalidate();
+
+        assertFalse(union.isValid());
+    }
+
+    @Test(expected = InvalidAssumptionException.class)
+    public void testFirstInvalidateCheck() throws InvalidAssumptionException {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        first.invalidate();
+
+        union.check();
+    }
+
+    @Test
+    public void testSecondInvalidateIsValid() {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        second.invalidate();
+
+        assertFalse(union.isValid());
+    }
+
+    @Test(expected = InvalidAssumptionException.class)
+    public void testSecondInvalidateCheck() throws InvalidAssumptionException {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        second.invalidate();
+
+        union.check();
+    }
+
+    @Test
+    public void testBothInvalidateIsValid() {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        first.invalidate();
+        second.invalidate();
+
+        assertFalse(union.isValid());
+    }
+
+    @Test(expected = InvalidAssumptionException.class)
+    public void testBothInvalidateCheck() throws InvalidAssumptionException {
+        final Assumption first = Truffle.getRuntime().createAssumption("first");
+        final Assumption second = Truffle.getRuntime().createAssumption("second");
+        final UnionAssumption union = new UnionAssumption(first, second);
+
+        first.invalidate();
+        second.invalidate();
+
+        union.check();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.vm;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.*;
+
+public class ImplicitExplicitExportTest {
+    private TruffleVM vm;
+
+    @Before
+    public void initializeVM() {
+        vm = TruffleVM.newVM().build();
+        assertTrue("Found " + L1 + " language", vm.getLanguages().containsKey(L1));
+        assertTrue("Found " + L2 + " language", vm.getLanguages().containsKey(L2));
+        assertTrue("Found " + L3 + " language", vm.getLanguages().containsKey(L3));
+    }
+
+    @Test
+    public void explicitExportFound() throws IOException {
+        // @formatter:off
+        vm.eval(L1,
+            "explicit.ahoj=42"
+        );
+        Object ret = vm.eval(L3,
+            "return=ahoj"
+        );
+        // @formatter:on
+        assertEquals("42", ret);
+    }
+
+    @Test
+    public void implicitExportFound() throws IOException {
+        // @formatter:off
+        vm.eval(L1,
+            "implicit.ahoj=42"
+        );
+        Object ret = vm.eval(L3,
+            "return=ahoj"
+        );
+        // @formatter:on
+        assertEquals("42", ret);
+    }
+
+    @Test
+    public void explicitExportPreferred2() throws IOException {
+        // @formatter:off
+        vm.eval(L1,
+            "implicit.ahoj=42"
+        );
+        vm.eval(L2,
+            "explicit.ahoj=43"
+        );
+        Object ret = vm.eval(L3,
+            "return=ahoj"
+        );
+        // @formatter:on
+        assertEquals("Explicit import from L2 is used", "43", ret);
+        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
+    }
+
+    @Test
+    public void explicitExportPreferred1() throws IOException {
+        // @formatter:off
+        vm.eval(L1,
+            "explicit.ahoj=43"
+        );
+        vm.eval(L2,
+            "implicit.ahoj=42"
+        );
+        Object ret = vm.eval(L3,
+            "return=ahoj"
+        );
+        // @formatter:on
+        assertEquals("Explicit import from L2 is used", "43", ret);
+        assertEquals("Global symbol is also 43", "43", vm.findGlobalSymbol("ahoj").invoke(null));
+    }
+
+    private abstract static class AbstractExportImportLanguage extends TruffleLanguage {
+        protected AbstractExportImportLanguage(Env env) {
+            super(env);
+        }
+
+        private final Map<String, String> explicit = new HashMap<>();
+        private final Map<String, String> implicit = new HashMap<>();
+
+        @Override
+        protected Object eval(Source code) throws IOException {
+            Properties p = new Properties();
+            try (Reader r = code.getReader()) {
+                p.load(r);
+            }
+            Enumeration<Object> en = p.keys();
+            while (en.hasMoreElements()) {
+                Object n = en.nextElement();
+                if (n instanceof String) {
+                    String k = (String) n;
+                    if (k.startsWith("explicit.")) {
+                        explicit.put(k.substring(9), p.getProperty(k));
+                    }
+                    if (k.startsWith("implicit.")) {
+                        implicit.put(k.substring(9), p.getProperty(k));
+                    }
+                    if (k.equals("return")) {
+                        return env().importSymbol(p.getProperty(k));
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override
+        protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+            if (explicit.containsKey(globalName)) {
+                return explicit.get(globalName);
+            }
+            if (!onlyExplicit && implicit.containsKey(globalName)) {
+                return implicit.get(globalName);
+            }
+            return null;
+        }
+
+        @Override
+        protected Object getLanguageGlobal() {
+            return null;
+        }
+
+        @Override
+        protected boolean isObjectOfLanguage(Object object) {
+            return false;
+        }
+
+        @Override
+        protected ToolSupportProvider getToolSupport() {
+            return null;
+        }
+
+        @Override
+        protected DebugSupportProvider getDebugSupport() {
+            return null;
+        }
+    }
+
+    private static final String L1 = "application/x-test-import-export-1";
+    private static final String L2 = "application/x-test-import-export-2";
+    private static final String L3 = "application/x-test-import-export-3";
+
+    @TruffleLanguage.Registration(mimeType = L1, name = "ImportExport1", version = "0")
+    public static final class ExportImportLanguage1 extends AbstractExportImportLanguage {
+        public ExportImportLanguage1(Env env) {
+            super(env);
+        }
+    }
+
+    @TruffleLanguage.Registration(mimeType = L2, name = "ImportExport2", version = "0")
+    public static final class ExportImportLanguage2 extends AbstractExportImportLanguage {
+        public ExportImportLanguage2(Env env) {
+            super(env);
+        }
+    }
+
+    @TruffleLanguage.Registration(mimeType = L3, name = "ImportExport3", version = "0")
+    public static final class ExportImportLanguage3 extends AbstractExportImportLanguage {
+        public ExportImportLanguage3(Env env) {
+            super(env);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/TruffleVMSingleThreadedTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.test.vm;
+
+import java.io.*;
+import java.net.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.vm.*;
+
+public class TruffleVMSingleThreadedTest {
+    TruffleVM tvm;
+
+    @Before
+    public void initInDifferentThread() throws InterruptedException {
+        final TruffleVM.Builder b = TruffleVM.newVM();
+        Thread t = new Thread("Initializer") {
+            @Override
+            public void run() {
+                tvm = b.build();
+            }
+        };
+        t.start();
+        t.join();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void evalURI() throws IOException, URISyntaxException {
+        tvm.eval(new URI("http://unknown.js"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void evalString() throws IOException {
+        tvm.eval("text/javascript", "1 + 1");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void evalReader() throws IOException {
+        try (StringReader sr = new StringReader("1 + 1")) {
+            tvm.eval("text/javascript", sr);
+        }
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void findGlobalSymbol() {
+        tvm.findGlobalSymbol("doesNotExists");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/.checkstyle_checks.xml	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,218 @@
+<?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: Checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="error"/>
+  <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-zA-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="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="ModifiedControlVariable"/>
+    <module name="MutableException">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <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">
+      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+      <property name="format" value=" ,"/>
+      <property name="message" value="illegal space before a comma"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="[^\x00-\x7F]"/>
+      <property name="message" value="Only use ASCII characters."/>
+    </module>
+     <module name="RegexpSinglelineJava">
+      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+      <property name="message" value="Don't use old synchronized collection classes"/>
+    </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.  Oracle designates this\n \* particular file as subject to the &quot;Classpath&quot; exception as provided\n \* by Oracle in the LICENSE file that accompanied this code.\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"/>
+    <property name="fileExtensions" value="java"/>
+  </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="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 name="RegexpMultiline">
+    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+    <property name="format" value="\r\n"/>
+    <property name="message" value="illegal Windows line ending"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop system..print check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume system..print check"/>
+    <property name="checkFormat" value="RegexpSingleline"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable System.(out|err).print checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+    <property name="checkFormat" value=".*Header"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: start generated"/>
+    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+    <property name="checkFormat" value=".*Name|.*LineLength"/>
+  </module>
+  <module name="RegexpSingleline">
+    <property name="format" value="System\.(out|err)\.print"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption is a global boolean flag that starts with the value true (i.e., the assumption is
+ * valid) and can subsequently be invalidated (using {@link Assumption#invalidate()}). Once
+ * invalidated, an assumption can never get valid again. Assumptions can be created using the
+ * {@link TruffleRuntime#createAssumption()} or the {@link TruffleRuntime#createAssumption(String)}
+ * method. The Truffle compiler has special knowledge of this class in order to produce efficient
+ * machine code for checking an assumption in case the assumption object is a compile time constant.
+ * Therefore, assumptions should be stored in final fields in Truffle nodes.
+ *
+ * All instances of classes implementing {@code Assumption} must be held in {@code final} fields for
+ * compiler optimizations to take effect.
+ */
+public interface Assumption {
+
+    /**
+     * Checks that this assumption is still valid. The method throws an exception, if this is no
+     * longer the case. This method is preferred over the {@link #isValid()} method when writing
+     * guest language interpreter code. The catch block should perform a node rewrite (see
+     * {@link Node#replace(Node)}) with a node that no longer relies on the assumption.
+     *
+     * @throws InvalidAssumptionException If the assumption is no longer valid.
+     */
+    void check() throws InvalidAssumptionException;
+
+    /**
+     * Checks whether the assumption is still valid.
+     *
+     * @return a boolean value indicating the validity of the assumption
+     */
+    boolean isValid();
+
+    /**
+     * Invalidates this assumption. Performs no operation, if the assumption is already invalid.
+     */
+    void invalidate();
+
+    /**
+     * A name for the assumption that is used for debug output.
+     *
+     * @return the name of the assumption
+     */
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * Represents the target of a call.
+ */
+public interface CallTarget {
+
+    /**
+     * Calls this target as a root method.
+     *
+     * @param arguments passed arguments as an object array
+     * @return the return result of the call
+     */
+    Object call(Object... arguments);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * Assertions about the code produced by the Truffle compiler. All operations have no effect when
+ * either executed in the interpreter or in the compiled code. The assertions are checked during
+ * code generation and the Truffle compiler produces for failing assertions a stack trace that
+ * identifies the code position of the assertion in the context of the current compilation.
+ *
+ */
+public class CompilerAsserts {
+    /**
+     * Assertion that this code position should never be reached during compilation. It can be used
+     * for exceptional code paths or rare code paths that should never be included in a compilation
+     * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler
+     * directive.
+     */
+    public static void neverPartOfCompilation() {
+        neverPartOfCompilation("");
+    }
+
+    /**
+     * Assertion that this code position should never be reached during compilation. It can be used
+     * for exceptional code paths or rare code paths that should never be included in a compilation
+     * unit. See {@link CompilerDirectives#transferToInterpreter()} for the corresponding compiler
+     * directive.
+     *
+     * @param message text associated with the bailout exception
+     */
+    public static void neverPartOfCompilation(String message) {
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during compilation.
+     *
+     * @param value the value that must be constant during compilation
+     */
+    public static <T> void compilationConstant(Object value) {
+        if (!CompilerDirectives.isCompilationConstant(value)) {
+            neverPartOfCompilation("Value is not compilation constant");
+        }
+    }
+
+    /**
+     * Assertion that the corresponding value is reduced to a constant during the initial partial
+     * evaluation phase.
+     *
+     * @param value the value that must be constant during compilation
+     */
+    public static <T> void partialEvaluationConstant(Object value) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import java.lang.annotation.*;
+import java.util.concurrent.*;
+
+/**
+ * Directives that influence the optimizations of the Truffle compiler. All of the operations have
+ * no effect when executed in the Truffle interpreter.
+ */
+public final class CompilerDirectives {
+
+    public static final double LIKELY_PROBABILITY = 0.75;
+    public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY;
+
+    public static final double SLOWPATH_PROBABILITY = 0.0001;
+    public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;
+
+    /**
+     * Directive for the compiler to discontinue compilation at this code position and instead
+     * insert a transfer to the interpreter.
+     */
+    public static void transferToInterpreter() {
+        if (inInterpreter()) {
+            Truffle.getRuntime().notifyTransferToInterpreter();
+        }
+    }
+
+    /**
+     * Directive for the compiler to discontinue compilation at this code position and instead
+     * insert a transfer to the interpreter, invalidating the currently executing machine code.
+     */
+    public static void transferToInterpreterAndInvalidate() {
+        if (inInterpreter()) {
+            Truffle.getRuntime().notifyTransferToInterpreter();
+        }
+    }
+
+    /**
+     * Returns a boolean value indicating whether the method is executed in the interpreter.
+     *
+     * @return {@code true} when executed in the interpreter, {@code false} in compiled code.
+     */
+    public static boolean inInterpreter() {
+        return true;
+    }
+
+    /**
+     * Returns a boolean value indicating whether the method is executed in the compiled code.
+     *
+     * @return {@code false} when executed in the interpreter, {@code true} in compiled code.
+     */
+    public static boolean inCompiledCode() {
+        return false;
+    }
+
+    /**
+     * Returns a boolean indicating whether or not a given value is seen as constant in optimized
+     * code. If this method is called in the interpreter this method will always return
+     * <code>true</code>.
+     *
+     * Note that optimizations that a compiler will apply to code that is conditional on
+     * <code>isCompilationConstant</code> may be limited. For this reason
+     * <code>isCompilationConstant</code> is not recommended for use to select between alternate
+     * implementations of functionality depending on whether a value is constant. Instead, it is
+     * intended for use as a diagnostic mechanism.
+     *
+     * @param value
+     * @return {@code true} when given value is seen as compilation constant, {@code false} if not
+     *         compilation constant.
+     */
+    public static boolean isCompilationConstant(Object value) {
+        return CompilerDirectives.inInterpreter();
+    }
+
+    /**
+     * Directive for the compiler that the given runnable should only be executed in the interpreter
+     * and ignored in the compiled code.
+     *
+     * @param runnable the closure that should only be executed in the interpreter
+     */
+    public static void interpreterOnly(Runnable runnable) {
+        runnable.run();
+    }
+
+    /**
+     * Directive for the compiler that the given callable should only be executed in the
+     * interpreter.
+     *
+     * @param callable the closure that should only be executed in the interpreter
+     * @return the result of executing the closure in the interpreter and null in the compiled code
+     * @throws Exception If the closure throws an exception when executed in the interpreter.
+     */
+    public static <T> T interpreterOnly(Callable<T> callable) throws Exception {
+        return callable.call();
+    }
+
+    /**
+     * Injects a probability for the given condition into the probability information of the
+     * immediately succeeding branch instruction for the condition. The probability must be a value
+     * between 0.0 and 1.0 (inclusive). The condition should not be a combined condition.
+     *
+     * Example usage immediately before an if statement (it specifies that the likelihood for a to
+     * be greater than b is 90%):
+     *
+     * <code>
+     * if (injectBranchProbability(0.9, a &gt; b)) {
+     *    // ...
+     * }
+     * </code>
+     *
+     * Example usage for a combined condition (it specifies that the likelihood for a to be greater
+     * than b is 90% and under the assumption that this is true, the likelihood for a being 0 is
+     * 10%):
+     *
+     * <code>
+     * if (injectBranchProbability(0.9, a &gt; b) &amp;&amp; injectBranchProbability(0.1, a == 0)) {
+     *    // ...
+     * }
+     * </code>
+     *
+     * There are predefined constants for commonly used probabilities (see
+     * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY},
+     * {@link #FASTPATH_PROBABILITY} ).
+     *
+     * @param probability the probability value between 0.0 and 1.0 that should be injected
+     */
+    public static boolean injectBranchProbability(double probability, boolean condition) {
+        assert probability >= 0.0 && probability <= 1.0;
+        return condition;
+    }
+
+    /**
+     * Bails out of a compilation (e.g., for guest language features that should never be compiled).
+     *
+     * @param reason the reason for the bailout
+     */
+    public static void bailout(String reason) {
+    }
+
+    /**
+     * Marks fields that should be considered final for a Truffle compilation although they are not
+     * final while executing in the interpreter.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface CompilationFinal {
+    }
+
+    /**
+     * Marks a method that it is considered as a boundary for Truffle partial evaluation.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+    public @interface TruffleBoundary {
+    }
+
+    /**
+     * Marks classes as value types. Reference comparisons (==) between instances of those classes
+     * have undefined semantics and can either return true or false.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    public @interface ValueType {
+    }
+
+    /**
+     * Ensures that the given object is not virtual, i.e., not removed by Escape Analysis at the
+     * point of this call.
+     *
+     * @param obj the object to exclude from Escape Analysis
+     */
+    public static void materialize(Object obj) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerOptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Allows options to be set to control the compilation of a specific {@link RootNode}, without
+ * creating a dependency on the specific compiler used. Options can be tested for support before
+ * setting.
+ */
+public interface CompilerOptions {
+
+    boolean supportsOption(String name);
+
+    void setOption(String name, Object value);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * This class contains methods that will be part of java.lang.Math starting with JDK 8. Until JDK 8
+ * is release, we duplicate them here because they are generally useful for dynamic language
+ * implementations.
+ */
+public class ExactMath {
+
+    public static int addExact(int x, int y) {
+        int r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long addExact(long x, long y) {
+        long r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int subtractExact(int x, int y) {
+        int r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    public static long subtractExact(long x, long y) {
+        long r = x - y;
+        // HD 2-12 Overflow iff the arguments have different signs and
+        // the sign of the result is different than the sign of x
+        if (((x ^ y) & (x ^ r)) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return r;
+    }
+
+    public static int multiplyExact(int x, int y) {
+        long r = (long) x * (long) y;
+        if ((int) r != r) {
+            throw new ArithmeticException("long overflow");
+        }
+        return (int) r;
+    }
+
+    public static long multiplyExact(long x, long y) {
+        long r = x * y;
+        long ax = Math.abs(x);
+        long ay = Math.abs(y);
+        if (((ax | ay) >>> 31 != 0)) {
+            // Some bits greater than 2^31 that might cause overflow
+            // Check the result using the divide operator
+            // and check for the special case of Long.MIN_VALUE * -1
+            if (((y != 0) && (r / y != x)) || (x == Long.MIN_VALUE && y == -1)) {
+                throw new ArithmeticException("long overflow");
+            }
+        }
+        return r;
+    }
+
+    public static int multiplyHigh(int x, int y) {
+        long r = (long) x * (long) y;
+        return (int) (r >> 32);
+    }
+
+    public static int multiplyHighUnsigned(int x, int y) {
+        long xl = x & 0xFFFFFFFFL;
+        long yl = y & 0xFFFFFFFFL;
+        long r = xl * yl;
+        return (int) (r >> 32);
+    }
+
+    public static long multiplyHigh(long x, long y) {
+        // Checkstyle: stop
+        long x0, y0, z0;
+        long x1, y1, z1, z2, t;
+        // Checkstyle: resume
+
+        x0 = x & 0xFFFFFFFFL;
+        x1 = x >> 32;
+
+        y0 = y & 0xFFFFFFFFL;
+        y1 = y >> 32;
+
+        z0 = x0 * y0;
+        t = x1 * y0 + (z0 >>> 32);
+        z1 = t & 0xFFFFFFFFL;
+        z2 = t >> 32;
+        z1 += x0 * y1;
+
+        return x1 * y1 + z2 + (z1 >> 32);
+    }
+
+    public static long multiplyHighUnsigned(long x, long y) {
+        // Checkstyle: stop
+        long x0, y0, z0;
+        long x1, y1, z1, z2, t;
+        // Checkstyle: resume
+
+        x0 = x & 0xFFFFFFFFL;
+        x1 = x >>> 32;
+
+        y0 = y & 0xFFFFFFFFL;
+        y1 = y >>> 32;
+
+        z0 = x0 * y0;
+        t = x1 * y0 + (z0 >>> 32);
+        z1 = t & 0xFFFFFFFFL;
+        z2 = t >>> 32;
+        z1 += x0 * y1;
+
+        return x1 * y1 + z2 + (z1 >>> 32);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.impl.*;
+
+/**
+ * Access to information and basic services in the runtime context for a Truffle-implemented guest
+ * language.
+ */
+public abstract class ExecutionContext {
+
+    protected ExecutionContext() {
+    }
+
+    /**
+     * Get compiler options specific to this <code>ExecutionContext</code>.
+     */
+    public CompilerOptions getCompilerOptions() {
+        return DefaultCompilerOptions.INSTANCE;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/LoopCountReceiver.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * Accepts the execution count of a loop that is a child of this node. The optimization heuristics
+ * can use the loop count to guide compilation and inlining.
+ */
+public interface LoopCountReceiver {
+
+    void reportLoopCount(int count);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/OptimizationFailedException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+public class OptimizationFailedException extends RuntimeException {
+
+    private final RootCallTarget callTarget;
+
+    public OptimizationFailedException(Throwable cause, RootCallTarget callTarget) {
+        super(cause);
+        this.callTarget = callTarget;
+    }
+
+    public RootCallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    private static final long serialVersionUID = -8797188744430210785L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/ReplaceObserver.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An observer that is notified whenever a child node is replaced.
+ */
+public interface ReplaceObserver {
+
+    /**
+     * Returns <code>true</code> if the event is consumed and no parent nodes should be notified by
+     * for replaces. Returns <code>false</code> if the parent {@link Node} or {@link CallTarget}
+     * should get notified.
+     */
+    boolean nodeReplaced(Node oldNode, Node newNode, CharSequence reason);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/RootCallTarget.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Represents the target of a call to a {@link RootNode}, i.e., to another tree of nodes. Instances
+ * of this class can be created using {@link TruffleRuntime#createCallTarget(RootNode)}.
+ */
+public interface RootCallTarget extends CallTarget {
+
+    RootNode getRootNode();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/Truffle.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import java.lang.reflect.*;
+import java.security.*;
+
+import com.oracle.truffle.api.impl.*;
+
+/**
+ * Class for obtaining the Truffle runtime singleton object of this virtual machine.
+ */
+public class Truffle {
+
+    private static final TruffleRuntime RUNTIME = initRuntime();
+
+    /**
+     * Gets the singleton {@link TruffleRuntime} object.
+     */
+    public static TruffleRuntime getRuntime() {
+        return RUNTIME;
+    }
+
+    private static TruffleRuntime initRuntime() {
+        if (TruffleOptions.ForceInterpreter) {
+            /*
+             * Force Truffle to run in interpreter mode even if we have a specialized implementation
+             * of TruffleRuntime available.
+             */
+            return new DefaultTruffleRuntime();
+        }
+
+        return AccessController.doPrivileged(new PrivilegedAction<TruffleRuntime>() {
+            public TruffleRuntime run() {
+                TruffleRuntimeAccess access = null;
+                Class<?> servicesClass = null;
+                try {
+                    servicesClass = Class.forName("com.oracle.jvmci.service.Services");
+                } catch (ClassNotFoundException e) {
+                    // JVMCI is unavailable
+                    e.printStackTrace();
+                } catch (IllegalArgumentException ex) {
+                    throw new IllegalStateException("jvmci service found but yields error", ex);
+                }
+                if (servicesClass != null) {
+                    try {
+                        Method m = servicesClass.getDeclaredMethod("loadSingle", Class.class, boolean.class);
+                        access = (TruffleRuntimeAccess) m.invoke(null, TruffleRuntimeAccess.class, false);
+                    } catch (Throwable e) {
+                        // Fail fast for other errors
+                        throw (InternalError) new InternalError().initCause(e);
+                    }
+                }
+                // TODO: try standard ServiceLoader?
+                if (access != null) {
+                    return access.getRuntime();
+                }
+                return new DefaultTruffleRuntime();
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+
+/**
+ * An entry point for everyone who wants to implement a Truffle based language. By providing
+ * implementation of this type and registering it using {@link Registration} annotation, your
+ * language becomes accessible to users of the {@link TruffleVM Truffle virtual machine} - all they
+ * will need to do is to include your JAR into their application and all the Truffle goodies (multi
+ * language support, multitenant hosting, debugging, etc.) will be made available to them.
+ */
+public abstract class TruffleLanguage {
+    private final Env env;
+
+    /**
+     * Constructor to be called by subclasses.
+     *
+     * @param env language environment that will be available via {@link #env()} method to
+     *            subclasses.
+     */
+    protected TruffleLanguage(Env env) {
+        this.env = env;
+    }
+
+    /**
+     * The annotation to use to register your language to the {@link TruffleVM Truffle} system. By
+     * annotating your implementation of {@link TruffleLanguage} by this annotation you are just a
+     * <em>one JAR drop to the class path</em> away from your users. Once they include your JAR in
+     * their application, your language will be available to the {@link TruffleVM Truffle virtual
+     * machine}.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target(ElementType.TYPE)
+    public @interface Registration {
+        /**
+         * Unique name of your language. This name will be exposed to users via the
+         * {@link Language#getName()} getter.
+         *
+         * @return identifier of your language
+         */
+        String name();
+
+        /**
+         * Unique string identifying the language version. This name will be exposed to users via
+         * the {@link Language#getVersion()} getter.
+         *
+         * @return version of your language
+         */
+        String version();
+
+        /**
+         * List of MIME types associated with your language. Users will use them (directly or
+         * indirectly) when {@link TruffleVM#eval(java.lang.String, java.lang.String) executing}
+         * their code snippets or their {@link TruffleVM#eval(java.net.URI) files}.
+         *
+         * @return array of MIME types assigned to your language files
+         */
+        String[] mimeType();
+    }
+
+    protected final Env env() {
+        if (this.env == null) {
+            throw new NullPointerException("Accessing env before initialization is finished");
+        }
+        return this.env;
+    }
+
+    protected abstract Object eval(Source code) throws IOException;
+
+    /**
+     * Called when some other language is seeking for a global symbol. This method is supposed to do
+     * lazy binding, e.g. there is no need to export symbols in advance, it is fine to wait until
+     * somebody asks for it (by calling this method).
+     * <p>
+     * The exported object can either be <code>TruffleObject</code> (e.g. a native object from the
+     * other language) to support interoperability between languages, {@link String} or one of Java
+     * primitive wrappers ( {@link Integer}, {@link Double}, {@link Short}, {@link Boolean}, etc.).
+     * <p>
+     * The way a symbol becomes <em>exported</em> is language dependent. In general it is preferred
+     * to make the export explicit - e.g. call some function or method to register an object under
+     * specific name. Some languages may however decide to support implicit export of symbols (for
+     * example from global scope, if they have one). However explicit exports should always be
+     * preferred. Implicitly exported object of some name should only be used when there is no
+     * explicit export under such <code>globalName</code>. To ensure so the infrastructure first
+     * asks all known languages for <code>onlyExplicit</code> symbols and only when none is found,
+     * it does one more round with <code>onlyExplicit</code> set to <code>false</code>.
+     *
+     * @param globalName the name of the global symbol to find
+     * @param onlyExplicit should the language seek for implicitly exported object or only consider
+     *            the explicitly exported ones?
+     * @return an exported object or <code>null</code>, if the symbol does not represent anything
+     *         meaningful in this language
+     */
+    protected abstract Object findExportedSymbol(String globalName, boolean onlyExplicit);
+
+    /**
+     * Returns global object for the language.
+     * <p>
+     * The object is expected to be <code>TruffleObject</code> (e.g. a native object from the other
+     * language) but technically it can be one of Java primitive wrappers ({@link Integer},
+     * {@link Double}, {@link Short}, etc.).
+     *
+     * @return the global object or <code>null</code> if the language does not support such concept
+     */
+    protected abstract Object getLanguageGlobal();
+
+    /**
+     * Checks whether the object is provided by this language.
+     *
+     * @param object the object to check
+     * @return <code>true</code> if this language can deal with such object in native way
+     */
+    protected abstract boolean isObjectOfLanguage(Object object);
+
+    protected abstract ToolSupportProvider getToolSupport();
+
+    protected abstract DebugSupportProvider getDebugSupport();
+
+    /**
+     * Represents execution environment of the {@link TruffleLanguage}. Each active
+     * {@link TruffleLanguage} receives instance of the environment before any code is executed upon
+     * it. The environment has knowledge of all active languages and can exchange symbols between
+     * them.
+     */
+    public static final class Env {
+        private final TruffleVM vm;
+        private final TruffleLanguage lang;
+        private final Reader in;
+        private final Writer err;
+        private final Writer out;
+
+        Env(TruffleVM vm, Constructor<?> langConstructor, Writer out, Writer err, Reader in) {
+            this.vm = vm;
+            this.in = in;
+            this.err = err;
+            this.out = out;
+            try {
+                this.lang = (TruffleLanguage) langConstructor.newInstance(this);
+            } catch (Exception ex) {
+                throw new IllegalStateException("Cannot construct language " + langConstructor.getDeclaringClass().getName(), ex);
+            }
+        }
+
+        /**
+         * Asks the environment to go through other registered languages and find whether they
+         * export global symbol of specified name. The expected return type is either
+         * <code>TruffleObject</code>, or one of wrappers of Java primitive types ({@link Integer},
+         * {@link Double}).
+         *
+         * @param globalName the name of the symbol to search for
+         * @return object representing the symbol or <code>null</code>
+         */
+        public Object importSymbol(String globalName) {
+            return API.importSymbol(vm, lang, globalName);
+        }
+
+        /**
+         * Input associated with this {@link TruffleVM}.
+         *
+         * @return reader, never <code>null</code>
+         */
+        public Reader stdIn() {
+            return in;
+        }
+
+        /**
+         * Standard output writer for this {@link TruffleVM}.
+         *
+         * @return writer, never <code>null</code>
+         */
+        public Writer stdOut() {
+            return out;
+        }
+
+        /**
+         * Standard error writer for this {@link TruffleVM}.
+         *
+         * @return writer, never <code>null</code>
+         */
+        public Writer stdErr() {
+            return err;
+        }
+    }
+
+    private static final AccessAPI API = new AccessAPI();
+
+    private static final class AccessAPI extends Accessor {
+        @Override
+        protected TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
+            Env env = new Env(vm, langClazz, stdOut, stdErr, stdIn);
+            return env.lang;
+        }
+
+        @Override
+        public Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
+            return super.importSymbol(vm, queryingLang, globalName);
+        }
+
+        @Override
+        protected Object eval(TruffleLanguage l, Source s) throws IOException {
+            return l.eval(s);
+        }
+
+        @Override
+        protected Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
+            return l.findExportedSymbol(globalName, onlyExplicit);
+        }
+
+        @Override
+        protected Object languageGlobal(TruffleLanguage l) {
+            return l.getLanguageGlobal();
+        }
+
+        @Override
+        protected ToolSupportProvider getToolSupport(TruffleLanguage l) {
+            return l.getToolSupport();
+        }
+
+        @Override
+        protected DebugSupportProvider getDebugSupport(TruffleLanguage l) {
+            return l.getDebugSupport();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleOptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import java.security.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Class containing general Truffle options.
+ */
+public class TruffleOptions {
+
+    /**
+     * Force truffle to run in interpreter mode.
+     * <p>
+     * Can be set with {@code -Dtruffle.ForceInterpreter=true}.
+     */
+    public static final boolean ForceInterpreter = Boolean.getBoolean("truffle.ForceInterpreter");
+
+    /**
+     * Enables/disables the rewriting of traces in the Truffle runtime to stdout.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewrites=true}.
+     */
+    public static final boolean TraceRewrites;
+
+    /**
+     * Enables the generation of detailed rewrite reasons. Enabling this may introduce some overhead
+     * for rewriting nodes.
+     * <p>
+     * Can be set with {@code -Dtruffle.DetailedRewriteReasons=true}.
+     */
+    public static final boolean DetailedRewriteReasons;
+
+    /**
+     * Filters rewrites that do not contain the given string in the qualified name of the source or
+     * target class hierarchy.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceRewritesFilterClass=name}.
+     */
+    public static String TraceRewritesFilterClass;
+
+    /**
+     * Filters rewrites which does not contain the {@link NodeCost} in its source {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterFromCost=NONE|MONOMORPHIC|POLYMORPHIC|MEGAMORPHIC}.
+     */
+    public static NodeCost TraceRewritesFilterFromCost;
+
+    /**
+     * Filters rewrites which does not contain the {@link NodeCost} in its target {@link NodeInfo}.
+     * If no {@link NodeInfo} is defined the element is filtered if the filter value is set.
+     * <p>
+     * Can be set with
+     * {@code -Dtruffle.TraceRewritesFilterToKind=UNINITIALIZED|SPECIALIZED|POLYMORPHIC|GENERIC}.
+     */
+    public static NodeCost TraceRewritesFilterToCost;
+
+    /**
+     * Enables the dumping of Node creations and AST rewrites in JSON format.
+     * <p>
+     * Can be set with {@code -Dtruffle.TraceASTJSON=true}.
+     */
+    public static final boolean TraceASTJSON;
+
+    private static NodeCost parseNodeInfoKind(String kind) {
+        if (kind == null) {
+            return null;
+        }
+
+        return NodeCost.valueOf(kind);
+    }
+
+    static {
+        final boolean[] values = new boolean[3];
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                values[0] = Boolean.getBoolean("truffle.TraceRewrites");
+                TraceRewritesFilterClass = System.getProperty("truffle.TraceRewritesFilterClass");
+                TraceRewritesFilterFromCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterFromCost"));
+                TraceRewritesFilterToCost = parseNodeInfoKind(System.getProperty("truffle.TraceRewritesFilterToCost"));
+                values[1] = Boolean.getBoolean("truffle.DetailedRewriteReasons");
+                values[2] = Boolean.getBoolean("truffle.TraceASTJSON");
+                return null;
+            }
+        });
+        TraceRewrites = values[0];
+        DetailedRewriteReasons = values[1];
+        TraceASTJSON = values[2];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Interface representing a Truffle runtime object. The runtime is responsible for creating call
+ * targets and performing optimizations for them.
+ */
+public interface TruffleRuntime {
+
+    /**
+     * Name describing this runtime implementation for debugging purposes.
+     *
+     * @return the name as a String
+     */
+    String getName();
+
+    /**
+     * Creates a new call target for a given root node.
+     *
+     * @param rootNode the root node whose
+     *            {@link RootNode#execute(com.oracle.truffle.api.frame.VirtualFrame)} method
+     *            represents the entry point
+     * @return the new call target object
+     */
+    RootCallTarget createCallTarget(RootNode rootNode);
+
+    /**
+     * Creates a new runtime specific version of {@link DirectCallNode}.
+     *
+     * @param target the direct {@link CallTarget} to call
+     * @return the new call node
+     */
+    DirectCallNode createDirectCallNode(CallTarget target);
+
+    /**
+     * Experimental API. May change without notice.
+     */
+    LoopNode createLoopNode(RepeatingNode body);
+
+    /**
+     * Creates a new runtime specific version of {@link IndirectCallNode}.
+     *
+     * @return the new call node
+     */
+    IndirectCallNode createIndirectCallNode();
+
+    /**
+     * Creates a new assumption object that can be checked and invalidated.
+     *
+     * @return the newly created assumption object
+     */
+    Assumption createAssumption();
+
+    /**
+     * Creates a new assumption object with a given name that can be checked and invalidated.
+     *
+     * @param name the name for the new assumption
+     * @return the newly created assumption object
+     */
+    Assumption createAssumption(String name);
+
+    /**
+     * Creates a new virtual frame object that can be used to store values and is potentially
+     * optimizable by the runtime.
+     *
+     * @return the newly created virtual frame object
+     */
+    VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor);
+
+    /**
+     * Creates a new materialized frame object that can be used to store values.
+     *
+     * @return the newly created materialized frame object
+     */
+    MaterializedFrame createMaterializedFrame(Object[] arguments);
+
+    /**
+     * Creates a new materialized frame object with the given frame descriptor that can be used to
+     * store values.
+     *
+     * @param frameDescriptor the frame descriptor describing this frame's values
+     * @return the newly created materialized frame object
+     */
+    MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor);
+
+    /**
+     * Creates an object which allows you to test for support of and set options specific for this
+     * runtime.
+     *
+     * @return the newly created compiler options object
+     */
+    CompilerOptions createCompilerOptions();
+
+    /**
+     * Accesses the current stack, i.e., the contents of the {@link Frame}s and the associated
+     * {@link CallTarget}s. Iteration starts at the caller frame, i.e., it does not include the
+     * current frame.
+     *
+     * Iteration continues as long as {@link FrameInstanceVisitor#visitFrame}, which is invoked for
+     * every {@link FrameInstance}, returns null. Any non-null result of the visitor indicates that
+     * frame iteration should stop.
+     *
+     * @param visitor the visitor that is called for every matching frame.
+     * @return the last result returned by the visitor (which is non-null to indicate that iteration
+     *         should stop), or null if the whole stack was iterated.
+     */
+    <T> T iterateFrames(FrameInstanceVisitor<T> visitor);
+
+    /**
+     * Accesses the caller frame. This is a convenience method that returns the first frame that is
+     * passed to the visitor of {@link #iterateFrames}.
+     */
+    FrameInstance getCallerFrame();
+
+    /**
+     * Accesses the current frame, i.e., the frame of the closest {@link CallTarget}. It is
+     * important to note that this {@link FrameInstance} supports only slow path access.
+     */
+    FrameInstance getCurrentFrame();
+
+    /**
+     * Requests a capability from the runtime.
+     *
+     * @param capability the type of the interface representing the capability
+     * @return an implementation of the capability or {@code null} if the runtime does not offer it
+     */
+    <T> T getCapability(Class<T> capability);
+
+    /**
+     * Returns a list of all still referenced {@link RootCallTarget} instances that were created
+     * using {@link #createCallTarget(RootNode)}.
+     */
+    Collection<RootCallTarget> getCallTargets();
+
+    /**
+     * Internal API method. Do not use.
+     */
+    void notifyTransferToInterpreter();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntimeAccess.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+/**
+ * A service that provides access to a {@link TruffleRuntime} implementation.
+ */
+public interface TruffleRuntimeAccess {
+
+    /**
+     * Gets the {@link TruffleRuntime} implementation available via this access object.
+     */
+    TruffleRuntime getRuntime();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TypedObject.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api;
+
+public interface TypedObject {
+
+    Object getTypeIdentifier();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.debug;
+
+public class DebugSupportException extends Exception {
+
+    private static final long serialVersionUID = 3039074861617372741L;
+
+    public DebugSupportException(String string) {
+        super(string);
+    }
+
+    public DebugSupportException(Exception ex) {
+        super(ex);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/DebugSupportProvider.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.debug;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Access to language-specific information and execution services to enable debugging.
+ */
+public interface DebugSupportProvider extends ToolSupportProvider {
+
+    /**
+     * Runs source code.
+     *
+     * @param source code
+     * @throws DebugSupportException if unable to run successfully
+     */
+    void run(Source source) throws DebugSupportException;
+
+    /**
+     * Runs source code in a halted execution context, or at top level.
+     *
+     * @param source the code to run
+     * @param node node where execution halted, {@code null} if no execution context
+     * @param mFrame frame where execution halted, {@code null} if no execution context
+     * @return result of running the code in the context, or at top level if no execution context.
+     * @throws DebugSupportException if the evaluation cannot be performed
+     */
+    Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException;
+
+    /**
+     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
+     * that, when executed, computes the result of a textual expression in the language; used to
+     * create an
+     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+     * Advanced Instrument}.
+     *
+     * @param expr a guest language expression
+     * @param resultListener optional listener for the result of each evaluation.
+     * @return a new factory
+     * @throws DebugSupportException if the factory cannot be created, for example if the expression
+     *             is badly formed.
+     */
+    AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a frame containing values of local variables of the guest language. Instances of this
+ * type must not be stored in a field or cast to {@link java.lang.Object}.
+ */
+public interface Frame {
+
+    /**
+     * @return the object describing the layout of this frame
+     */
+    FrameDescriptor getFrameDescriptor();
+
+    /**
+     * Retrieves the arguments object from this frame. The runtime assumes that the arguments object
+     * is never null.
+     *
+     * @return the arguments used when calling this method
+     */
+    Object[] getArguments();
+
+    /**
+     * Read access to a local variable of type {@link Object}.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    Object getObject(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type {@link Object}.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setObject(FrameSlot slot, Object value);
+
+    /**
+     * Read access to a local variable of type byte.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     * @throws FrameSlotTypeException
+     */
+    byte getByte(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type byte.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+
+    void setByte(FrameSlot slot, byte value);
+
+    /**
+     * Read access to a local variable of type boolean.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type boolean.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setBoolean(FrameSlot slot, boolean value);
+
+    /**
+     * Read access to a local variable of type int.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    int getInt(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type int.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setInt(FrameSlot slot, int value);
+
+    /**
+     * Read access to a local variable of type long.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    long getLong(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type long.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setLong(FrameSlot slot, long value);
+
+    /**
+     * Read access to a local variable of type float.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    float getFloat(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type float.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setFloat(FrameSlot slot, float value);
+
+    /**
+     * Read access to a local variable of type double.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable
+     */
+    double getDouble(FrameSlot slot) throws FrameSlotTypeException;
+
+    /**
+     * Write access to a local variable of type double.
+     *
+     * @param slot the slot of the local variable
+     * @param value the new value of the local variable
+     */
+    void setDouble(FrameSlot slot, double value);
+
+    /**
+     * Read access to a local variable of any type.
+     *
+     * @param slot the slot of the local variable
+     * @return the current value of the local variable or defaultValue if unset
+     */
+    Object getValue(FrameSlot slot);
+
+    /**
+     * Materializes this frame, which allows it to be stored in a field or cast to
+     * {@link java.lang.Object}.
+     *
+     * @return the new materialized frame
+     */
+    MaterializedFrame materialize();
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type object.
+     */
+    boolean isObject(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type byte.
+     */
+    boolean isByte(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type boolean.
+     */
+    boolean isBoolean(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type int.
+     */
+    boolean isInt(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type long.
+     */
+    boolean isLong(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type float.
+     */
+    boolean isFloat(FrameSlot slot);
+
+    /**
+     * Check whether the given {@link FrameSlot} is of type double.
+     */
+    boolean isDouble(FrameSlot slot);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Descriptor of the slots of frame objects. Multiple frame instances are associated with one such
+ * descriptor.
+ */
+public final class FrameDescriptor implements Cloneable {
+
+    private final Object defaultValue;
+    private final ArrayList<FrameSlot> slots;
+    private final HashMap<Object, FrameSlot> identifierToSlotMap;
+    private Assumption version;
+    private HashMap<Object, Assumption> identifierToNotInFrameAssumptionMap;
+
+    public FrameDescriptor() {
+        this(null);
+    }
+
+    public FrameDescriptor(Object defaultValue) {
+        this.defaultValue = defaultValue;
+        slots = new ArrayList<>();
+        identifierToSlotMap = new HashMap<>();
+        version = createVersion();
+    }
+
+    public static FrameDescriptor create() {
+        return new FrameDescriptor();
+    }
+
+    public static FrameDescriptor create(Object defaultValue) {
+        return new FrameDescriptor(defaultValue);
+    }
+
+    public FrameSlot addFrameSlot(Object identifier) {
+        return addFrameSlot(identifier, null, FrameSlotKind.Illegal);
+    }
+
+    public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) {
+        return addFrameSlot(identifier, null, kind);
+    }
+
+    public FrameSlot addFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
+        CompilerAsserts.neverPartOfCompilation("interpreter-only.  includes hashmap operations.");
+        assert !identifierToSlotMap.containsKey(identifier);
+        FrameSlot slot = new FrameSlot(this, identifier, info, slots.size(), kind);
+        slots.add(slot);
+        identifierToSlotMap.put(identifier, slot);
+        updateVersion();
+        invalidateNotInFrameAssumption(identifier);
+        return slot;
+    }
+
+    public FrameSlot findFrameSlot(Object identifier) {
+        return identifierToSlotMap.get(identifier);
+    }
+
+    public FrameSlot findOrAddFrameSlot(Object identifier) {
+        FrameSlot result = findFrameSlot(identifier);
+        if (result != null) {
+            return result;
+        }
+        return addFrameSlot(identifier);
+    }
+
+    public FrameSlot findOrAddFrameSlot(Object identifier, FrameSlotKind kind) {
+        FrameSlot result = findFrameSlot(identifier);
+        if (result != null) {
+            return result;
+        }
+        return addFrameSlot(identifier, kind);
+    }
+
+    public FrameSlot findOrAddFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
+        FrameSlot result = findFrameSlot(identifier);
+        if (result != null) {
+            return result;
+        }
+        return addFrameSlot(identifier, info, kind);
+    }
+
+    public void removeFrameSlot(Object identifier) {
+        CompilerAsserts.neverPartOfCompilation("interpreter-only.  includes hashmap operations.");
+        assert identifierToSlotMap.containsKey(identifier);
+        slots.remove(identifierToSlotMap.get(identifier));
+        identifierToSlotMap.remove(identifier);
+        updateVersion();
+        getNotInFrameAssumption(identifier);
+    }
+
+    public int getSize() {
+        return slots.size();
+    }
+
+    public List<? extends FrameSlot> getSlots() {
+        return Collections.unmodifiableList(slots);
+    }
+
+    /**
+     * Retrieve the list of all the identifiers associated with this frame descriptor.
+     *
+     * @return the list of all the identifiers in this frame descriptor
+     */
+    public Set<Object> getIdentifiers() {
+        return Collections.unmodifiableSet(identifierToSlotMap.keySet());
+    }
+
+    public FrameDescriptor copy() {
+        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
+        for (int i = 0; i < this.getSlots().size(); i++) {
+            Object identifier = this.getSlots().get(i).getIdentifier();
+            clonedFrameDescriptor.addFrameSlot(identifier);
+        }
+        return clonedFrameDescriptor;
+    }
+
+    public FrameDescriptor shallowCopy() {
+        FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
+        clonedFrameDescriptor.slots.addAll(slots);
+        clonedFrameDescriptor.identifierToSlotMap.putAll(identifierToSlotMap);
+        return clonedFrameDescriptor;
+    }
+
+    void updateVersion() {
+        version.invalidate();
+        version = createVersion();
+    }
+
+    public Assumption getVersion() {
+        return version;
+    }
+
+    private static Assumption createVersion() {
+        return Truffle.getRuntime().createAssumption("frame version");
+    }
+
+    public Object getDefaultValue() {
+        return defaultValue;
+    }
+
+    public Assumption getNotInFrameAssumption(Object identifier) {
+        if (identifierToSlotMap.containsKey(identifier)) {
+            throw new IllegalArgumentException("Cannot get not-in-frame assumption for existing frame slot!");
+        }
+
+        if (identifierToNotInFrameAssumptionMap == null) {
+            identifierToNotInFrameAssumptionMap = new HashMap<>();
+        } else {
+            Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
+            if (assumption != null) {
+                return assumption;
+            }
+        }
+        Assumption assumption = Truffle.getRuntime().createAssumption("not in frame: " + identifier);
+        identifierToNotInFrameAssumptionMap.put(identifier, assumption);
+        return assumption;
+    }
+
+    private void invalidateNotInFrameAssumption(Object identifier) {
+        if (identifierToNotInFrameAssumptionMap != null) {
+            Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
+            if (assumption != null) {
+                assumption.invalidate();
+                identifierToNotInFrameAssumptionMap.remove(identifier);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("FrameDescriptor@").append(Integer.toHexString(hashCode()));
+        sb.append("{");
+        boolean comma = false;
+        for (FrameSlot slot : slots) {
+            if (comma) {
+                sb.append(", ");
+            } else {
+                comma = true;
+            }
+            sb.append(slot.getIndex()).append(":").append(slot.getIdentifier());
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstance.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+public interface FrameInstance {
+
+    public static enum FrameAccess {
+        NONE,
+        READ_ONLY,
+        READ_WRITE,
+        MATERIALIZE
+    }
+
+    Frame getFrame(FrameAccess access, boolean slowPath);
+
+    boolean isVirtualFrame();
+
+    Node getCallNode();
+
+    CallTarget getCallTarget();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameInstanceVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Callback interface for {@link TruffleRuntime#iterateFrames}. Implementations of
+ * {@link #visitFrame} return null to indicate that frame iteration should continue and the next
+ * caller frame should be visited; and return any non-null value to indicate that frame iteration
+ * should stop.
+ */
+public interface FrameInstanceVisitor<T> {
+
+    T visitFrame(FrameInstance frameInstance);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * A slot in a frame that can store a value of a given type.
+ */
+public final class FrameSlot implements Cloneable {
+
+    private final FrameDescriptor descriptor;
+    private final Object identifier;
+    private final Object info;
+    private final int index;
+    @CompilationFinal private FrameSlotKind kind;
+
+    public FrameSlot(FrameDescriptor descriptor, Object identifier, Object info, int index, FrameSlotKind kind) {
+        this.descriptor = descriptor;
+        this.identifier = identifier;
+        this.info = info;
+        this.index = index;
+        this.kind = kind;
+    }
+
+    public Object getIdentifier() {
+        return identifier;
+    }
+
+    public Object getInfo() {
+        return info;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public FrameSlotKind getKind() {
+        return kind;
+    }
+
+    public void setKind(final FrameSlotKind kind) {
+        if (this.kind != kind) {
+            CompilerDirectives.transferToInterpreter();
+            this.kind = kind;
+            this.descriptor.updateVersion();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "[" + index + "," + identifier + "," + kind + "]";
+    }
+
+    public FrameDescriptor getFrameDescriptor() {
+        return this.descriptor;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+public enum FrameSlotKind {
+    Object,
+    Illegal,
+    Long,
+    Int,
+    Double,
+    Float,
+    Boolean,
+    Byte;
+
+    public final byte tag;
+
+    private FrameSlotKind() {
+        this.tag = (byte) ordinal();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotTypeException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Exception thrown if the frame slot type does not match the access type.
+ */
+public final class FrameSlotTypeException extends SlowPathException {
+
+    private static final long serialVersionUID = 6972120475215757452L;
+
+    public FrameSlotTypeException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+public final class FrameUtil {
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getObject(FrameSlot)
+     */
+    public static Object getObjectSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getObject(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getByte(FrameSlot)
+     */
+    public static byte getByteSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getByte(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getBoolean(FrameSlot)
+     */
+    public static boolean getBooleanSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getBoolean(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getInt(FrameSlot)
+     */
+    public static int getIntSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getInt(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getLong(FrameSlot)
+     */
+    public static long getLongSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getLong(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getDouble(FrameSlot)
+     */
+    public static double getDoubleSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getDouble(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Read a frame slot that is guaranteed to be of the desired kind (either previously checked by
+     * a guard or statically known).
+     *
+     * @param frameSlot the slot of the variable
+     * @throws IllegalStateException if the slot kind does not match
+     * @see Frame#getFloat(FrameSlot)
+     */
+    public static float getFloatSafe(Frame frame, FrameSlot frameSlot) {
+        try {
+            return frame.getFloat(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            throw new IllegalStateException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/MaterializedFrame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a materialized frame containing values of local variables of the guest language. It
+ * can be created using the {@link VirtualFrame#materialize()} method. Instances of this type are
+ * the only frame instances that may be stored in fields or cast to {@link java.lang.Object}.
+ */
+public interface MaterializedFrame extends Frame {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.frame;
+
+/**
+ * Represents a frame containing values of local variables of the guest language. Instances of this
+ * type must not be stored in a field or cast to {@link java.lang.Object}. If this is necessary, the
+ * frame must be explicitly converted into a materialized frame using the
+ * {@link VirtualFrame#materialize()} method.
+ */
+public interface VirtualFrame extends Frame {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+
+public abstract class AbstractAssumption implements Assumption {
+
+    protected final String name;
+    protected boolean isValid;
+
+    protected AbstractAssumption(String name) {
+        this.name = name;
+        this.isValid = true;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "Assumption(" + (isValid ? "valid" : "invalid") + ", name=" + name + ")";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.*;
+
+/**
+ * Communication between TruffleVM and TruffleLanguage API/SPI.
+ */
+public abstract class Accessor {
+    private static Accessor API;
+    private static Accessor SPI;
+    static {
+        TruffleLanguage lng = new TruffleLanguage(null) {
+            @Override
+            protected Object eval(Source code) throws IOException {
+                return null;
+            }
+
+            @Override
+            protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+                return null;
+            }
+
+            @Override
+            protected Object getLanguageGlobal() {
+                return null;
+            }
+
+            @Override
+            protected boolean isObjectOfLanguage(Object object) {
+                return false;
+            }
+
+            @Override
+            protected ToolSupportProvider getToolSupport() {
+                return null;
+            }
+
+            @Override
+            protected DebugSupportProvider getDebugSupport() {
+                return null;
+            }
+        };
+        lng.hashCode();
+    }
+
+    protected Accessor() {
+        if (this.getClass().getSimpleName().endsWith("API")) {
+            if (API != null) {
+                throw new IllegalStateException();
+            }
+            API = this;
+        } else {
+            if (SPI != null) {
+                throw new IllegalStateException();
+            }
+            SPI = this;
+        }
+    }
+
+    protected TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
+        return API.attachEnv(vm, langClazz, stdOut, stdErr, stdIn);
+    }
+
+    protected Object eval(TruffleLanguage l, Source s) throws IOException {
+        return API.eval(l, s);
+    }
+
+    protected Object importSymbol(TruffleVM vm, TruffleLanguage queryingLang, String globalName) {
+        return SPI.importSymbol(vm, queryingLang, globalName);
+    }
+
+    protected Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
+        return API.findExportedSymbol(l, globalName, onlyExplicit);
+    }
+
+    protected Object languageGlobal(TruffleLanguage l) {
+        return API.languageGlobal(l);
+    }
+
+    protected ToolSupportProvider getToolSupport(TruffleLanguage l) {
+        return API.getToolSupport(l);
+    }
+
+    protected DebugSupportProvider getDebugSupport(TruffleLanguage l) {
+        return API.getDebugSupport(l);
+    }
+
+    protected Object invoke(Object obj, Object[] args) throws IOException {
+        for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) {
+            return si.invoke(obj, args);
+        }
+        throw new IOException("No symbol invoker found!");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is an implementation-specific class. Do not use or instantiate it. Instead, use
+ * {@link TruffleRuntime#createAssumption()} to create an {@link Assumption}.
+ */
+final class DefaultAssumption extends AbstractAssumption {
+
+    DefaultAssumption(String name) {
+        super(name);
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        if (!isValid) {
+            throw new InvalidAssumptionException();
+        }
+    }
+
+    @Override
+    public void invalidate() {
+        isValid = false;
+    }
+
+    @Override
+    public boolean isValid() {
+        return isValid;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCallTarget.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is an implementation-specific class. Do not use or instantiate it. Instead, use
+ * {@link TruffleRuntime#createCallTarget(RootNode)} to create a {@link RootCallTarget}.
+ */
+public class DefaultCallTarget implements RootCallTarget {
+
+    private final RootNode rootNode;
+
+    protected DefaultCallTarget(RootNode function) {
+        this.rootNode = function;
+        this.rootNode.adoptChildren();
+        this.rootNode.applyInstrumentation();
+    }
+
+    @Override
+    public String toString() {
+        return rootNode.toString();
+    }
+
+    public final RootNode getRootNode() {
+        return rootNode;
+    }
+
+    @Override
+    public Object call(Object... args) {
+        final VirtualFrame frame = new DefaultVirtualFrame(getRootNode().getFrameDescriptor(), args);
+        FrameInstance oldCurrentFrame = defaultTruffleRuntime().setCurrentFrame(new FrameInstance() {
+
+            public Frame getFrame(FrameAccess access, boolean slowPath) {
+                return frame;
+            }
+
+            public boolean isVirtualFrame() {
+                return false;
+            }
+
+            public Node getCallNode() {
+                return null;
+            }
+
+            public CallTarget getCallTarget() {
+                return DefaultCallTarget.this;
+            }
+        });
+        try {
+            return getRootNode().execute(frame);
+        } finally {
+            defaultTruffleRuntime().setCurrentFrame(oldCurrentFrame);
+        }
+    }
+
+    private static DefaultTruffleRuntime defaultTruffleRuntime() {
+        return (DefaultTruffleRuntime) Truffle.getRuntime();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultCompilerOptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+
+public class DefaultCompilerOptions implements CompilerOptions {
+
+    public static DefaultCompilerOptions INSTANCE = new DefaultCompilerOptions();
+
+    public boolean supportsOption(String name) {
+        return false;
+    }
+
+    public void setOption(String name, Object value) {
+        throw new UnsupportedOperationException(String.format("Option %s is not supported by this runtime", name));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultDirectCallNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is runtime specific API. Do not use in a guest language.
+ */
+public final class DefaultDirectCallNode extends DirectCallNode {
+
+    private boolean inliningForced;
+
+    public DefaultDirectCallNode(CallTarget target) {
+        super(target);
+    }
+
+    @Override
+    public Object call(final VirtualFrame frame, Object[] arguments) {
+        final CallTarget currentCallTarget = defaultTruffleRuntime().getCurrentFrame().getCallTarget();
+        FrameInstance frameInstance = new FrameInstance() {
+
+            public Frame getFrame(FrameAccess access, boolean slowPath) {
+                return frame;
+            }
+
+            public boolean isVirtualFrame() {
+                return false;
+            }
+
+            public Node getCallNode() {
+                return DefaultDirectCallNode.this;
+            }
+
+            public CallTarget getCallTarget() {
+                return currentCallTarget;
+            }
+        };
+        defaultTruffleRuntime().pushFrame(frameInstance);
+        try {
+            return getCurrentCallTarget().call(arguments);
+        } finally {
+            defaultTruffleRuntime().popFrame();
+        }
+    }
+
+    @Override
+    public void forceInlining() {
+        inliningForced = true;
+    }
+
+    @Override
+    public boolean isInliningForced() {
+        return inliningForced;
+    }
+
+    @Override
+    public CallTarget getClonedCallTarget() {
+        return null;
+    }
+
+    @Override
+    public boolean cloneCallTarget() {
+        return false;
+    }
+
+    @Override
+    public boolean isCallTargetCloningAllowed() {
+        return false;
+    }
+
+    @Override
+    public boolean isInlinable() {
+        return false;
+    }
+
+    private static DefaultTruffleRuntime defaultTruffleRuntime() {
+        return (DefaultTruffleRuntime) Truffle.getRuntime();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultIndirectCallNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is runtime specific API. Do not use in a guest language.
+ */
+final class DefaultIndirectCallNode extends IndirectCallNode {
+    @Override
+    public Object call(final VirtualFrame frame, final CallTarget target, Object[] arguments) {
+        DefaultTruffleRuntime truffleRuntime = (DefaultTruffleRuntime) Truffle.getRuntime();
+        final CallTarget currentCallTarget = truffleRuntime.getCurrentFrame().getCallTarget();
+        FrameInstance frameInstance = new FrameInstance() {
+            public Frame getFrame(FrameAccess access, boolean slowPath) {
+                return frame;
+            }
+
+            public boolean isVirtualFrame() {
+                return false;
+            }
+
+            public Node getCallNode() {
+                return DefaultIndirectCallNode.this;
+            }
+
+            public CallTarget getCallTarget() {
+                return currentCallTarget;
+            }
+        };
+        truffleRuntime.pushFrame(frameInstance);
+        try {
+            return target.call(arguments);
+        } finally {
+            truffleRuntime.popFrame();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultLoopNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public final class DefaultLoopNode extends LoopNode {
+
+    @Child private RepeatingNode repeatNode;
+
+    public DefaultLoopNode(RepeatingNode repeatNode) {
+        this.repeatNode = repeatNode;
+    }
+
+    @Override
+    public RepeatingNode getRepeatingNode() {
+        return repeatNode;
+    }
+
+    @Override
+    public void executeLoop(VirtualFrame frame) {
+        while (repeatNode.executeRepeating(frame)) {
+            // Empty
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * This is an implementation-specific class. Do not use or instantiate it. Instead, use
+ * {@link TruffleRuntime#createMaterializedFrame(Object[])} or {@link Frame#materialize()} to create
+ * a {@link MaterializedFrame}.
+ */
+final class DefaultMaterializedFrame implements MaterializedFrame {
+
+    private final DefaultVirtualFrame wrapped;
+
+    DefaultMaterializedFrame(DefaultVirtualFrame wrapped) {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public Object[] getArguments() {
+        return wrapped.getArguments();
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getObject(slot);
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) {
+        wrapped.setObject(slot, value);
+    }
+
+    @Override
+    public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getByte(slot);
+    }
+
+    @Override
+    public void setByte(FrameSlot slot, byte value) {
+        wrapped.setByte(slot, value);
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getBoolean(slot);
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) {
+        wrapped.setBoolean(slot, value);
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getInt(slot);
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) {
+        wrapped.setInt(slot, value);
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getLong(slot);
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) {
+        wrapped.setLong(slot, value);
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getFloat(slot);
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) {
+        wrapped.setFloat(slot, value);
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
+        return wrapped.getDouble(slot);
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) {
+        wrapped.setDouble(slot, value);
+    }
+
+    @Override
+    public Object getValue(FrameSlot slot) {
+        return wrapped.getValue(slot);
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        return this;
+    }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return wrapped.getFrameDescriptor();
+    }
+
+    @Override
+    public boolean isObject(FrameSlot slot) {
+        return wrapped.isObject(slot);
+    }
+
+    @Override
+    public boolean isByte(FrameSlot slot) {
+        return wrapped.isByte(slot);
+    }
+
+    @Override
+    public boolean isBoolean(FrameSlot slot) {
+        return wrapped.isBoolean(slot);
+    }
+
+    @Override
+    public boolean isInt(FrameSlot slot) {
+        return wrapped.isInt(slot);
+    }
+
+    @Override
+    public boolean isLong(FrameSlot slot) {
+        return wrapped.isLong(slot);
+    }
+
+    @Override
+    public boolean isFloat(FrameSlot slot) {
+        return wrapped.isFloat(slot);
+    }
+
+    @Override
+    public boolean isDouble(FrameSlot slot) {
+        return wrapped.isDouble(slot);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.unsafe.*;
+
+/**
+ * Default implementation of the Truffle runtime if the virtual machine does not provide a better
+ * performing alternative.
+ * <p>
+ * This is an implementation-specific class. Do not use or instantiate it. Instead, use
+ * {@link Truffle#getRuntime()} to retrieve the current {@link TruffleRuntime}.
+ */
+public final class DefaultTruffleRuntime implements TruffleRuntime {
+
+    private final ThreadLocal<LinkedList<FrameInstance>> stackTraces = new ThreadLocal<>();
+    private final ThreadLocal<FrameInstance> currentFrames = new ThreadLocal<>();
+    private final Map<RootCallTarget, Void> callTargets = Collections.synchronizedMap(new WeakHashMap<RootCallTarget, Void>());
+
+    public DefaultTruffleRuntime() {
+    }
+
+    @Override
+    public String getName() {
+        return "Default Truffle Runtime";
+    }
+
+    @Override
+    public RootCallTarget createCallTarget(RootNode rootNode) {
+        DefaultCallTarget target = new DefaultCallTarget(rootNode);
+        rootNode.setCallTarget(target);
+        callTargets.put(target, null);
+        return target;
+    }
+
+    public DirectCallNode createDirectCallNode(CallTarget target) {
+        return new DefaultDirectCallNode(target);
+    }
+
+    public IndirectCallNode createIndirectCallNode() {
+        return new DefaultIndirectCallNode();
+    }
+
+    @Override
+    public VirtualFrame createVirtualFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
+        return new DefaultVirtualFrame(frameDescriptor, arguments);
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Object[] arguments) {
+        return createMaterializedFrame(arguments, new FrameDescriptor());
+    }
+
+    @Override
+    public MaterializedFrame createMaterializedFrame(Object[] arguments, FrameDescriptor frameDescriptor) {
+        return new DefaultMaterializedFrame(new DefaultVirtualFrame(frameDescriptor, arguments));
+    }
+
+    @Override
+    public CompilerOptions createCompilerOptions() {
+        return new DefaultCompilerOptions();
+    }
+
+    @Override
+    public Assumption createAssumption() {
+        return createAssumption(null);
+    }
+
+    @Override
+    public Assumption createAssumption(String name) {
+        return new DefaultAssumption(name);
+    }
+
+    private LinkedList<FrameInstance> getThreadLocalStackTrace() {
+        LinkedList<FrameInstance> result = stackTraces.get();
+        if (result == null) {
+            result = new LinkedList<>();
+            stackTraces.set(result);
+        }
+        return result;
+    }
+
+    public FrameInstance setCurrentFrame(FrameInstance newValue) {
+        FrameInstance oldValue = currentFrames.get();
+        currentFrames.set(newValue);
+        return oldValue;
+    }
+
+    public void pushFrame(FrameInstance frame) {
+        getThreadLocalStackTrace().addFirst(frame);
+    }
+
+    public void popFrame() {
+        getThreadLocalStackTrace().removeFirst();
+    }
+
+    @Override
+    public <T> T iterateFrames(FrameInstanceVisitor<T> visitor) {
+        T result = null;
+        for (FrameInstance frameInstance : getThreadLocalStackTrace()) {
+            result = visitor.visitFrame(frameInstance);
+            if (result != null) {
+                return result;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public FrameInstance getCallerFrame() {
+        return getThreadLocalStackTrace().peekFirst();
+    }
+
+    @Override
+    public Collection<RootCallTarget> getCallTargets() {
+        return Collections.unmodifiableSet(callTargets.keySet());
+    }
+
+    @Override
+    public FrameInstance getCurrentFrame() {
+        return currentFrames.get();
+    }
+
+    public <T> T getCapability(Class<T> capability) {
+        if (capability == UnsafeAccessFactory.class) {
+            return capability.cast(new UnsafeAccessFactoryImpl());
+        }
+        return null;
+    }
+
+    public void notifyTransferToInterpreter() {
+    }
+
+    public LoopNode createLoopNode(RepeatingNode repeating) {
+        if (!(repeating instanceof Node)) {
+            throw new IllegalArgumentException("Repeating node must be of type Node.");
+        }
+        return new DefaultLoopNode(repeating);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * This is an implementation-specific class. Do not use or instantiate it. Instead, use
+ * {@link TruffleRuntime#createVirtualFrame(Object[], FrameDescriptor)} to create a
+ * {@link VirtualFrame}.
+ */
+final class DefaultVirtualFrame implements VirtualFrame {
+
+    private final FrameDescriptor descriptor;
+    private final Object[] arguments;
+    private Object[] locals;
+    private byte[] tags;
+
+    DefaultVirtualFrame(FrameDescriptor descriptor, Object[] arguments) {
+        this.descriptor = descriptor;
+        this.arguments = arguments;
+        this.locals = new Object[descriptor.getSize()];
+        Arrays.fill(locals, descriptor.getDefaultValue());
+        this.tags = new byte[descriptor.getSize()];
+    }
+
+    @Override
+    public Object[] getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public MaterializedFrame materialize() {
+        return new DefaultMaterializedFrame(this);
+    }
+
+    @Override
+    public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Object);
+        return locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setObject(FrameSlot slot, Object value) {
+        verifySet(slot, FrameSlotKind.Object);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Byte);
+        return (byte) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setByte(FrameSlot slot, byte value) {
+        verifySet(slot, FrameSlotKind.Byte);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Boolean);
+        return (boolean) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setBoolean(FrameSlot slot, boolean value) {
+        verifySet(slot, FrameSlotKind.Boolean);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public int getInt(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Int);
+        return (int) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setInt(FrameSlot slot, int value) {
+        verifySet(slot, FrameSlotKind.Int);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public long getLong(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Long);
+        return (long) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setLong(FrameSlot slot, long value) {
+        verifySet(slot, FrameSlotKind.Long);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Float);
+        return (float) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setFloat(FrameSlot slot, float value) {
+        verifySet(slot, FrameSlotKind.Float);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
+        verifyGet(slot, FrameSlotKind.Double);
+        return (double) locals[slot.getIndex()];
+    }
+
+    @Override
+    public void setDouble(FrameSlot slot, double value) {
+        verifySet(slot, FrameSlotKind.Double);
+        locals[slot.getIndex()] = value;
+    }
+
+    @Override
+    public FrameDescriptor getFrameDescriptor() {
+        return this.descriptor;
+    }
+
+    @Override
+    public Object getValue(FrameSlot slot) {
+        int slotIndex = getSlotIndexChecked(slot);
+        return locals[slotIndex];
+    }
+
+    private int getSlotIndexChecked(FrameSlot slot) {
+        int slotIndex = slot.getIndex();
+        if (slotIndex >= tags.length) {
+            if (!resize()) {
+                throw new IllegalArgumentException(String.format("The frame slot '%s' is not known by the frame descriptor.", slot));
+            }
+        }
+        return slotIndex;
+    }
+
+    private void verifySet(FrameSlot slot, FrameSlotKind accessKind) {
+        int slotIndex = getSlotIndexChecked(slot);
+        tags[slotIndex] = (byte) accessKind.ordinal();
+    }
+
+    private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
+        int slotIndex = getSlotIndexChecked(slot);
+        byte tag = tags[slotIndex];
+        if (accessKind == FrameSlotKind.Object ? tag != 0 : tag != accessKind.ordinal()) {
+            throw new FrameSlotTypeException();
+        }
+    }
+
+    private boolean resize() {
+        int oldSize = tags.length;
+        int newSize = descriptor.getSize();
+        if (newSize > oldSize) {
+            locals = Arrays.copyOf(locals, newSize);
+            Arrays.fill(locals, oldSize, newSize, descriptor.getDefaultValue());
+            tags = Arrays.copyOf(tags, newSize);
+            return true;
+        }
+        return false;
+    }
+
+    private byte getTag(FrameSlot slot) {
+        int slotIndex = getSlotIndexChecked(slot);
+        return tags[slotIndex];
+    }
+
+    @Override
+    public boolean isObject(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Object.ordinal();
+    }
+
+    @Override
+    public boolean isByte(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Byte.ordinal();
+    }
+
+    @Override
+    public boolean isBoolean(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Boolean.ordinal();
+    }
+
+    @Override
+    public boolean isInt(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Int.ordinal();
+    }
+
+    @Override
+    public boolean isLong(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Long.ordinal();
+    }
+
+    @Override
+    public boolean isFloat(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Float.ordinal();
+    }
+
+    @Override
+    public boolean isDouble(FrameSlot slot) {
+        return getTag(slot) == FrameSlotKind.Double.ordinal();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/SymbolInvoker.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import java.io.*;
+
+/**
+ * XXX: Temporary class to make unit tests pass without messing with Message implementations and
+ * associated nodes too much.
+ */
+public abstract class SymbolInvoker {
+    protected abstract Object invoke(Object symbol, Object... args) throws IOException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/UnsafeAccessFactoryImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.impl;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.unsafe.*;
+
+final class UnsafeAccessFactoryImpl implements UnsafeAccessFactory {
+    public UnsafeAccess createUnsafeAccess(final Unsafe unsafe) {
+        return new UnsafeAccessImpl(unsafe);
+    }
+
+    private static final class UnsafeAccessImpl implements UnsafeAccess {
+        private final Unsafe unsafe;
+
+        private UnsafeAccessImpl(Unsafe unsafe) {
+            this.unsafe = unsafe;
+        }
+
+        @SuppressWarnings("unchecked")
+        public <T> T uncheckedCast(Object value, Class<T> type, boolean condition, boolean nonNull) {
+            return (T) value;
+        }
+
+        public void putShort(Object receiver, long offset, short value, Object locationIdentity) {
+            unsafe.putShort(receiver, offset, value);
+        }
+
+        public void putObject(Object receiver, long offset, Object value, Object locationIdentity) {
+            unsafe.putObject(receiver, offset, value);
+        }
+
+        public void putLong(Object receiver, long offset, long value, Object locationIdentity) {
+            unsafe.putLong(receiver, offset, value);
+        }
+
+        public void putInt(Object receiver, long offset, int value, Object locationIdentity) {
+            unsafe.putInt(receiver, offset, value);
+        }
+
+        public void putFloat(Object receiver, long offset, float value, Object locationIdentity) {
+            unsafe.putFloat(receiver, offset, value);
+        }
+
+        public void putDouble(Object receiver, long offset, double value, Object locationIdentity) {
+            unsafe.putDouble(receiver, offset, value);
+        }
+
+        public void putByte(Object receiver, long offset, byte value, Object locationIdentity) {
+            unsafe.putByte(receiver, offset, value);
+        }
+
+        public void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity) {
+            unsafe.putBoolean(receiver, offset, value);
+        }
+
+        public short getShort(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getShort(receiver, offset);
+        }
+
+        public Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getObject(receiver, offset);
+        }
+
+        public long getLong(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getLong(receiver, offset);
+        }
+
+        public int getInt(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getInt(receiver, offset);
+        }
+
+        public float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getFloat(receiver, offset);
+        }
+
+        public double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getDouble(receiver, offset);
+        }
+
+        public byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getByte(receiver, offset);
+        }
+
+        public boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity) {
+            return unsafe.getBoolean(receiver, offset);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import java.io.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Access to AST-based debugging support, which is could be language implementation specific in the
+ * details chosen to be presented.
+ * <p>
+ * <strong>WARNING:</strong> this interface is under development and will change substantially.
+ */
+public interface ASTPrinter {
+
+    /**
+     * Prints a textual AST display, one line per node, with nesting.
+     *
+     * @param p
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    void printTree(PrintWriter p, Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     *
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     * @param markNode a node to mark with a textual arrow prefix, if present.
+     */
+    String printTreeToString(Node node, int maxDepth, Node markNode);
+
+    /**
+     * Creates a textual AST display, one line per node, with nesting.
+     *
+     * @param node the root node of the display.
+     * @param maxDepth the maximum number of levels to print below the root
+     */
+    String printTreeToString(Node node, int maxDepth);
+
+    /**
+     * Creates a textual display describing a single (non-wrapper) node, including instrumentation
+     * status: if Probed, and any tags.
+     */
+    String printNodeWithInstrumentation(Node node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTProber.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Enables instrumentation by attaching {@linkplain Probe Probes} to some nodes in a (newly created,
+ * not yet executed) AST.
+ *
+ * @see Probe
+ * @see Probe#addProbeListener(ProbeListener)
+ */
+public interface ASTProber {
+
+    /**
+     * Walk the AST starting at a node and enable instrumentation at selected nodes by attaching
+     * {@linkplain Probe Probes} to them. Ignore {@linkplain Node#isInstrumentable()
+     * non-instrumentable} nodes.
+     */
+    void probeAST(Node node);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Listener for receiving the result a client-provided {@linkplain AdvancedInstrumentRoot AST
+ * fragment}, when executed by a
+ * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+ * Advanced Instrument}.
+ *
+ * @see Instrument
+ * @see AdvancedInstrumentRoot
+ * @see AdvancedInstrumentRootFactory
+ */
+public interface AdvancedInstrumentResultListener {
+
+    /**
+     * Notifies listener that a client-provided {@linkplain AdvancedInstrumentRoot AST fragment} has
+     * been executed by an
+     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+     * Advanced Instrument} with the specified result, possibly {@code null}.
+     * <p>
+     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
+     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
+     *
+     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
+     *            attached
+     * @param vFrame execution frame at the guest-language AST node
+     * @param result the result of this AST fragment's execution
+     */
+    void notifyResult(Node node, VirtualFrame vFrame, Object result);
+
+    /**
+     * Notifies listener that execution of client-provided {@linkplain AdvancedInstrumentRoot AST
+     * fragment} filed during execution by a @linkplain
+     * Instrument#create(AdvancedInstrumentRootFactory, String) Advanced Instrument}.
+     * <p>
+     * <strong>Note: </strong> Truffle will attempt to optimize implementations through partial
+     * evaluation; annotate with {@link TruffleBoundary} if this should not be permitted.
+     *
+     * @param node the guest-language AST node to which the host Instrument's {@link Probe} is
+     *            attached
+     * @param vFrame execution frame at the guest-language AST node
+     * @param ex the exception
+     */
+    void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Root of a client-provided AST fragment that can be executed efficiently, subject to full Truffle
+ * optimization, by an
+ * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+ * Advanced Instrument}.
+ *
+ * @see Instrument
+ * @see AdvancedInstrumentRootFactory
+ * @see AdvancedInstrumentResultListener
+ */
+public abstract class AdvancedInstrumentRoot extends Node implements InstrumentationNode {
+
+    /**
+     * Executes this AST fragment on behalf of a client {@link Instrument}, just before the
+     * guest-language AST node to which the {@link Probe} holding the Instrument is executed.
+     *
+     * @param node the guest-language AST node to which the host Instrument's Probe is attached
+     * @param vFrame execution frame at the guest-language AST node
+     * @return the result of this AST fragment's execution
+     */
+    public abstract Object executeRoot(Node node, VirtualFrame vFrame);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Creator of {@linkplain AdvancedInstrumentRoot AST fragments} suitable for efficient execution,
+ * subject to full Truffle optimization, by an
+ * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+ * Advanced Instrument}.
+ *
+ * @see Instrument
+ * @see AdvancedInstrumentRoot
+ */
+public interface AdvancedInstrumentRootFactory {
+
+    /**
+     * Provider of {@linkplain AdvancedInstrumentRoot AST fragment} instances to be executed by the
+     * Instrumentation Framework at a {@linkplain Probe Probed} site in a guest-language AST.
+     * <p>
+     * <strong>Notes:</strong>
+     * <ul>
+     * <li>Once the factory has produced an AST fragment at a particular {@linkplain Node AST Node},
+     * it will not be called again at that Node.</li>
+     * <li>In some use cases, for example to implement a breakpoint at a specific program location,
+     * the Probe argument will be the same for every call. Each Node argument will represent the
+     * same program location associated with the Probe, but in different clones of the AST.</li>
+     * <li>In other use cases, for example to implement a breakpoint at any Node with a particular
+     * {@linkplain SyntaxTag tag}, both the Probe and Node argument may differ. Implementations that
+     * are sensitive to the lexical context in which the AST fragment will be evaluated must take
+     * care to build a new, possibly different AST fragment for each request.</li>
+     * </ul>
+     *
+     * @param probe the Probe to which the Instrument requesting the AST fragment is attached
+     * @param node the guest-language AST location that is the context in which the requesting
+     *            Instrument must execute the AST fragment.
+     * @return a newly created AST fragment suitable for execution, via instrumentation, in the
+     *         execution context of the specified guest-language AST site.
+     */
+    AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrument.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+// TODO (mlvdv) these statics should not be global.  Move them to some kind of context.
+// TODO (mlvdv) migrate factory (together with Probe)? break out nested classes?
+
+/**
+ * A <em>binding</em> between:
+ * <ol>
+ * <li>A {@link Probe}: a source of <em>execution events</em> taking place at a program location in
+ * an executing Truffle AST, and</li>
+ * <li>A <em>listener</em>: a consumer of execution events on behalf of an external client.
+ * </ol>
+ * <p>
+ * Client-oriented documentation for the use of Instruments is available online at <a
+ * HREF="https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events"
+ * >https://wiki.openjdk.java.net/display/Graal/Listening+for+Execution+Events</a>
+ * <p>
+ * The implementation of Instruments is complicated by the requirement that Truffle be able to clone
+ * ASTs at any time. In particular, any instrumentation-supporting Nodes that have been attached to
+ * an AST must be cloned along with the AST: AST clones are not permitted to share Nodes.
+ * <p>
+ * AST cloning is intended to be as <em>transparent</em> as possible to clients. This is encouraged
+ * by providing the {@link SimpleInstrumentListener} for clients that need know nothing more than
+ * the properties associated with a Probe: it's {@link SourceSection} and any associated instances
+ * of {@link SyntaxTag}.
+ * <p>
+ * AST cloning is <em>not transparent</em> to clients that use the
+ * {@link StandardInstrumentListener}, since those event methods identify the concrete Node instance
+ * (and thus the AST instance) where the event takes place.
+ * <p>
+ * <h4>Implementation Notes: the Life Cycle of an {@link Instrument} at a {@link Probe}</h4>
+ * <p>
+ * <ul>
+ * <li>A new Instrument is created in permanent association with a client-provided
+ * <em>listener.</em></li>
+ *
+ * <li>Multiple Instruments may share a single listener.</li>
+ *
+ * <li>An Instrument does nothing until it is {@linkplain Probe#attach(Instrument) attached} to a
+ * Probe, at which time the Instrument begins routing execution events from the Probe's AST location
+ * to the Instrument's listener.</li>
+ *
+ * <li>Neither Instruments nor Probes are {@link Node}s.</li>
+ *
+ * <li>A Probe has a single source-based location in an AST, but manages a separate
+ * <em>instrumentation chain</em> of Nodes at the equivalent location in each clone of the AST.</li>
+ * <li>When a probed AST is cloned, the instrumentation chain associated with each Probe is cloned
+ * along with the rest of the AST.</li>
+ *
+ * <li>When a new Instrument (for example an instance of {@link SimpleInstrument} is attached to a
+ * Probe, the Instrument inserts a new instance of its private Node type,
+ * {@link SimpleInstrument.SimpleInstrumentNode}, into <em>each of the instrument chains</em>
+ * managed by the Probe, i.e. one node instance per existing clone of the AST.</li>
+ *
+ * <li>If an Instrument is attached to a Probe in an AST that subsequently gets cloned, then the
+ * Instrument's private Node type will be cloned along with the rest of the the AST.</li>
+ * <li>Each Instrument's private Node type is a dynamic inner class whose only state is in the
+ * shared (outer) Instrument instance; that state includes a reference to the Instrument's listener.
+ * </li>
+ *
+ * <li>When an Instrument that has been attached to a Probe is {@linkplain #dispose() disposed}, the
+ * Instrument searches every instrument chain associated with the Probe and removes the instance of
+ * its private Node type.</li>
+ *
+ * <li>Attaching and disposing an Instrument at a Probe <em>deoptimizes</em> any compilations of the
+ * AST.</li>
+ *
+ * </ul>
+ *
+ * @see Probe
+ * @see TruffleEvents
+ */
+public abstract class Instrument {
+
+    /**
+     * Creates a <em>Simple Instrument</em>: this Instrument routes execution events to a
+     * client-provided listener.
+     *
+     * @param listener a listener for execution events
+     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
+     * @return a new instrument, ready for attachment at a probe
+     */
+    public static Instrument create(SimpleInstrumentListener listener, String instrumentInfo) {
+        return new SimpleInstrument(listener, instrumentInfo);
+    }
+
+    /**
+     * Creates a <em>Standard Instrument</em>: this Instrument routes execution events, together
+     * with access to Truffle execution state, to a client-provided listener.
+     *
+     * @param standardListener a listener for execution events and execution state
+     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
+     * @return a new instrument, ready for attachment at a probe
+     */
+    public static Instrument create(StandardInstrumentListener standardListener, String instrumentInfo) {
+        return new StandardInstrument(standardListener, instrumentInfo);
+    }
+
+    /**
+     * Creates an <em>Advanced Instrument</em>: this Instrument executes efficiently, subject to
+     * full Truffle optimization, a client-provided AST fragment every time the Probed node is
+     * entered.
+     * <p>
+     * Any {@link RuntimeException} thrown by execution of the fragment is caught by the framework
+     * and reported to the listener; there is no other notification.
+     *
+     * @param resultListener optional client callback for results/failure notification
+     * @param rootFactory provider of AST fragments on behalf of the client
+     * @param requiredResultType optional requirement, any non-assignable result is reported to the
+     *            the listener, if any, as a failure
+     * @param instrumentInfo optional description of the instrument's role, intended for debugging.
+     * @return a new instrument, ready for attachment at a probe
+     */
+    public static Instrument create(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
+        return new AdvancedInstrument(resultListener, rootFactory, requiredResultType, instrumentInfo);
+    }
+
+    // TODO (mlvdv) experimental
+    /**
+     * For implementation testing.
+     */
+    public static Instrument create(TruffleOptListener listener) {
+        return new TruffleOptInstrument(listener, null);
+    }
+
+    /**
+     * Has this instrument been disposed? stays true once set.
+     */
+    private boolean isDisposed = false;
+
+    protected Probe probe = null;
+
+    /**
+     * Optional documentation, mainly for debugging.
+     */
+    private final String instrumentInfo;
+
+    private Instrument(String instrumentInfo) {
+        this.instrumentInfo = instrumentInfo;
+    }
+
+    /**
+     * Gets the {@link Probe} to which this Instrument is currently attached: {@code null} if not
+     * yet attached to a Probe or if this Instrument has been {@linkplain #dispose() disposed}.
+     */
+    public Probe getProbe() {
+        return probe;
+    }
+
+    /**
+     * Removes this Instrument from the Probe to which it attached and renders this Instrument
+     * inert.
+     *
+     * @throws IllegalStateException if this instrument has already been disposed
+     */
+    public void dispose() throws IllegalStateException {
+        if (isDisposed) {
+            throw new IllegalStateException("Attempt to dispose an already disposed Instrumennt");
+        }
+        if (probe != null) {
+            // It's attached
+            probe.disposeInstrument(this);
+            probe = null;
+        }
+        this.isDisposed = true;
+    }
+
+    /**
+     * For internal implementation only.
+     */
+    void setAttachedTo(Probe probe) {
+        this.probe = probe;
+    }
+
+    /**
+     * Has this instrument been disposed and rendered unusable?
+     */
+    boolean isDisposed() {
+        return isDisposed;
+    }
+
+    abstract AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode);
+
+    /**
+     * Removes this instrument from an instrument chain.
+     */
+    abstract AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode);
+
+    /**
+     * An instrument that propagates events to an instance of {@link SimpleInstrumentListener}.
+     */
+    private static final class SimpleInstrument extends Instrument {
+
+        /**
+         * Tool-supplied listener for events.
+         */
+        private final SimpleInstrumentListener simpleListener;
+
+        private SimpleInstrument(SimpleInstrumentListener simpleListener, String instrumentInfo) {
+            super(instrumentInfo);
+            this.simpleListener = simpleListener;
+        }
+
+        @Override
+        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
+            return new SimpleInstrumentNode(nextNode);
+        }
+
+        @Override
+        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
+            boolean found = false;
+            if (instrumentNode != null) {
+                if (instrumentNode.getInstrument() == this) {
+                    // Found the match at the head of the chain
+                    return instrumentNode.nextInstrumentNode;
+                }
+                // Match not at the head of the chain; remove it.
+                found = instrumentNode.removeFromChain(SimpleInstrument.this);
+            }
+            if (!found) {
+                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
+            }
+            return instrumentNode;
+        }
+
+        /**
+         * Node that implements a {@link SimpleInstrument} in a particular AST.
+         */
+        @NodeInfo(cost = NodeCost.NONE)
+        private final class SimpleInstrumentNode extends AbstractInstrumentNode {
+
+            private SimpleInstrumentNode(AbstractInstrumentNode nextNode) {
+                super(nextNode);
+            }
+
+            public void enter(Node node, VirtualFrame vFrame) {
+                SimpleInstrument.this.simpleListener.enter(SimpleInstrument.this.probe);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.enter(node, vFrame);
+                }
+            }
+
+            public void returnVoid(Node node, VirtualFrame vFrame) {
+                SimpleInstrument.this.simpleListener.returnVoid(SimpleInstrument.this.probe);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnVoid(node, vFrame);
+                }
+            }
+
+            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
+                SimpleInstrument.this.simpleListener.returnValue(SimpleInstrument.this.probe, result);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnValue(node, vFrame, result);
+                }
+            }
+
+            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+                SimpleInstrument.this.simpleListener.returnExceptional(SimpleInstrument.this.probe, exception);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
+                }
+            }
+
+            public String instrumentationInfo() {
+                final String info = getInstrumentInfo();
+                return info != null ? info : simpleListener.getClass().getSimpleName();
+            }
+        }
+    }
+
+    /**
+     * An instrument that propagates events to an instance of {@link StandardInstrumentListener}.
+     */
+    private static final class StandardInstrument extends Instrument {
+
+        /**
+         * Tool-supplied listener for AST events.
+         */
+        private final StandardInstrumentListener standardListener;
+
+        private StandardInstrument(StandardInstrumentListener standardListener, String instrumentInfo) {
+            super(instrumentInfo);
+            this.standardListener = standardListener;
+        }
+
+        @Override
+        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
+            return new StandardInstrumentNode(nextNode);
+        }
+
+        @Override
+        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
+            boolean found = false;
+            if (instrumentNode != null) {
+                if (instrumentNode.getInstrument() == this) {
+                    // Found the match at the head of the chain
+                    return instrumentNode.nextInstrumentNode;
+                }
+                // Match not at the head of the chain; remove it.
+                found = instrumentNode.removeFromChain(StandardInstrument.this);
+            }
+            if (!found) {
+                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
+            }
+            return instrumentNode;
+        }
+
+        /**
+         * Node that implements a {@link StandardInstrument} in a particular AST.
+         */
+        @NodeInfo(cost = NodeCost.NONE)
+        private final class StandardInstrumentNode extends AbstractInstrumentNode {
+
+            private StandardInstrumentNode(AbstractInstrumentNode nextNode) {
+                super(nextNode);
+            }
+
+            public void enter(Node node, VirtualFrame vFrame) {
+                standardListener.enter(StandardInstrument.this.probe, node, vFrame);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.enter(node, vFrame);
+                }
+            }
+
+            public void returnVoid(Node node, VirtualFrame vFrame) {
+                standardListener.returnVoid(StandardInstrument.this.probe, node, vFrame);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnVoid(node, vFrame);
+                }
+            }
+
+            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
+                standardListener.returnValue(StandardInstrument.this.probe, node, vFrame, result);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnValue(node, vFrame, result);
+                }
+            }
+
+            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+                standardListener.returnExceptional(StandardInstrument.this.probe, node, vFrame, exception);
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
+                }
+            }
+
+            public String instrumentationInfo() {
+                final String info = getInstrumentInfo();
+                return info != null ? info : standardListener.getClass().getSimpleName();
+            }
+        }
+    }
+
+    /**
+     * An instrument that allows clients to provide an AST fragment to be executed directly from
+     * within a Probe's <em>instrumentation chain</em>, and thus directly in the executing Truffle
+     * AST with potential for full optimization.
+     */
+    private static final class AdvancedInstrument extends Instrument {
+
+        private final AdvancedInstrumentResultListener resultListener;
+        private final AdvancedInstrumentRootFactory rootFactory;
+        private final Class<?> requiredResultType;
+
+        private AdvancedInstrument(AdvancedInstrumentResultListener resultListener, AdvancedInstrumentRootFactory rootFactory, Class<?> requiredResultType, String instrumentInfo) {
+            super(instrumentInfo);
+            this.resultListener = resultListener;
+            this.rootFactory = rootFactory;
+            this.requiredResultType = requiredResultType;
+        }
+
+        @Override
+        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
+            return new AdvancedInstrumentNode(nextNode);
+        }
+
+        @Override
+        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
+            boolean found = false;
+            if (instrumentNode != null) {
+                if (instrumentNode.getInstrument() == this) {
+                    // Found the match at the head of the chain
+                    return instrumentNode.nextInstrumentNode;
+                }
+                // Match not at the head of the chain; remove it.
+                found = instrumentNode.removeFromChain(AdvancedInstrument.this);
+            }
+            if (!found) {
+                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
+            }
+            return instrumentNode;
+        }
+
+        /**
+         * Node that implements a {@link AdvancedInstrument} in a particular AST.
+         */
+        @NodeInfo(cost = NodeCost.NONE)
+        private final class AdvancedInstrumentNode extends AbstractInstrumentNode {
+
+            @Child private AdvancedInstrumentRoot instrumentRoot;
+
+            private AdvancedInstrumentNode(AbstractInstrumentNode nextNode) {
+                super(nextNode);
+            }
+
+            public void enter(Node node, VirtualFrame vFrame) {
+                if (instrumentRoot == null) {
+                    try {
+                        final AdvancedInstrumentRoot newInstrumentRoot = AdvancedInstrument.this.rootFactory.createInstrumentRoot(AdvancedInstrument.this.probe, node);
+                        if (newInstrumentRoot != null) {
+                            instrumentRoot = newInstrumentRoot;
+                            adoptChildren();
+                            AdvancedInstrument.this.probe.invalidateProbeUnchanged();
+                        }
+                    } catch (RuntimeException ex) {
+                        if (resultListener != null) {
+                            resultListener.notifyFailure(node, vFrame, ex);
+                        }
+                    }
+                }
+                if (instrumentRoot != null) {
+                    try {
+                        final Object result = instrumentRoot.executeRoot(node, vFrame);
+                        if (resultListener != null) {
+                            checkResultType(result);
+                            resultListener.notifyResult(node, vFrame, result);
+                        }
+                    } catch (RuntimeException ex) {
+                        if (resultListener != null) {
+                            resultListener.notifyFailure(node, vFrame, ex);
+                        }
+                    }
+                }
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.enter(node, vFrame);
+                }
+            }
+
+            private void checkResultType(Object result) {
+                if (requiredResultType == null) {
+                    return;
+                }
+                if (result == null) {
+                    throw new RuntimeException("Instrument result null: " + requiredResultType.getSimpleName() + " is required");
+                }
+                if (!(requiredResultType.isAssignableFrom(result.getClass()))) {
+                    throw new RuntimeException("Instrument result " + result.toString() + " not assignable to " + requiredResultType.getSimpleName());
+                }
+            }
+
+            public void returnVoid(Node node, VirtualFrame vFrame) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnVoid(node, vFrame);
+                }
+            }
+
+            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnValue(node, vFrame, result);
+                }
+            }
+
+            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
+                }
+            }
+
+            public String instrumentationInfo() {
+                final String info = getInstrumentInfo();
+                return info != null ? info : rootFactory.getClass().getSimpleName();
+            }
+        }
+    }
+
+    public interface TruffleOptListener {
+        void notifyIsCompiled(boolean isCompiled);
+    }
+
+    private static final class TruffleOptInstrument extends Instrument {
+
+        private final TruffleOptListener toolOptListener;
+
+        private TruffleOptInstrument(TruffleOptListener listener, String instrumentInfo) {
+            super(instrumentInfo);
+            this.toolOptListener = listener;
+        }
+
+        @Override
+        AbstractInstrumentNode addToChain(AbstractInstrumentNode nextNode) {
+            return new TruffleOptInstrumentNode(nextNode);
+        }
+
+        @Override
+        AbstractInstrumentNode removeFromChain(AbstractInstrumentNode instrumentNode) {
+            boolean found = false;
+            if (instrumentNode != null) {
+                if (instrumentNode.getInstrument() == this) {
+                    // Found the match at the head of the chain
+                    return instrumentNode.nextInstrumentNode;
+                }
+                // Match not at the head of the chain; remove it.
+                found = instrumentNode.removeFromChain(TruffleOptInstrument.this);
+            }
+            if (!found) {
+                throw new IllegalStateException("Couldn't find instrument node to remove: " + this);
+            }
+            return instrumentNode;
+        }
+
+        @NodeInfo(cost = NodeCost.NONE)
+        private final class TruffleOptInstrumentNode extends AbstractInstrumentNode {
+
+            private boolean isCompiled;
+
+            private TruffleOptInstrumentNode(AbstractInstrumentNode nextNode) {
+                super(nextNode);
+                this.isCompiled = CompilerDirectives.inCompiledCode();
+            }
+
+            public void enter(Node node, VirtualFrame vFrame) {
+                if (this.isCompiled != CompilerDirectives.inCompiledCode()) {
+                    this.isCompiled = CompilerDirectives.inCompiledCode();
+                    TruffleOptInstrument.this.toolOptListener.notifyIsCompiled(this.isCompiled);
+                }
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.enter(node, vFrame);
+                }
+            }
+
+            public void returnVoid(Node node, VirtualFrame vFrame) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnVoid(node, vFrame);
+                }
+            }
+
+            public void returnValue(Node node, VirtualFrame vFrame, Object result) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnValue(node, vFrame, result);
+                }
+            }
+
+            public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+                if (nextInstrumentNode != null) {
+                    nextInstrumentNode.returnExceptional(node, vFrame, exception);
+                }
+            }
+
+            public String instrumentationInfo() {
+                final String info = getInstrumentInfo();
+                return info != null ? info : toolOptListener.getClass().getSimpleName();
+            }
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    abstract class AbstractInstrumentNode extends Node implements TruffleEvents, InstrumentationNode {
+
+        @Child protected AbstractInstrumentNode nextInstrumentNode;
+
+        protected AbstractInstrumentNode(AbstractInstrumentNode nextNode) {
+            this.nextInstrumentNode = nextNode;
+        }
+
+        @Override
+        public boolean isInstrumentable() {
+            return false;
+        }
+
+        /**
+         * Gets the instrument that created this node.
+         */
+        private Instrument getInstrument() {
+            return Instrument.this;
+        }
+
+        /**
+         * Removes the node from this chain that was added by a particular instrument, assuming that
+         * the head of the chain is not the one to be replaced. This is awkward, but is required
+         * because {@link Node#replace(Node)} won't take a {@code null} argument. This doesn't work
+         * for the tail of the list, which would be replacing itself with null. So the replacement
+         * must be directed the parent of the node being removed.
+         */
+        private boolean removeFromChain(Instrument instrument) {
+            assert getInstrument() != instrument;
+            if (nextInstrumentNode == null) {
+                return false;
+            }
+            if (nextInstrumentNode.getInstrument() == instrument) {
+                // Next is the one to remove
+                if (nextInstrumentNode.nextInstrumentNode == null) {
+                    // Next is at the tail; just forget
+                    nextInstrumentNode = null;
+                } else {
+                    // Replace next with its successor
+                    nextInstrumentNode.replace(nextInstrumentNode.nextInstrumentNode);
+                }
+                return true;
+            }
+            return nextInstrumentNode.removeFromChain(instrument);
+        }
+
+        protected String getInstrumentInfo() {
+            return Instrument.this.instrumentInfo;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+public class InstrumentationException extends Exception {
+
+    public InstrumentationException(RuntimeException ex) {
+        super(ex);
+    }
+
+    private static final long serialVersionUID = 447857066220935502L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A marker interface for Truffle {@linkplain Node nodes} that internally implement the
+ * <em>Instrumentation Framework</em>. Such nodes should not be part of any Guest Language execution
+ * semantics, and should in general not be visible to ordinary Instrumentation clients.
+ */
+public interface InstrumentationNode {
+
+    /**
+     * A short description of the particular role played by the node, intended to support debugging.
+     */
+    String instrumentationInfo();
+
+    /**
+     * Events that propagate through the {@linkplain InstrumentationNode implementation nodes} of
+     * the Instrumentation Framework, not visible in this form to Instrumentation clients.
+     */
+    interface TruffleEvents {
+
+        /**
+         * An AST node's execute method is about to be called.
+         */
+        void enter(Node node, VirtualFrame vFrame);
+
+        /**
+         * An AST Node's {@code void}-valued execute method has just returned.
+         */
+        void returnVoid(Node node, VirtualFrame vFrame);
+
+        /**
+         * An AST Node's execute method has just returned a value (boxed if primitive).
+         */
+        void returnValue(Node node, VirtualFrame vFrame, Object result);
+
+        /**
+         * An AST Node's execute method has just thrown an exception.
+         */
+        void returnExceptional(Node node, VirtualFrame vFrame, Exception exception);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+/**
+ * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language
+ * program execution.
+ * <p>
+ * Tools share a common <em>life cycle</em>:
+ * <ul>
+ * <li>A newly created tool is inert until {@linkplain #install() installed}.</li>
+ * <li>An installed tool becomes <em>enabled</em> and immediately begins installing
+ * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from
+ * those instruments</li>
+ * <li>A tool may only be installed once.</li>
+ * <li>It should be possible to install multiple instances of a tool, possibly (but not necessarily)
+ * configured differently with respect to what data is being collected.</li>
+ * <li>Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled}
+ * arbitrarily.</li>
+ * <li>A disabled tool:
+ * <ul>
+ * <li>Collects no data;</li>
+ * <li>Retains existing AST instrumentation;</li>
+ * <li>Continues to instrument newly created ASTs; and</li>
+ * <li>Retains previously collected data.</li>
+ * </ul>
+ * </li>
+ * <li>An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool
+ * installed but with all previously collected data removed.</li>
+ * <li>A {@linkplain #dispose() disposed} tool removes all instrumentation (but not
+ * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data persists.</li>
+ * </ul>
+ * <p>
+ * Tool-specific methods that access data collected by the tool should:
+ * <ul>
+ * <li>Return modification-safe representations of the data; and</li>
+ * <li>Not change the state of the data.</li>
+ * </ul>
+ * <b>Note:</b><br>
+ * Tool installation is currently <em>global</em> to the Truffle Execution environment. When
+ * language-agnostic management of individual execution environments is added to the platform,
+ * installation will be (optionally) specific to a single execution environment.
+ */
+public abstract class InstrumentationTool {
+    // TODO (mlvdv) still thinking about the most appropriate name for this class of tools
+
+    private enum ToolState {
+
+        /** Not yet installed, inert. */
+        UNINSTALLED,
+
+        /** Installed, collecting data. */
+        ENABLED,
+
+        /** Installed, not collecting data. */
+        DISABLED,
+
+        /** Was installed, but now removed, inactive, and no longer usable. */
+        DISPOSED;
+    }
+
+    private ToolState toolState = ToolState.UNINSTALLED;
+
+    protected InstrumentationTool() {
+    }
+
+    /**
+     * Connect the tool to some part of the Truffle runtime, and enable data collection to start.
+     * Instrumentation will only be added to subsequently created ASTs.
+     *
+     * @throws IllegalStateException if the tool has previously been installed.
+     */
+    public final void install() {
+        checkUninstalled();
+        if (internalInstall()) {
+            toolState = ToolState.ENABLED;
+        }
+    }
+
+    /**
+     * @return whether the tool is currently collecting data.
+     */
+    public final boolean isEnabled() {
+        return toolState == ToolState.ENABLED;
+    }
+
+    /**
+     * Switches tool state between <em>enabled</em> (collecting data) and <em>disabled</em> (not
+     * collecting data, but keeping data already collected).
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void setEnabled(boolean isEnabled) {
+        checkInstalled();
+        internalSetEnabled(isEnabled);
+        toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED;
+    }
+
+    /**
+     * Clears any data already collected, but otherwise does not change the state of the tool.
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void reset() {
+        checkInstalled();
+        internalReset();
+    }
+
+    /**
+     * Makes the tool permanently <em>disabled</em>, removes instrumentation, but keeps data already
+     * collected.
+     *
+     * @throws IllegalStateException if not yet installed or disposed.
+     */
+    public final void dispose() {
+        checkInstalled();
+        internalDispose();
+        toolState = ToolState.DISPOSED;
+    }
+
+    /**
+     * @return whether the installation succeeded.
+     */
+    protected abstract boolean internalInstall();
+
+    /**
+     * No subclass action required.
+     *
+     * @param isEnabled
+     */
+    protected void internalSetEnabled(boolean isEnabled) {
+    }
+
+    protected abstract void internalReset();
+
+    protected abstract void internalDispose();
+
+    /**
+     * Ensure that the tool is currently installed.
+     *
+     * @throws IllegalStateException
+     */
+    private void checkInstalled() throws IllegalStateException {
+        if (toolState == ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed");
+        }
+        if (toolState == ToolState.DISPOSED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed");
+        }
+    }
+
+    /**
+     * Ensure that the tool has not yet been installed.
+     *
+     * @throws IllegalStateException
+     */
+    private void checkUninstalled() {
+        if (toolState != ToolState.UNINSTALLED) {
+            throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/KillException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Controls breaking out of an execution context, such as a shell or eval.
+ */
+public final class KillException extends ControlFlowException {
+
+    private static final long serialVersionUID = 3163641880088766957L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import java.io.*;
+import java.lang.ref.*;
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+
+//TODO (mlvdv) these statics should not be global.  Move them to some kind of context.
+
+/**
+ * A <em>binding</em> between:
+ * <ol>
+ * <li>A program location in an executing Truffle AST (corresponding to a {@link SourceSection}),
+ * and</li>
+ * <li>A dynamically managed collection of "attached" {@linkplain Instrument Instruments} that
+ * receive event notifications on behalf of external clients.</li>
+ * </ol>
+ * <p>
+ * Client-oriented documentation for the use of Probes is available online at <a
+ * HREF="https://wiki.openjdk.java.net/display/Graal/Finding+Probes"
+ * >https://wiki.openjdk.java.net/display/Graal/Finding+Probes</a>
+ * <p>
+ * <h4>Implementation notes:</h4>
+ * <p>
+ * <ul>
+ * <li>A Probe must be permanently associated with a <em>program location</em>, defined by a
+ * particular {@link SourceSection}, even though:
+ * <ul>
+ * <li>that location is represented in an AST as a {@link Node}, which might be replaced through
+ * optimizations such as specialization, and</li>
+ * <li>Truffle may <em>clone</em> the AST so that the location is actually represented by multiple
+ * Nodes in multiple ASTs.</li>
+ * </ul>
+ * </li>
+ *
+ * <li>The effect of the binding is to intercept {@linkplain TruffleEvents execution events}
+ * arriving at the "probed" AST Node and notify each attached {@link Instrument} before execution is
+ * allowed to proceed to the child and again after execution completes.</li>
+ *
+ * <li>The method {@link Node#probe()} creates a Probe on an AST Node; redundant calls return the
+ * same Probe.</li>
+ *
+ * <li>The "probing" of a Truffle AST must be done after the AST is complete (i.e. parent pointers
+ * correctly assigned), but before any cloning or executions. This is done by creating an instance
+ * of {@link ASTProber} and registering it via {@link #registerASTProber(ASTProber)}. Once
+ * registered, it will be applied automatically to every newly created AST.</li>
+ *
+ * <li>The "probing" of an AST Node is implemented by insertion of a {@link ProbeNode.WrapperNode}
+ * into the AST (as new parent of the Node being probed), together with an associated
+ * {@link ProbeNode} that routes execution events at the probed Node to all the
+ * {@linkplain Instrument Instruments} attached to the Probe's <em>instrument chain</em>.</li>
+ *
+ * <li>When Truffle clones an AST, any attached WrapperNodes and ProbeNodes are cloned as well,
+ * together with their attached instrument chains. Each Probe instance intercepts cloning events and
+ * keeps track of all AST copies.</li>
+ *
+ * <li>All attached {@link InstrumentationNode}s effectively become part of the running program:
+ * <ul>
+ * <li>Good News: instrumentation code implicitly benefits from every kind of Truffle optimization.</li>
+ * <li>Bad News: instrumentation code must be implemented carefully to avoid interfering with any
+ * Truffle optimizations.</li>
+ * </ul>
+ * </li>
+ *
+ * </ul>
+ *
+ * @see Instrument
+ * @see ASTProber
+ * @see ProbeListener
+ * @see SyntaxTag
+ */
+public final class Probe {
+
+    private static final boolean TRACE = false;
+    private static final String TRACE_PREFIX = "PROBE: ";
+    private static final PrintStream OUT = System.out;
+
+    private static void trace(String format, Object... args) {
+        if (TRACE) {
+            OUT.println(TRACE_PREFIX + String.format(format, args));
+        }
+    }
+
+    private static final List<ASTProber> astProbers = new ArrayList<>();
+
+    private static final List<ProbeListener> probeListeners = new ArrayList<>();
+
+    /**
+     * All Probes that have been created.
+     */
+    private static final List<WeakReference<Probe>> probes = new ArrayList<>();
+
+    /**
+     * A global trap that triggers notification just before executing any Node that is Probed with a
+     * matching tag.
+     */
+    @CompilationFinal private static SyntaxTagTrap beforeTagTrap = null;
+
+    /**
+     * A global trap that triggers notification just after executing any Node that is Probed with a
+     * matching tag.
+     */
+    @CompilationFinal private static SyntaxTagTrap afterTagTrap = null;
+
+    private static final class FindSourceVisitor implements NodeVisitor {
+
+        Source source = null;
+
+        public boolean visit(Node node) {
+            final SourceSection sourceSection = node.getSourceSection();
+            if (sourceSection != null) {
+                source = sourceSection.getSource();
+                return false;
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Walks an AST, looking for the first node with an assigned {@link SourceSection} and returning
+     * the {@link Source}.
+     */
+    private static Source findSource(Node node) {
+        final FindSourceVisitor visitor = new FindSourceVisitor();
+        node.accept(visitor);
+        return visitor.source;
+    }
+
+    /**
+     * Enables instrumentation at selected nodes in all subsequently constructed ASTs.
+     */
+    public static void registerASTProber(ASTProber prober) {
+        astProbers.add(prober);
+    }
+
+    public static void unregisterASTProber(ASTProber prober) {
+        astProbers.remove(prober);
+    }
+
+    /**
+     * Enables instrumentation in a newly created AST by applying all registered instances of
+     * {@link ASTProber}.
+     */
+    public static void applyASTProbers(Node node) {
+
+        String name = "<?>";
+        final Source source = findSource(node);
+        if (source != null) {
+            name = source.getShortName();
+        } else {
+            final SourceSection sourceSection = node.getEncapsulatingSourceSection();
+            if (sourceSection != null) {
+                name = sourceSection.getShortDescription();
+            }
+        }
+        trace("START %s", name);
+        for (ProbeListener listener : probeListeners) {
+            listener.startASTProbing(source);
+        }
+        for (ASTProber prober : astProbers) {
+            prober.probeAST(node);
+        }
+        for (ProbeListener listener : probeListeners) {
+            listener.endASTProbing(source);
+        }
+        trace("FINISHED %s", name);
+    }
+
+    /**
+     * Adds a {@link ProbeListener} to receive events.
+     */
+    public static void addProbeListener(ProbeListener listener) {
+        assert listener != null;
+        probeListeners.add(listener);
+    }
+
+    /**
+     * Removes a {@link ProbeListener}. Ignored if listener not found.
+     */
+    public static void removeProbeListener(ProbeListener listener) {
+        probeListeners.remove(listener);
+    }
+
+    /**
+     * Returns all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole collection of
+     * probes if the specified tag is {@code null}.
+     *
+     * @return A collection of probes containing the given tag.
+     */
+    public static Collection<Probe> findProbesTaggedAs(SyntaxTag tag) {
+        final List<Probe> taggedProbes = new ArrayList<>();
+        for (WeakReference<Probe> ref : probes) {
+            Probe probe = ref.get();
+            if (probe != null) {
+                if (tag == null || probe.isTaggedAs(tag)) {
+                    taggedProbes.add(ref.get());
+                }
+            }
+        }
+        return taggedProbes;
+    }
+
+    // TODO (mlvdv) generalize to permit multiple "before traps" without a performance hit?
+    /**
+     * Sets the current "<em>before</em> tag trap"; there can be no more than one in effect.
+     * <ul>
+     * <li>The before-trap triggers a callback just <strong><em>before</em></strong> execution
+     * reaches <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created)
+     * with the specified {@link SyntaxTag}.</li>
+     * <li>Setting the before-trap to {@code null} clears an existing before-trap.</li>
+     * <li>Setting a non{@code -null} before-trap when one is already set clears the previously set
+     * before-trap.</li>
+     * </ul>
+     *
+     * @param newBeforeTagTrap The new "before" {@link SyntaxTagTrap} to set.
+     */
+    public static void setBeforeTagTrap(SyntaxTagTrap newBeforeTagTrap) {
+        beforeTagTrap = newBeforeTagTrap;
+        for (WeakReference<Probe> ref : probes) {
+            final Probe probe = ref.get();
+            if (probe != null) {
+                probe.notifyTrapsChanged();
+            }
+        }
+    }
+
+    // TODO (mlvdv) generalize to permit multiple "after traps" without a performance hit?
+    /**
+     * Sets the current "<em>after</em> tag trap"; there can be no more than one in effect.
+     * <ul>
+     * <li>The after-trap triggers a callback just <strong><em>after</em></strong> execution leaves
+     * <strong><em>any</em></strong> {@link Probe} (either existing or subsequently created) with
+     * the specified {@link SyntaxTag}.</li>
+     * <li>Setting the after-trap to {@code null} clears an existing after-trap.</li>
+     * <li>Setting a non{@code -null} after-trap when one is already set clears the previously set
+     * after-trap.</li>
+     * </ul>
+     *
+     * @param newAfterTagTrap The new "after" {@link SyntaxTagTrap} to set.
+     */
+    public static void setAfterTagTrap(SyntaxTagTrap newAfterTagTrap) {
+        afterTagTrap = newAfterTagTrap;
+        for (WeakReference<Probe> ref : probes) {
+            final Probe probe = ref.get();
+            if (probe != null) {
+                probe.notifyTrapsChanged();
+            }
+        }
+    }
+
+    private final SourceSection sourceSection;
+    private final ArrayList<SyntaxTag> tags = new ArrayList<>();
+    private final List<WeakReference<ProbeNode>> probeNodeClones = new ArrayList<>();
+
+    /*
+     * Invalidated whenever something changes in the Probe and its Instrument chain, so need deopt
+     */
+    private final CyclicAssumption probeStateUnchangedCyclic = new CyclicAssumption("Probe state unchanged");
+
+    /*
+     * The assumption that nothing had changed in this probe, the last time anybody checked (when
+     * there may have been a deopt). Every time a check fails, gets replaced by a new unchanged
+     * assumption.
+     */
+    @CompilationFinal private Assumption probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption();
+
+    // Must invalidate whenever changed
+    @CompilationFinal private boolean isBeforeTrapActive = false;
+
+    // Must invalidate whenever changed
+    @CompilationFinal private boolean isAfterTrapActive = false;
+
+    /**
+     * Intended for use only by {@link ProbeNode}.
+     */
+    Probe(ProbeNode probeNode, SourceSection sourceSection) {
+        this.sourceSection = sourceSection;
+        probes.add(new WeakReference<>(this));
+        registerProbeNodeClone(probeNode);
+        if (TRACE) {
+            final String location = this.sourceSection == null ? "<unknown>" : sourceSection.getShortDescription();
+            trace("ADDED %s %s %s", "Probe@", location, getTagsDescription());
+        }
+        for (ProbeListener listener : probeListeners) {
+            listener.newProbeInserted(this);
+        }
+    }
+
+    /**
+     * Is this node tagged as belonging to a particular human-sensible category of language
+     * constructs?
+     */
+    public boolean isTaggedAs(SyntaxTag tag) {
+        assert tag != null;
+        return tags.contains(tag);
+    }
+
+    /**
+     * In which user-sensible categories has this node been tagged (<em>empty set</em> if none).
+     */
+    public Collection<SyntaxTag> getSyntaxTags() {
+        return Collections.unmodifiableCollection(tags);
+    }
+
+    /**
+     * Adds a {@linkplain SyntaxTag tag} to the set of tags associated with this {@link Probe};
+     * {@code no-op} if already in the set.
+     */
+    public void tagAs(SyntaxTag tag, Object tagValue) {
+        assert tag != null;
+        if (!tags.contains(tag)) {
+            tags.add(tag);
+            for (ProbeListener listener : probeListeners) {
+                listener.probeTaggedAs(this, tag, tagValue);
+            }
+
+            // Update the status of this Probe with respect to global tag traps
+            boolean tagTrapsChanged = false;
+            if (beforeTagTrap != null && tag == beforeTagTrap.getTag()) {
+                this.isBeforeTrapActive = true;
+                tagTrapsChanged = true;
+            }
+            if (afterTagTrap != null && tag == afterTagTrap.getTag()) {
+                this.isAfterTrapActive = true;
+                tagTrapsChanged = true;
+            }
+            if (tagTrapsChanged) {
+                invalidateProbeUnchanged();
+            }
+            if (TRACE) {
+                trace("TAGGED as %s: %s", tag, getShortDescription());
+            }
+        }
+    }
+
+    /**
+     * Adds instrumentation at this Probe.
+     *
+     * @param instrument an instrument not yet attached to a probe
+     * @throws IllegalStateException if the instrument has ever been attached before
+     */
+    public void attach(Instrument instrument) throws IllegalStateException {
+        if (instrument.isDisposed()) {
+            throw new IllegalStateException("Attempt to attach disposed instrument");
+        }
+        if (instrument.getProbe() != null) {
+            throw new IllegalStateException("Attampt to attach an already attached instrument");
+        }
+        instrument.setAttachedTo(this);
+        for (WeakReference<ProbeNode> ref : probeNodeClones) {
+            final ProbeNode probeNode = ref.get();
+            if (probeNode != null) {
+                probeNode.addInstrument(instrument);
+            }
+        }
+        invalidateProbeUnchanged();
+    }
+
+    /**
+     * Gets the {@link SourceSection} associated with the Guest Language AST node being
+     * instrumented, possibly {@code null}.
+     */
+    public SourceSection getProbedSourceSection() {
+        return sourceSection;
+    }
+
+    public String getShortDescription() {
+        final String location = sourceSection == null ? "<unknown>" : sourceSection.getShortDescription();
+        return "Probe@" + location + getTagsDescription();
+    }
+
+    /**
+     * Internal method for removing and rendering inert a specific instrument previously attached at
+     * this Probe.
+     *
+     * @param instrument an instrument already attached
+     * @throws IllegalStateException if instrument not attached at this Probe
+     * @see Instrument#dispose()
+     */
+    void disposeInstrument(Instrument instrument) throws IllegalStateException {
+        for (WeakReference<ProbeNode> ref : probeNodeClones) {
+            final ProbeNode probeNode = ref.get();
+            if (probeNode != null) {
+                probeNode.removeInstrument(instrument);
+            }
+        }
+        invalidateProbeUnchanged();
+    }
+
+    /**
+     * Receives notification that a new clone of the instrument chain associated with this
+     * {@link Probe} has been created as a side-effect of AST cloning.
+     */
+    void registerProbeNodeClone(ProbeNode probeNode) {
+        probeNodeClones.add(new WeakReference<>(probeNode));
+    }
+
+    /**
+     * Gets the currently active <strong><em>before</em></strong> {@linkplain SyntaxTagTrap Tag
+     * Trap} at this Probe. Non{@code -null} if the global
+     * {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Before Tag Trap} is set and if this Probe
+     * holds the {@link SyntaxTag} specified in the trap.
+     */
+    SyntaxTagTrap getBeforeTrap() {
+        checkProbeUnchanged();
+        return isBeforeTrapActive ? beforeTagTrap : null;
+    }
+
+    /**
+     * Gets the currently active <strong><em>after</em></strong> {@linkplain SyntaxTagTrap Tag Trap}
+     * at this Probe. Non{@code -null} if the global
+     * {@linkplain Probe#setAfterTagTrap(SyntaxTagTrap) After Tag Trap} is set and if this Probe
+     * holds the {@link SyntaxTag} specified in the trap.
+     */
+    SyntaxTagTrap getAfterTrap() {
+        checkProbeUnchanged();
+        return isAfterTrapActive ? afterTagTrap : null;
+    }
+
+    /**
+     * To be called wherever in the Probe/Instrument chain there are dependencies on the probe
+     * state's @CompilatonFinal fields.
+     */
+    void checkProbeUnchanged() {
+        try {
+            probeStateUnchangedAssumption.check();
+        } catch (InvalidAssumptionException ex) {
+            // Failure creates an implicit deoptimization
+            // Get the assumption associated with the new probe state
+            this.probeStateUnchangedAssumption = probeStateUnchangedCyclic.getAssumption();
+        }
+    }
+
+    void invalidateProbeUnchanged() {
+        probeStateUnchangedCyclic.invalidate();
+    }
+
+    private void notifyTrapsChanged() {
+        this.isBeforeTrapActive = beforeTagTrap != null && this.isTaggedAs(beforeTagTrap.getTag());
+        this.isAfterTrapActive = afterTagTrap != null && this.isTaggedAs(afterTagTrap.getTag());
+        invalidateProbeUnchanged();
+    }
+
+    private String getTagsDescription() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("[");
+        String prefix = "";
+        for (SyntaxTag tag : tags) {
+            sb.append(prefix);
+            prefix = ",";
+            sb.append(tag.toString());
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.instrument.ProbeFailure.Reason;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An exception thrown when {@link Node#probe()} fails because of an implementation failure.
+ * <p>
+ * Language and tool implementations should ensure that clients of tools never see this exception.
+ */
+public class ProbeException extends RuntimeException {
+    static final long serialVersionUID = 1L;
+    private final ProbeFailure failure;
+
+    public ProbeException(Reason reason, Node parent, Node child, Object wrapper) {
+        this.failure = new ProbeFailure(reason, parent, child, wrapper);
+    }
+
+    public ProbeFailure getFailure() {
+        return failure;
+    }
+
+    @Override
+    public String toString() {
+        return failure.getMessage();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Description of a failed attempt to instrument an AST node.
+ */
+public final class ProbeFailure {
+
+    public enum Reason {
+
+        /**
+         * Node to be probed has no parent.
+         */
+        NO_PARENT("Node to be probed has no parent"),
+
+        /**
+         * The node to be probed is a wrapper.
+         */
+        WRAPPER_NODE("The node to be probed is a wrapper"),
+
+        /**
+         * The node to be probed returned {@link Node#isInstrumentable()}{@code == false}.
+         */
+        NOT_INSTRUMENTABLE("The node to be project is \"not instrumentable\""),
+
+        /**
+         * No wrapper could be created that is also a {@link Node}.
+         */
+        NO_WRAPPER("No wrapper could be created"),
+
+        /**
+         * Wrapper not assignable to the parent's child field.
+         */
+        WRAPPER_TYPE("Wrapper not assignable to parent's child field");
+
+        final String message;
+
+        private Reason(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+    }
+
+    private final Reason reason;
+    private final Node parent;
+    private final Node child;
+    private final Object wrapper;
+
+    /**
+     * Description of an internal failure of {@link Node#probe()}.
+     *
+     * @param reason what caused the failure
+     * @param parent the parent, if known, of the child being probed
+     * @param child this child being probed
+     * @param wrapper the {@link WrapperNode} created to implement the probe
+     */
+    public ProbeFailure(Reason reason, Node parent, Node child, Object wrapper) {
+        this.reason = reason;
+        this.parent = parent;
+        this.child = child;
+        this.wrapper = wrapper;
+    }
+
+    /**
+     * @return a short explanation of the failure
+     */
+    public Reason getReason() {
+        return reason;
+    }
+
+    /**
+     * @return the parent, if any, of the node being probed
+     */
+    public Node getParent() {
+        return parent;
+    }
+
+    /**
+     * @return the node being probed
+     */
+    public Node getChild() {
+        return child;
+    }
+
+    /**
+     * @return the {@link WrapperNode} created for the probe attempt
+     */
+    public Object getWrapper() {
+        return wrapper;
+    }
+
+    public String getMessage() {
+        final StringBuilder sb = new StringBuilder(reason.message + ": ");
+        if (parent != null) {
+            sb.append("parent=" + parent.getClass().getSimpleName() + " ");
+            if (child != null) {
+                sb.append("child=" + child.getClass().getSimpleName() + " ");
+                final NodeFieldAccessor field = NodeUtil.findChildField(parent, child);
+                if (field != null) {
+                    sb.append("field=" + field.getName() + " ");
+                }
+            }
+        }
+        if (wrapper != null) {
+            sb.append("wrapper=" + wrapper.getClass().getSimpleName());
+        }
+        return sb.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * An observer of events related to {@link Probe}s: creating and tagging.
+ */
+public interface ProbeListener {
+
+    /**
+     * Notifies that all registered {@link ASTProber}s are about to be applied to a newly
+     * constructed AST.
+     *
+     * @param source source code from which the AST was constructed
+     */
+    void startASTProbing(Source source);
+
+    /**
+     * Notifies that a {@link Probe} has been newly attached to an AST via {@link Node#probe()}.
+     * <p>
+     * There can be no more than one {@link Probe} at a node; this notification will only be
+     * delivered the first time {@linkplain Node#probe() probe()} is called at a particular AST
+     * node. There will also be no notification when the AST to which the Probe is attached is
+     * cloned.
+     */
+    void newProbeInserted(Probe probe);
+
+    /**
+     * Notifies that a {@link SyntaxTag} has been newly added to the set of tags associated with a
+     * {@link Probe} via {@link Probe#tagAs(SyntaxTag, Object)}.
+     * <p>
+     * The {@linkplain SyntaxTag tags} at a {@link Probe} are a <em>set</em>; this notification will
+     * only be delivered the first time a particular {@linkplain SyntaxTag tag} is added at a
+     * {@link Probe}.
+     * <p>
+     * An optional value supplied with {@linkplain Probe#tagAs(SyntaxTag, Object) tagAs(SyntaxTag,
+     * Object)} is reported to all listeners, but not stored. As a consequence, the optional value
+     * will have no effect at all if the tag had already been added.
+     *
+     * @param probe where a tag has been added
+     * @param tag the tag that has been newly added (subsequent additions of the tag are
+     *            unreported).
+     * @param tagValue an optional value associated with the tag for the purposes of reporting.
+     */
+    void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue);
+
+    /**
+     * Notifies that the application of all registered {@link ASTProber}s to a newly constructed AST
+     * has completed.
+     *
+     * @param source source code from which the AST was constructed
+     */
+    void endASTProbing(Source source);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.Instrument.AbstractInstrumentNode;
+import com.oracle.truffle.api.instrument.InstrumentationNode.TruffleEvents;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Implementation class & interface for enabling the attachment of {@linkplain Probe Probes} to
+ * Truffle ASTs.
+ * <p>
+ * A {@link ProbeNode} is the head of a chain of nodes acting on behalf of {@linkplain Instrument
+ * instruments}. It is attached to an AST as a child of a guest-language-specific
+ * {@link WrapperNode} node.
+ * <p>
+ * When Truffle clones an AST, the chain, including all attached {@linkplain Instrument instruments}
+ * will be cloned along with the {@link WrapperNode} to which it is attached. An instance of
+ * {@link Probe} represents abstractly the instrumentation at a particular location in a Guest
+ * Language AST, tracks the clones of the chain, and keeps the instrumentation attached to the
+ * clones consistent.
+ */
+@NodeInfo(cost = NodeCost.NONE)
+public final class ProbeNode extends Node implements TruffleEvents, InstrumentationNode {
+
+    /**
+     * A node that can be inserted into a Truffle AST, and which enables {@linkplain Instrument
+     * instrumentation} at a particular Guest Language (GL) node. Implementations must extend
+     * {@link Node} and should override {@link Node#isInstrumentable()} to return {@code false}.
+     * <p>
+     * The implementation must be GL-specific. A wrapper <em>decorates</em> a GL AST node (the
+     * wrapper's <em>child</em>) by acting as a transparent <em>proxy</em> with respect to the GL's
+     * execution semantics.
+     * <p>
+     * Instrumentation at the wrapped node is implemented by an instance of {@link ProbeNode}
+     * attached as a second child of the {@link WrapperNode}.
+     * <p>
+     * A wrapper is obliged to notify its attached {@link ProbeNode} when execution events occur at
+     * the wrapped AST node during program execution.
+     * <p>
+     * When a GL AST is cloned, the {@link WrapperNode}, its {@link ProbeNode} and any
+     * {@linkplain Instrument instrumentation} are also cloned; they are in effect part of the GL
+     * AST. An instance of {@link Probe} represents abstractly the instrumentation at a particular
+     * location in a GL AST; it tracks all the copies of the Wrapper and attached instrumentation,
+     * and acts as a single point of access for tools.
+     * <p>
+     * This interface is not intended to be visible as part of the API for tools (instrumentation
+     * clients).
+     * <p>
+     * Implementation guidelines:
+     * <ol>
+     * <li>Each GL implementation should include a WrapperNode implementation; usually only one is
+     * needed.</li>
+     * <li>The wrapper type should descend from the <em>GL-specific node class</em>.</li>
+     * <li>Must have a field: {@code @Child private <GL>Node child;}</li>
+     * <li>Must have a field: {@code @Child private ProbeNode probeNode;}</li>
+     * <li>The wrapper must act as a <em>proxy</em> for its child, which means implementing every
+     * possible <em>execute-</em> method that gets called on guest language AST node types by their
+     * parents, and passing along each call to its child.</li>
+     * <li>Method {@code Probe getProbe()} should be implemented as {@code probeNode.getProbe();}
+     * <li>Method {@code insertProbe(ProbeNode)} should be implemented as
+     * {@code this.probeNode=insert(newProbeNode);}</li>
+     * <li>Most importantly, Wrappers must be implemented so that Truffle optimization will reduce
+     * their runtime overhead to zero when there are no attached {@link Instrument}s.</li>
+     * </ol>
+     * <p>
+     *
+     * @see Instrument
+     */
+    public interface WrapperNode extends InstrumentationNode {
+
+        /**
+         * Gets the node being "wrapped", i.e. the AST node for which
+         * {@linkplain InstrumentationNode.TruffleEvents execution events} will be reported through
+         * the Instrumentation Framework.
+         */
+        Node getChild();
+
+        /**
+         * Gets the {@link Probe} responsible for installing this wrapper.
+         */
+        Probe getProbe();
+
+        /**
+         * Implementation support for completing a newly created wrapper node.
+         */
+        void insertProbe(ProbeNode probeNode);
+    }
+
+    /**
+     * Create a new {@link Probe} associated with, and attached to, a Guest Language specific
+     * instance of {@link WrapperNode}.
+     */
+    public static Probe insertProbe(WrapperNode wrapper) {
+        final SourceSection sourceSection = wrapper.getChild().getSourceSection();
+        final ProbeNode probeNode = new ProbeNode(); // private constructor
+        probeNode.probe = new Probe(probeNode, sourceSection);  // package private access
+        wrapper.insertProbe(probeNode);
+        return probeNode.probe;
+    }
+
+    // Never changed once set.
+    @CompilationFinal Probe probe = null;
+    /**
+     * First {@link AbstractInstrumentNode} node in chain; {@code null} of no instruments in chain.
+     */
+    @Child protected AbstractInstrumentNode firstInstrumentNode;
+
+    @Override
+    public boolean isInstrumentable() {
+        return false;
+    }
+
+    @Override
+    public Node copy() {
+        Node node = super.copy();
+        probe.registerProbeNodeClone((ProbeNode) node);
+        return node;
+    }
+
+    /**
+     * @return the {@link Probe} permanently associated with this {@link ProbeNode}.
+     */
+    public Probe getProbe() {
+        return probe;
+    }
+
+    public void enter(Node node, VirtualFrame vFrame) {
+        this.probe.checkProbeUnchanged();
+        final SyntaxTagTrap beforeTagTrap = probe.getBeforeTrap();
+        if (beforeTagTrap != null) {
+            beforeTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
+        }
+        if (firstInstrumentNode != null) {
+            firstInstrumentNode.enter(node, vFrame);
+        }
+    }
+
+    public void returnVoid(Node node, VirtualFrame vFrame) {
+        this.probe.checkProbeUnchanged();
+        if (firstInstrumentNode != null) {
+            firstInstrumentNode.returnVoid(node, vFrame);
+        }
+        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
+        if (afterTagTrap != null) {
+            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
+        }
+    }
+
+    public void returnValue(Node node, VirtualFrame vFrame, Object result) {
+        this.probe.checkProbeUnchanged();
+        if (firstInstrumentNode != null) {
+            firstInstrumentNode.returnValue(node, vFrame, result);
+        }
+        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
+        if (afterTagTrap != null) {
+            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
+        }
+    }
+
+    public void returnExceptional(Node node, VirtualFrame vFrame, Exception exception) {
+        this.probe.checkProbeUnchanged();
+        if (firstInstrumentNode != null) {
+            firstInstrumentNode.returnExceptional(node, vFrame, exception);
+        }
+        final SyntaxTagTrap afterTagTrap = probe.getAfterTrap();
+        if (afterTagTrap != null) {
+            afterTagTrap.tagTrappedAt(((WrapperNode) this.getParent()).getChild(), vFrame.materialize());
+        }
+    }
+
+    public String instrumentationInfo() {
+        return "Standard probe";
+    }
+
+    /**
+     * Gets the guest-language AST node to which this Probe is attached.
+     */
+    Node getProbedNode() {
+        return ((WrapperNode) this.getParent()).getChild();
+    }
+
+    /**
+     * Adds an {@link AbstractInstrumentNode} to this chain.
+     */
+    @TruffleBoundary
+    void addInstrument(Instrument instrument) {
+        assert instrument.getProbe() == probe;
+        // The existing chain of nodes may be empty
+        // Attach the modified chain.
+        firstInstrumentNode = insert(instrument.addToChain(firstInstrumentNode));
+    }
+
+    /**
+     * Removes an instrument from this chain of instruments.
+     *
+     * @throws RuntimeException if no matching instrument is found,
+     */
+    @TruffleBoundary
+    void removeInstrument(Instrument instrument) {
+        assert instrument.getProbe() == probe;
+        final AbstractInstrumentNode modifiedChain = instrument.removeFromChain(firstInstrumentNode);
+        if (modifiedChain == null) {
+            firstInstrumentNode = null;
+        } else {
+            firstInstrumentNode = insert(modifiedChain);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/QuitException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Controls breaking out of all executions and ending Truffle execution.
+ */
+public final class QuitException extends ControlFlowException {
+
+    private static final long serialVersionUID = -4301115629772778413L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SimpleInstrumentListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A receiver of Truffle execution events that can act on behalf of an external client.
+ * <p>
+ * The {@link Probe} instance provides access to the {@link SourceSection} associated with the
+ * event, as well as any {@link SyntaxTag}s that have been applied at that program's location.
+ * <p>
+ * This is the simplest kind of listener, suitable for clients that need no other information about
+ * the program's execution state at the time of the event. Clients that require access to the AST
+ * execution state should use {@link StandardInstrumentListener}.
+ * <p>
+ * Clients are free, of course, to record additional information in the listener implementation that
+ * carries additional information about the context and reason for the particular {@link Instrument}
+ * that is to be created from the listener.
+ */
+public interface SimpleInstrumentListener {
+
+    /**
+     * Receive notification that a program location is about to be executed.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void enter(Probe probe);
+
+    /**
+     * Receive notification that a program location's {@code void}-valued execution has just
+     * completed.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnVoid(Probe probe);
+
+    /**
+     * Receive notification that a program location's execution has just completed and returned a
+     * value (boxed if primitive).
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnValue(Probe probe, Object result);
+
+    /**
+     * Receive notification that a program location's execution has just thrown an exception.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnExceptional(Probe probe, Exception exception);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardInstrumentListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A receiver of Truffle execution events that can act on behalf of an external client.
+ * <p>
+ * The {@link Probe} argument provides access to the {@link SourceSection} associated with the
+ * event, as well as any {@link SyntaxTag}s that have been applied at that AST node.
+ * <p>
+ * This listener is designed for clients that also require access to the AST execution state at the
+ * time of the event. Clients that do not require access to the AST execution state should use the
+ * {@link SimpleInstrumentListener}.
+ * <p>
+ * Clients are free, of course, to record additional information in the listener implementation that
+ * carries additional information about the context and reason for the particular {@link Instrument}
+ * that is to be created from the listener.
+ */
+public interface StandardInstrumentListener {
+
+    /**
+     * Receive notification that an AST node's execute method is about to be called.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void enter(Probe probe, Node node, VirtualFrame vFrame);
+
+    /**
+     * Receive notification that an AST Node's {@code void}-valued execute method has just returned.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnVoid(Probe probe, Node node, VirtualFrame vFrame);
+
+    /**
+     * Receive notification that an AST Node's execute method has just returned a value (boxed if
+     * primitive).
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result);
+
+    /**
+     * Receive notification that an AST Node's execute method has just thrown an exception.
+     * <p>
+     * <strong>Synchronous</strong>: Truffle execution waits until the call returns.
+     */
+    void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/StandardSyntaxTag.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+/**
+ * A somewhat language-agnostic set of user-sensible syntactic categories, suitable for conventional
+ * imperative languages, and is being developed incrementally.
+ * <p>
+ * The need for alternative sets of tags is likely to arise, perhaps for other families of languages
+ * (for example for mostly expression-oriented languages) or even for specific languages.
+ *
+ * @see Probe
+ */
+public enum StandardSyntaxTag implements SyntaxTag {
+
+    /**
+     * Marker for a variable assignment.
+     */
+    ASSIGNMENT("assignment", "a variable assignment"),
+
+    /**
+     * Marker for a call site.
+     */
+    CALL("call", "a method/procedure call site"),
+
+    /**
+     * Marker for a location where a guest language exception is about to be thrown.
+     */
+    THROW("throw", "creator of an exception"),
+
+    /**
+     * Marker for a location where ordinary "stepping" should halt.
+     */
+    STATEMENT("statement", "basic unit of the language, suitable for \"stepping\" in a debugger"),
+
+    /**
+     * Marker for the start of the body of a method.
+     */
+    START_METHOD("start-method", "start of the body of a method"),
+
+    /**
+     * Marker for the start of the body of a loop.
+     */
+    START_LOOP("start-loop", "start of the body of a loop"),
+
+    /**
+     * Marker that is attached to some arbitrary locations that appear often-enough in an AST so
+     * that a location with this tag is regularly executed. Could be the start of method and loop
+     * bodies. May be used to implement some kind of safepoint functionality.
+     */
+    PERIODIC("periodic", "arbitrary locations that appear often-enough in an AST so that a location with this tag is regularly executed");
+
+    private final String name;
+    private final String description;
+
+    private StandardSyntaxTag(String name, String description) {
+        this.name = name;
+        this.description = description;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTag.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+/**
+ * Program element "tags", presumed to be singletons (best implemented as enums) that define
+ * user-visible behavior for debugging and other simple tools. These categories should correspond to
+ * program structures, for example "statement" and "assignment", that are meaningful
+ * ("human-sensible") to guest language programmers.
+ * <p>
+ * An untagged Truffle node should be understood as an artifact of the guest language implementation
+ * and should not be visible to guest language programmers. Nodes may also have more than one tag,
+ * for example a variable assignment that is also a statement. Finally, the assignment of tags to
+ * nodes could depending on the use-case of whatever tool is using them.
+ *
+ * @see Probe
+ * @see StandardSyntaxTag
+ */
+public interface SyntaxTag {
+
+    /**
+     * Human-friendly name of guest language program elements belonging to the category, e.g.
+     * "statement".
+     */
+    String name();
+
+    /**
+     * Criteria and example uses for the tag.
+     */
+    String getDescription();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagTrap.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A trap that can be set to interrupt execution at probed nodes carrying a specific tag.
+ *
+ * @see Probe
+ */
+public abstract class SyntaxTagTrap {
+
+    private final SyntaxTag tag;
+
+    protected SyntaxTagTrap(SyntaxTag tag) {
+        this.tag = tag;
+    }
+
+    public final SyntaxTag getTag() {
+        return tag;
+    }
+
+    /**
+     * Notifies that execution is halted at a node with the specified tag.
+     */
+    public abstract void tagTrappedAt(Node node, MaterializedFrame frame);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ToolSupportProvider.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+/**
+ * Access to language-specific information and execution services for external tools.
+ */
+public interface ToolSupportProvider {
+
+    /**
+     * Gets visualization services for language-specific information.
+     */
+    Visualizer getVisualizer();
+
+    /**
+     * Enables AST probing on all subsequently created ASTs (sources parsed).
+     *
+     * @param astProber optional AST prober to enable; the default for the language used if
+     *            {@code null}
+     */
+    void enableASTProbing(ASTProber astProber);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Visualizer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Visualization services for the benefit of instrumentation-based tools, possibly specialized for
+ * each guest language and possibly specialized for relevant information from the underlying Truffle
+ * implementation.
+ * <p>
+ * <strong>Disclaimer:</strong> experimental interface under development.
+ */
+public interface Visualizer {
+
+    // TODO (mlvdv) "Visualizer" is misleading: rename.
+    /**
+     * Gets a printer for Truffle ASTs, possibly specialized to be helpful for a specific guest
+     * language implementation.
+     */
+    ASTPrinter getASTPrinter();
+
+    /**
+     * A short description of a source location in terms of source + line number.
+     */
+    String displaySourceLocation(Node node);
+
+    /**
+     * Describes the name of the method containing a node.
+     */
+    String displayMethodName(Node node);
+
+    /**
+     * The name of the method.
+     */
+    String displayCallTargetName(CallTarget callTarget);
+
+    /**
+     * Converts a value in the guest language to a display string. If
+     * 
+     * @param trim if {@code > 0}, them limit size of String to either the value of trim or the
+     *            number of characters in the first line, whichever is lower.
+     */
+    String displayValue(Object value, int trim);
+
+    /**
+     * Converts a slot identifier in the guest language to a display string.
+     */
+    String displayIdentifier(FrameSlot slot);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A language-agnostic for printing out various pieces of a Truffle AST.
+ */
+public class DefaultASTPrinter implements ASTPrinter {
+
+    public DefaultASTPrinter() {
+    }
+
+    public void printTree(PrintWriter p, Node node, int maxDepth, Node markNode) {
+        printTree(p, node, maxDepth, markNode, 1);
+        p.println();
+        p.flush();
+    }
+
+    public String printTreeToString(Node node, int maxDepth, Node markNode) {
+        StringWriter out = new StringWriter();
+        printTree(new PrintWriter(out), node, maxDepth, markNode);
+        return out.toString();
+    }
+
+    public String printTreeToString(Node node, int maxDepth) {
+        return printTreeToString(node, maxDepth, null);
+    }
+
+    public String printNodeWithInstrumentation(Node node) {
+        if (node == null) {
+            return "null";
+        }
+        final StringBuilder sb = new StringBuilder();
+        sb.append(nodeName(node));
+        sb.append("(");
+        if (node instanceof InstrumentationNode) {
+            sb.append(instrumentInfo((InstrumentationNode) node));
+        }
+        sb.append(sourceInfo(node));
+        sb.append(NodeUtil.printSyntaxTags(node));
+        sb.append(")");
+        final Node parent = node.getParent();
+        if (parent instanceof WrapperNode) {
+            final WrapperNode wrapper = (WrapperNode) parent;
+            sb.append(" Probed");
+            sb.append(NodeUtil.printSyntaxTags(wrapper));
+        }
+        return sb.toString();
+    }
+
+    protected void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(nodeName(node));
+
+        p.print("(");
+
+        if (node instanceof InstrumentationNode) {
+            p.print(instrumentInfo((InstrumentationNode) node));
+        }
+
+        p.print(sourceInfo(node));
+
+        p.print(NodeUtil.printSyntaxTags(node));
+
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
+
+        for (NodeFieldAccessor field : NodeClass.get(node).getFields()) {
+            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
+                childFields.add(field);
+            } else if (field.getKind() == NodeFieldKind.DATA) {
+                // p.print(sep);
+                // sep = ", ";
+                //
+                // final String fieldName = field.getName();
+                // switch (fieldName) {
+                //
+                // }
+                // p.print(fieldName);
+                // p.print(" = ");
+                // p.print(field.loadValue(node));
+            }
+        }
+        p.print(")");
+
+        if (level <= maxDepth) {
+
+            if (childFields.size() != 0) {
+                p.print(" {");
+                for (NodeFieldAccessor field : childFields) {
+
+                    Object value = field.loadValue(node);
+                    if (value == null) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        p.print(" = null ");
+                    } else if (field.getKind() == NodeFieldKind.CHILD) {
+                        printChild(p, maxDepth, markNode, level, field, value);
+                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                        printChildren(p, maxDepth, markNode, level, field, value);
+                    } else {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                    }
+                }
+                printNewLine(p, level - 1);
+                p.print("}");
+            }
+        }
+    }
+
+    protected void printChildren(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
+        printNewLine(p, level);
+        p.print(field.getName());
+        Node[] children = (Node[]) value;
+        p.print(" = [");
+        String sep = "";
+        for (Node child : children) {
+            p.print(sep);
+            sep = ", ";
+            printTree(p, child, maxDepth, markNode, level + 1);
+        }
+        p.print("]");
+    }
+
+    protected void printChild(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
+        final Node valueNode = (Node) value;
+        printNewLine(p, level, valueNode == markNode);
+        p.print(field.getName());
+        p.print(" = ");
+        printTree(p, valueNode, maxDepth, markNode, level + 1);
+    }
+
+    protected static void printNewLine(PrintWriter p, int level, boolean mark) {
+        p.println();
+        for (int i = 0; i < level; i++) {
+            if (mark && i == 0) {
+                p.print(" -->");
+            } else {
+                p.print("    ");
+            }
+        }
+    }
+
+    protected static void printNewLine(PrintWriter p, int level) {
+        printNewLine(p, level, false);
+    }
+
+    protected static String nodeName(Node node) {
+        return node.getClass().getSimpleName();
+    }
+
+    protected static String sourceInfo(Node node) {
+        final SourceSection src = node.getSourceSection();
+        if (src != null) {
+            if (src instanceof NullSourceSection) {
+                final NullSourceSection nullSection = (NullSourceSection) src;
+                return nullSection.getShortDescription();
+            } else {
+                return src.getSource().getName() + ":" + src.getStartLine();
+            }
+        }
+        return "";
+    }
+
+    protected static String instrumentInfo(InstrumentationNode node) {
+        final String info = node.instrumentationInfo();
+        return info == null ? "" : info;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultProbeListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+public abstract class DefaultProbeListener implements ProbeListener {
+
+    public void startASTProbing(Source source) {
+    }
+
+    public void newProbeInserted(Probe probe) {
+    }
+
+    public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+    }
+
+    public void endASTProbing(Source source) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultSimpleInstrumentListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import com.oracle.truffle.api.instrument.*;
+
+/**
+ * A listener for Truffle execution events that provides a no-op implementation of every event.
+ */
+public class DefaultSimpleInstrumentListener implements SimpleInstrumentListener {
+
+    public void enter(Probe probe) {
+    }
+
+    public void returnVoid(Probe probe) {
+    }
+
+    public void returnValue(Probe probe, Object result) {
+    }
+
+    public void returnExceptional(Probe probe, Exception exception) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultStandardInstrumentListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A listener for AST {@linkplain StandardInstrumentListener execution events} that provides a no-op
+ * implementation of every event.
+ */
+public class DefaultStandardInstrumentListener implements StandardInstrumentListener {
+
+    public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+    }
+
+    public void returnVoid(Probe probe, Node node, VirtualFrame vFrame) {
+    }
+
+    public void returnValue(Probe probe, Node node, VirtualFrame vFrame, Object result) {
+    }
+
+    public void returnExceptional(Probe probe, Node node, VirtualFrame vFrame, Exception exception) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultVisualizer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+public class DefaultVisualizer implements Visualizer {
+
+    private final ASTPrinter astPrinter;
+
+    public DefaultVisualizer() {
+        this.astPrinter = new DefaultASTPrinter();
+    }
+
+    public ASTPrinter getASTPrinter() {
+        return astPrinter;
+    }
+
+    public String displaySourceLocation(Node node) {
+        if (node == null) {
+            return "<unknown>";
+        }
+        SourceSection section = node.getSourceSection();
+        boolean estimated = false;
+        if (section == null) {
+            section = node.getEncapsulatingSourceSection();
+            estimated = true;
+        }
+        if (section == null) {
+            return "<error: source location>";
+        }
+        return section.getShortDescription() + (estimated ? "~" : "");
+    }
+
+    public String displayMethodName(Node node) {
+        if (node == null) {
+            return null;
+        }
+        RootNode root = node.getRootNode();
+        if (root == null) {
+            return "unknown";
+        }
+        return root.getCallTarget().toString();
+    }
+
+    public String displayCallTargetName(CallTarget callTarget) {
+        return callTarget.toString();
+    }
+
+    public String displayValue(Object value, int trim) {
+        return trim(value.toString(), trim);
+    }
+
+    public String displayIdentifier(FrameSlot slot) {
+        return slot.getIdentifier().toString();
+    }
+
+    /**
+     * Trims text if {@code trim > 0} to the shorter of {@code trim} or the length of the first line
+     * of test. Identity if {@code trim <= 0}.
+     */
+    protected String trim(String text, int trim) {
+        if (trim == 0) {
+            return text;
+        }
+        final String[] lines = text.split("\n");
+        String result = lines[0];
+        if (lines.length == 1) {
+            if (result.length() <= trim) {
+                return result;
+            }
+            if (trim <= 3) {
+                return result.substring(0, Math.min(result.length() - 1, trim - 1));
+            } else {
+                return result.substring(0, trim - 4) + "...";
+            }
+        }
+        return (result.length() < trim - 3 ? result : result.substring(0, trim - 4)) + "...";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * An exception thrown to model control flow in a Truffle interpreter. The Truffle optimizer has
+ * special knowledge of this exception class for performance optimizations.
+ */
+public class ControlFlowException extends RuntimeException {
+
+    private static final long serialVersionUID = 3676602078425211386L;
+
+    /**
+     * Creates an exception thrown to model control flow.
+     */
+    public ControlFlowException() {
+        /*
+         * We use the super constructor that initializes the cause to null. Without that, the cause
+         * would be this exception itself. This helps escape analysis: it avoids the circle of an
+         * object pointing to itself.
+         */
+        super((Throwable) null);
+    }
+
+    /**
+     * For performance reasons, this exception does not record any stack trace information.
+     */
+    @SuppressWarnings("sync-override")
+    @Override
+    public final Throwable fillInStackTrace() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/DirectCallNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Represents a direct call to a {@link CallTarget}. Direct calls are calls for which the
+ * {@link CallTarget} remains the same for each consecutive call. This part of the Truffle API
+ * enables the runtime system to perform additional optimizations on direct calls.
+ *
+ * Optimizations that can be applied to a {@link DirectCallNode} are inlining and call site
+ * sensitive AST duplication. Inlining inlines this call site into the call graph of the parent
+ * {@link CallTarget}. Call site sensitive AST duplication duplicates the {@link CallTarget} in an
+ * uninitialized state to collect call site sensitive profiling information.
+ *
+ * Please note: This class is not intended to be subclassed by guest language implementations.
+ *
+ * @see IndirectCallNode for calls with a non-constant target
+ * @see TruffleRuntime#createDirectCallNode(CallTarget)
+ * @see #forceInlining()
+ * @see #cloneCallTarget()
+ */
+public abstract class DirectCallNode extends Node {
+
+    protected final CallTarget callTarget;
+
+    protected DirectCallNode(CallTarget callTarget) {
+        this.callTarget = callTarget;
+    }
+
+    /**
+     * Calls the inner {@link CallTarget} returned by {@link #getCurrentCallTarget()}.
+     *
+     * @param arguments the arguments that should be passed to the callee
+     * @return the return result of the call
+     */
+    public abstract Object call(VirtualFrame frame, Object[] arguments);
+
+    /**
+     * Returns the originally supplied {@link CallTarget} when this call node was created. Please
+     * note that the returned {@link CallTarget} is not necessarily the {@link CallTarget} that is
+     * called. For that use {@link #getCurrentCallTarget()} instead.
+     *
+     * @return the {@link CallTarget} provided.
+     */
+    public CallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    /**
+     * Returns <code>true</code> if the underlying runtime system supports inlining for the
+     * {@link CallTarget} in this {@link DirectCallNode}.
+     *
+     * @return true if inlining is supported.
+     */
+    public abstract boolean isInlinable();
+
+    /**
+     * Returns <code>true</code> if the {@link CallTarget} is forced to be inlined. A
+     * {@link DirectCallNode} can either be inlined manually by invoking {@link #forceInlining()} or
+     * by the runtime system which may at any point decide to inline.
+     *
+     * @return true if this method was inlined else false.
+     */
+    public abstract boolean isInliningForced();
+
+    /**
+     * Enforces the runtime system to inline the {@link CallTarget} at this call site. If the
+     * runtime system does not support inlining or it is already inlined this method has no effect.
+     * The runtime system may decide to not inline calls which were forced to inline.
+     */
+    public abstract void forceInlining();
+
+    /**
+     * Returns true if the runtime system has decided to inline this call-site. If the
+     * {@link DirectCallNode} was forced to inline then this does not necessarily mean that the
+     * {@link DirectCallNode} is really going to be inlined. This depends on whether or not the
+     * runtime system supports inlining. The runtime system may also decide to not inline calls
+     * which were forced to inline.
+     *
+     * @deprecated we do not expose this information any longer. returns always false.
+     */
+    @SuppressWarnings("static-method")
+    @Deprecated
+    public final boolean isInlined() {
+        return false;
+    }
+
+    /**
+     * Returns <code>true</code> if the runtime system supports cloning and the {@link RootNode}
+     * returns <code>true</code> in {@link RootNode#isCloningAllowed()}.
+     *
+     * @return <code>true</code> if the target is allowed to be cloned.
+     */
+    public abstract boolean isCallTargetCloningAllowed();
+
+    /**
+     * Clones the {@link CallTarget} instance returned by {@link #getCallTarget()} in an
+     * uninitialized state for this {@link DirectCallNode}. This can be sensible to gather call site
+     * sensitive profiling information for this {@link DirectCallNode}. If
+     * {@link #isCallTargetCloningAllowed()} returns <code>false</code> this method has no effect
+     * and returns <code>false</code>.
+     */
+    public abstract boolean cloneCallTarget();
+
+    /**
+     * Returns <code>true</code> if the target of the {@link DirectCallNode} was cloned by the
+     * runtime system or by the guest language implementation.
+     *
+     * @return if the target was split
+     */
+    public final boolean isCallTargetCloned() {
+        return getClonedCallTarget() != null;
+    }
+
+    /**
+     * Returns the split {@link CallTarget} if this call site's {@link CallTarget} is cloned.
+     *
+     * @return the split {@link CallTarget}
+     */
+    public abstract CallTarget getClonedCallTarget();
+
+    /**
+     * Returns the used call target when {@link #call(VirtualFrame, Object[])} is invoked. If the
+     * {@link CallTarget} was split this method returns the {@link CallTarget} returned by
+     * {@link #getClonedCallTarget()}.
+     *
+     * @return the used {@link CallTarget} when node is called
+     */
+    public CallTarget getCurrentCallTarget() {
+        CallTarget split = getClonedCallTarget();
+        if (split != null) {
+            return split;
+        } else {
+            return getCallTarget();
+        }
+    }
+
+    /**
+     * Returns the {@link RootNode} associated with {@link CallTarget} returned by
+     * {@link #getCurrentCallTarget()}. If the stored {@link CallTarget} does not contain a
+     * {@link RootNode} this method returns <code>null</code>.
+     *
+     * @see #getCurrentCallTarget()
+     * @return the root node of the used call target
+     */
+    public final RootNode getCurrentRootNode() {
+        CallTarget target = getCurrentCallTarget();
+        if (target instanceof RootCallTarget) {
+            return ((RootCallTarget) target).getRootNode();
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(target=%s)", getClass().getSimpleName(), getCurrentCallTarget());
+    }
+
+    public static DirectCallNode create(CallTarget target) {
+        return Truffle.getRuntime().createDirectCallNode(target);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+
+/**
+ * Specifies for a method that the loops with constant number of invocations should be fully
+ * unrolled.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface ExplodeLoop {
+    boolean merge() default false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.net.*;
+import java.util.*;
+
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+
+import org.w3c.dom.*;
+
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+
+/**
+ * Utility class for creating output for the ideal graph visualizer.
+ */
+public class GraphPrintVisitor {
+
+    public static final String GraphVisualizerAddress = "127.0.0.1";
+    public static final int GraphVisualizerPort = 4444;
+
+    private Document dom;
+    private Map<Object, Element> nodeMap;
+    private List<Element> edgeList;
+    private Map<Object, Element> prevNodeMap;
+    private int id;
+    private Element graphDocument;
+    private Element groupElement;
+    private Element graphElement;
+    private Element nodesElement;
+    private Element edgesElement;
+
+    public GraphPrintVisitor() {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+
+            dom = db.newDocument();
+        } catch (ParserConfigurationException ex) {
+            throw new RuntimeException(ex);
+        }
+
+        graphDocument = dom.createElement("graphDocument");
+        dom.appendChild(graphDocument);
+    }
+
+    public GraphPrintVisitor beginGroup(String groupName) {
+        groupElement = dom.createElement("group");
+        graphDocument.appendChild(groupElement);
+        Element properties = dom.createElement("properties");
+        groupElement.appendChild(properties);
+
+        if (!groupName.isEmpty()) {
+            // set group name
+            Element propName = dom.createElement("p");
+            propName.setAttribute("name", "name");
+            propName.setTextContent(groupName);
+            properties.appendChild(propName);
+        }
+
+        // forget old nodes
+        nodeMap = prevNodeMap = null;
+        edgeList = null;
+
+        return this;
+    }
+
+    public GraphPrintVisitor beginGraph(String graphName) {
+        if (null == groupElement) {
+            beginGroup("");
+        } else if (null != prevNodeMap) {
+            // TODO: difference (create removeNode,removeEdge elements)
+        }
+
+        graphElement = dom.createElement("graph");
+        groupElement.appendChild(graphElement);
+        Element properties = dom.createElement("properties");
+        graphElement.appendChild(properties);
+        nodesElement = dom.createElement("nodes");
+        graphElement.appendChild(nodesElement);
+        edgesElement = dom.createElement("edges");
+        graphElement.appendChild(edgesElement);
+
+        // set graph name
+        Element propName = dom.createElement("p");
+        propName.setAttribute("name", "name");
+        propName.setTextContent(graphName);
+        properties.appendChild(propName);
+
+        // save old nodes
+        prevNodeMap = nodeMap;
+        nodeMap = new IdentityHashMap<>();
+        edgeList = new ArrayList<>();
+
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        if (null != dom) {
+            try {
+                Transformer tr = TransformerFactory.newInstance().newTransformer();
+                tr.setOutputProperty(OutputKeys.INDENT, "yes");
+                tr.setOutputProperty(OutputKeys.METHOD, "xml");
+                tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+                StringWriter strWriter = new StringWriter();
+                tr.transform(new DOMSource(dom), new StreamResult(strWriter));
+                return strWriter.toString();
+            } catch (TransformerException e) {
+                e.printStackTrace();
+            }
+        }
+        return "";
+    }
+
+    public void printToFile(File f) {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.INDENT, "yes");
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+            tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(f)));
+        } catch (TransformerException | FileNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void printToSysout() {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.INDENT, "yes");
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+            tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+            tr.transform(new DOMSource(dom), new StreamResult(System.out));
+        } catch (TransformerException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void printToNetwork(boolean ignoreErrors) {
+        try {
+            Transformer tr = TransformerFactory.newInstance().newTransformer();
+            tr.setOutputProperty(OutputKeys.METHOD, "xml");
+
+            Socket socket = new Socket(GraphVisualizerAddress, GraphVisualizerPort);
+            BufferedOutputStream stream = new BufferedOutputStream(socket.getOutputStream(), 0x4000);
+            tr.transform(new DOMSource(dom), new StreamResult(stream));
+        } catch (TransformerException | IOException e) {
+            if (!ignoreErrors) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private String nextId() {
+        return String.valueOf(id++);
+    }
+
+    private String oldOrNextId(Object node) {
+        if (null != prevNodeMap && prevNodeMap.containsKey(node)) {
+            Element nodeElem = prevNodeMap.get(node);
+            return nodeElem.getAttribute("id");
+        } else {
+            return nextId();
+        }
+    }
+
+    protected Element getElementByObject(Object op) {
+        return nodeMap.get(op);
+    }
+
+    protected void createElementForNode(Object node) {
+        boolean exists = nodeMap.containsKey(node);
+        if (!exists || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) {
+            Element nodeElem = dom.createElement("node");
+            nodeElem.setAttribute("id", !exists ? oldOrNextId(node) : nextId());
+            nodeMap.put(node, nodeElem);
+            Element properties = dom.createElement("properties");
+            nodeElem.appendChild(properties);
+            nodesElement.appendChild(nodeElem);
+
+            setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", ""));
+            NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class);
+            if (nodeInfo != null) {
+                setNodeProperty(node, "cost", nodeInfo.cost());
+                if (!nodeInfo.shortName().isEmpty()) {
+                    setNodeProperty(node, "shortName", nodeInfo.shortName());
+                }
+            }
+            setNodeProperty(node, "class", node.getClass().getSimpleName());
+            if (node instanceof Node) {
+                readNodeProperties((Node) node);
+                copyDebugProperties((Node) node);
+            }
+        }
+    }
+
+    private Element getPropertyElement(Object node, String propertyName) {
+        Element nodeElem = getElementByObject(node);
+        Element propertiesElem = (Element) nodeElem.getElementsByTagName("properties").item(0);
+        if (propertiesElem == null) {
+            return null;
+        }
+
+        NodeList propList = propertiesElem.getElementsByTagName("p");
+        for (int i = 0; i < propList.getLength(); i++) {
+            Element p = (Element) propList.item(i);
+            if (propertyName.equals(p.getAttribute("name"))) {
+                return p;
+            }
+        }
+        return null;
+    }
+
+    protected void setNodeProperty(Object node, String propertyName, Object value) {
+        Element nodeElem = getElementByObject(node);
+        Element propElem = getPropertyElement(node, propertyName); // if property exists, replace
+                                                                   // its value
+        if (null == propElem) { // if property doesn't exist, create one
+            propElem = dom.createElement("p");
+            propElem.setAttribute("name", propertyName);
+            nodeElem.getElementsByTagName("properties").item(0).appendChild(propElem);
+        }
+        propElem.setTextContent(String.valueOf(value));
+    }
+
+    private void copyDebugProperties(Node node) {
+        Map<String, Object> debugProperties = node.getDebugProperties();
+        for (Map.Entry<String, Object> property : debugProperties.entrySet()) {
+            setNodeProperty(node, property.getKey(), property.getValue());
+        }
+    }
+
+    private void readNodeProperties(Node node) {
+        NodeFieldAccessor[] fields = node.getNodeClass().getFields();
+        for (NodeFieldAccessor field : fields) {
+            if (field.getKind() == NodeFieldKind.DATA) {
+                String key = field.getName();
+                if (getPropertyElement(node, key) == null) {
+                    Object value = field.loadValue(node);
+                    setNodeProperty(node, key, value);
+                }
+            }
+        }
+    }
+
+    protected void connectNodes(Object a, Object b, String label) {
+        if (nodeMap.get(a) == null || nodeMap.get(b) == null) {
+            return;
+        }
+
+        String fromId = nodeMap.get(a).getAttribute("id");
+        String toId = nodeMap.get(b).getAttribute("id");
+
+        // count existing to-edges
+        int count = 0;
+        for (Element e : edgeList) {
+            if (e.getAttribute("to").equals(toId)) {
+                ++count;
+            }
+        }
+
+        Element edgeElem = dom.createElement("edge");
+        edgeElem.setAttribute("from", fromId);
+        edgeElem.setAttribute("to", toId);
+        edgeElem.setAttribute("index", String.valueOf(count));
+        if (label != null) {
+            edgeElem.setAttribute("label", label);
+        }
+        edgesElement.appendChild(edgeElem);
+        edgeList.add(edgeElem);
+    }
+
+    public GraphPrintVisitor visit(Object node) {
+        if (null == graphElement) {
+            beginGraph("truffle tree");
+        }
+
+        // if node is visited once again, skip
+        if (getElementByObject(node) != null && NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) == null) {
+            return this;
+        }
+
+        // respect node's custom handler
+        if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) {
+            Class<? extends GraphPrintHandler> customHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler();
+            try {
+                GraphPrintHandler customHandler = customHandlerClass.newInstance();
+                customHandler.visit(node, new GraphPrintAdapter());
+            } catch (InstantiationException | IllegalAccessException e) {
+                assert false : e;
+            }
+        } else if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) {
+            // ignore
+        } else {
+            // default handler
+            createElementForNode(node);
+
+            if (node instanceof Node) {
+                for (Map.Entry<String, Node> child : findNamedNodeChildren((Node) node).entrySet()) {
+                    visit(child.getValue());
+                    connectNodes(node, child.getValue(), child.getKey());
+                }
+            }
+        }
+
+        return this;
+    }
+
+    private static LinkedHashMap<String, Node> findNamedNodeChildren(Node node) {
+        LinkedHashMap<String, Node> nodes = new LinkedHashMap<>();
+        NodeClass nodeClass = node.getNodeClass();
+
+        for (NodeFieldAccessor field : nodeClass.getFields()) {
+            NodeFieldKind kind = field.getKind();
+            if (kind == NodeFieldKind.CHILD || kind == NodeFieldKind.CHILDREN) {
+                Object value = field.loadValue(node);
+                if (value != null) {
+                    if (kind == NodeFieldKind.CHILD) {
+                        nodes.put(field.getName(), (Node) value);
+                    } else if (kind == NodeFieldKind.CHILDREN) {
+                        Object[] children = (Object[]) value;
+                        for (int i = 0; i < children.length; i++) {
+                            if (children[i] != null) {
+                                nodes.put(field.getName() + "[" + i + "]", (Node) children[i]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return nodes;
+    }
+
+    public class GraphPrintAdapter {
+
+        public void createElementForNode(Object node) {
+            GraphPrintVisitor.this.createElementForNode(node);
+        }
+
+        public void visit(Object node) {
+            GraphPrintVisitor.this.visit(node);
+        }
+
+        public void connectNodes(Object node, Object child) {
+            GraphPrintVisitor.this.connectNodes(node, child, null);
+        }
+
+        public void setNodeProperty(Object node, String propertyName, Object value) {
+            GraphPrintVisitor.this.setNodeProperty(node, propertyName, value);
+        }
+    }
+
+    public interface GraphPrintHandler {
+
+        void visit(Object node, GraphPrintAdapter gPrinter);
+    }
+
+    public interface ChildSupplier {
+
+        /** Supplies an additional child if available. */
+        Object startNode(Object callNode);
+
+        void endNode(Object callNode);
+
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface CustomGraphPrintHandler {
+
+        Class<? extends GraphPrintHandler> handler();
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface NullGraphPrintHandler {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.TYPE)
+    public @interface GraphDuplicate {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public @interface HiddenField {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/IndirectCallNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Represents an indirect call to a {@link CallTarget}. Indirect calls are calls for which the
+ * {@link CallTarget} may change dynamically for each consecutive call. This part of the Truffle API
+ * enables the runtime system to perform additional optimizations on indirect calls.
+ *
+ * Please note: This class is not intended to be sub classed by guest language implementations.
+ *
+ * @see DirectCallNode for faster calls with a constantly known {@link CallTarget}.
+ */
+public abstract class IndirectCallNode extends Node {
+
+    /**
+     * Performs an indirect call to the given {@link CallTarget} target with the provided arguments.
+     *
+     * @param frame the caller frame
+     * @param target the {@link CallTarget} to call
+     * @param arguments the arguments to provide
+     * @return the return value of the call
+     */
+    public abstract Object call(VirtualFrame frame, CallTarget target, Object[] arguments);
+
+    public static IndirectCallNode create() {
+        return Truffle.getRuntime().createIndirectCallNode();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InvalidAssumptionException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * An exception that should be thrown if an assumption is checked and the check fails. The Truffle
+ * optimizer has special knowledge of this exception class and will never compile a catch block that
+ * catches this exception type.
+ */
+public final class InvalidAssumptionException extends SlowPathException {
+
+    private static final long serialVersionUID = -6801338218909717979L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/LoopNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Experimental API: may change significantly without notice.
+ */
+public abstract class LoopNode extends Node {
+
+    public abstract void executeLoop(VirtualFrame frame);
+
+    public abstract RepeatingNode getRepeatingNode();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+
+/**
+ * Abstract base class for all Truffle nodes.
+ */
+public abstract class Node implements NodeInterface, Cloneable {
+
+    private final NodeClass nodeClass;
+    @CompilationFinal private Node parent;
+    @CompilationFinal private SourceSection sourceSection;
+
+    /**
+     * Marks array fields that are children of this node.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Children {
+    }
+
+    /**
+     * Marks fields that represent child nodes of this node.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Child {
+    }
+
+    protected Node() {
+        this(null);
+    }
+
+    protected Node(SourceSection sourceSection) {
+        CompilerAsserts.neverPartOfCompilation();
+        this.sourceSection = sourceSection;
+        this.nodeClass = NodeClass.get(getClass());
+        if (TruffleOptions.TraceASTJSON) {
+            JSONHelper.dumpNewNode(this);
+        }
+    }
+
+    /**
+     * Assigns a link to a guest language source section to this node.
+     *
+     * @param section the object representing a section in guest language source code
+     */
+    public final void assignSourceSection(SourceSection section) {
+        if (sourceSection != null) {
+            // Patch this test during the transition to constructor-based
+            // source attribution, which would otherwise trigger this
+            // exception. This method will eventually be deprecated.
+            if (getSourceSection() != section) {
+                throw new IllegalStateException("Source section is already assigned. Old: " + getSourceSection() + ", new: " + section);
+            }
+        }
+        this.sourceSection = section;
+    }
+
+    NodeClass getNodeClass() {
+        return nodeClass;
+    }
+
+    /**
+     * Returns a rough estimate for the cost of this {@link Node}. This estimate can be used by
+     * runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method
+     * is intended to be overridden by subclasses. The default implementation returns the value of
+     * {@link NodeInfo#cost()} of the {@link NodeInfo} annotation declared at the subclass. If no
+     * {@link NodeInfo} annotation is declared the method returns {@link NodeCost#MONOMORPHIC} as a
+     * default value.
+     */
+    public NodeCost getCost() {
+        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
+        if (info != null) {
+            return info.cost();
+        }
+        return NodeCost.MONOMORPHIC;
+    }
+
+    /**
+     * Clears any previously assigned guest language source code from this node.
+     */
+    public final void clearSourceSection() {
+        this.sourceSection = null;
+    }
+
+    /**
+     * Retrieves the segment of guest language source code that is represented by this Node.
+     *
+     * @return the source code represented by this Node
+     */
+    public final SourceSection getSourceSection() {
+        return sourceSection;
+    }
+
+    /**
+     * Retrieves the segment of guest language source code that is represented by this Node, if
+     * present; otherwise retrieves the segment represented by the nearest AST ancestor that has
+     * this information.
+     *
+     * @return an approximation of the source code represented by this Node
+     */
+    @ExplodeLoop
+    public final SourceSection getEncapsulatingSourceSection() {
+        Node current = this;
+        while (current != null) {
+            if (current.sourceSection != null) {
+                return current.sourceSection;
+            }
+            current = current.parent;
+        }
+        return null;
+    }
+
+    /**
+     * Method that updates the link to the parent in the array of specified new child nodes to this
+     * node.
+     *
+     * @param newChildren the array of new children whose parent should be updated
+     * @return the array of new children
+     */
+    protected final <T extends Node> T[] insert(final T[] newChildren) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        assert newChildren != null;
+        for (Node newChild : newChildren) {
+            adoptHelper(newChild);
+        }
+        return newChildren;
+    }
+
+    /**
+     * Method that updates the link to the parent in the specified new child node to this node.
+     *
+     * @param newChild the new child whose parent should be updated
+     * @return the new child
+     */
+    protected final <T extends Node> T insert(final T newChild) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        assert newChild != null;
+        adoptHelper(newChild);
+        return newChild;
+    }
+
+    public final void adoptChildren() {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        adoptHelper();
+    }
+
+    private void adoptHelper(final Node newChild) {
+        assert newChild != null;
+        if (newChild == this) {
+            throw new IllegalStateException("The parent of a node can never be the node itself.");
+        }
+        newChild.parent = this;
+        if (TruffleOptions.TraceASTJSON) {
+            JSONHelper.dumpNewChild(this, newChild);
+        }
+        newChild.adoptHelper();
+    }
+
+    private void adoptHelper() {
+        Iterable<Node> children = this.getChildren();
+        for (Node child : children) {
+            if (child != null && child.getParent() != this) {
+                this.adoptHelper(child);
+            }
+        }
+    }
+
+    private void adoptUnadoptedHelper(final Node newChild) {
+        assert newChild != null;
+        if (newChild == this) {
+            throw new IllegalStateException("The parent of a node can never be the node itself.");
+        }
+        newChild.parent = this;
+        newChild.adoptUnadoptedHelper();
+    }
+
+    private void adoptUnadoptedHelper() {
+        Iterable<Node> children = this.getChildren();
+        for (Node child : children) {
+            if (child != null && child.getParent() == null) {
+                this.adoptUnadoptedHelper(child);
+            }
+        }
+    }
+
+    /**
+     * Returns properties of this node interesting for debugging and can be overwritten by
+     * subclasses to add their own custom properties.
+     *
+     * @return the properties as a key/value hash map
+     */
+    public Map<String, Object> getDebugProperties() {
+        Map<String, Object> properties = new HashMap<>();
+        return properties;
+    }
+
+    /**
+     * The current parent node of this node.
+     *
+     * @return the parent node
+     */
+    public final Node getParent() {
+        return parent;
+    }
+
+    /**
+     * Replaces this node with another node. If there is a source section (see
+     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
+     *
+     * @param newNode the new node that is the replacement
+     * @param reason a description of the reason for the replacement
+     * @return the new node
+     */
+    public final <T extends Node> T replace(final T newNode, final CharSequence reason) {
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        atomic(new Runnable() {
+            public void run() {
+                replaceHelper(newNode, reason);
+            }
+        });
+        return newNode;
+    }
+
+    /**
+     * Replaces this node with another node. If there is a source section (see
+     * {@link #getSourceSection()}) associated with this node, it is transferred to the new node.
+     *
+     * @param newNode the new node that is the replacement
+     * @return the new node
+     */
+    public final <T extends Node> T replace(T newNode) {
+        return replace(newNode, "");
+    }
+
+    final void replaceHelper(Node newNode, CharSequence reason) {
+        CompilerAsserts.neverPartOfCompilation();
+        assert inAtomicBlock();
+        if (this.getParent() == null) {
+            throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent.");
+        }
+        if (sourceSection != null && newNode.getSourceSection() == null) {
+            // Pass on the source section to the new node.
+            newNode.assignSourceSection(sourceSection);
+        }
+        // (aw) need to set parent *before* replace, so that (unsynchronized) getRootNode()
+        // will always find the root node
+        newNode.parent = this.parent;
+        if (NodeUtil.replaceChild(this.parent, this, newNode)) {
+            this.parent.adoptHelper(newNode);
+        } else {
+            this.parent.adoptUnadoptedHelper(newNode);
+        }
+        reportReplace(this, newNode, reason);
+        onReplace(newNode, reason);
+    }
+
+    /**
+     * Checks if this node can be replaced by another node: tree structure & type.
+     */
+    public final boolean isSafelyReplaceableBy(Node newNode) {
+        return NodeUtil.isReplacementSafe(getParent(), this, newNode);
+    }
+
+    private void reportReplace(Node oldNode, Node newNode, CharSequence reason) {
+        Node node = this;
+        while (node != null) {
+            boolean consumed = false;
+            if (node instanceof ReplaceObserver) {
+                consumed = ((ReplaceObserver) node).nodeReplaced(oldNode, newNode, reason);
+            } else if (node instanceof RootNode) {
+                CallTarget target = ((RootNode) node).getCallTarget();
+                if (target instanceof ReplaceObserver) {
+                    consumed = ((ReplaceObserver) target).nodeReplaced(oldNode, newNode, reason);
+                }
+            }
+            if (consumed) {
+                break;
+            }
+            node = node.getParent();
+        }
+        if (TruffleOptions.TraceRewrites) {
+            NodeUtil.traceRewrite(this, newNode, reason);
+        }
+        if (TruffleOptions.TraceASTJSON) {
+            JSONHelper.dumpReplaceChild(this, newNode, reason);
+        }
+    }
+
+    /**
+     * Intended to be implemented by subclasses of {@link Node} to receive a notification when the
+     * node is rewritten. This method is invoked before the actual replace has happened.
+     *
+     * @param newNode the replacement node
+     * @param reason the reason the replace supplied
+     */
+    protected void onReplace(Node newNode, CharSequence reason) {
+        // empty default
+    }
+
+    /**
+     * Invokes the {@link NodeVisitor#visit(Node)} method for this node and recursively also for all
+     * child nodes.
+     *
+     * @param nodeVisitor the visitor
+     */
+    public final void accept(NodeVisitor nodeVisitor) {
+        if (nodeVisitor.visit(this)) {
+            NodeUtil.forEachChildRecursive(this, nodeVisitor);
+        }
+    }
+
+    /**
+     * Iterator over the children of this node.
+     *
+     * @return the iterator
+     */
+    public final Iterable<Node> getChildren() {
+        return new Iterable<Node>() {
+            public Iterator<Node> iterator() {
+                return getNodeClass().makeIterator(Node.this);
+            }
+        };
+    }
+
+    /**
+     * Creates a shallow copy of this node.
+     *
+     * @return the new copy
+     */
+    public Node copy() {
+        try {
+            return (Node) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Creates a deep copy of this node.
+     *
+     * @return the new deep copy
+     */
+    public Node deepCopy() {
+        return NodeUtil.deepCopyImpl(this);
+    }
+
+    /**
+     * This method must never be called. It enforces that {@link Object#clone} is not directly
+     * called by subclasses. Use the {@link #copy()} method instead.
+     */
+    @Override
+    @Deprecated
+    protected final Object clone() throws CloneNotSupportedException {
+        throw new IllegalStateException("This method should never be called, use the copy method instead!");
+    }
+
+    /**
+     * Get the root node of the tree a node belongs to.
+     *
+     * @return the {@link RootNode} or {@code null} if there is none.
+     */
+    public final RootNode getRootNode() {
+        Node rootNode = this;
+        while (rootNode.getParent() != null) {
+            assert !(rootNode instanceof RootNode) : "root node must not have a parent";
+            rootNode = rootNode.getParent();
+        }
+        if (rootNode instanceof RootNode) {
+            return (RootNode) rootNode;
+        }
+        return null;
+    }
+
+    /**
+     * Any node for which this is {@code true} can be "instrumented" by installing a {@link Probe}
+     * that intercepts execution events at the node and routes them to any {@link Instrument}s that
+     * have been attached to the {@link Probe}. Only one {@link Probe} may be installed at each
+     * node; subsequent calls return the one already installed.
+     * <p>
+     * <b>Note:</b> instrumentation requires a appropriate {@link WrapperNode}, which must be
+     * provided by {@link #createWrapperNode()}.
+     *
+     * @see Instrument
+     */
+    public boolean isInstrumentable() {
+        return false;
+    }
+
+    /**
+     * For any node that {@link #isInstrumentable()}, this method must return a {@link Node} that:
+     * <ol>
+     * <li>implements {@link WrapperNode}</li>
+     * <li>has {@code this} as it's child, and</li>
+     * <li>whose type is safe for replacement of {@code this} in the parent.</li>
+     * </ol>
+     *
+     * @return an appropriately typed {@link WrapperNode} if {@link #isInstrumentable()}.
+     */
+    public WrapperNode createWrapperNode() {
+        return null;
+    }
+
+    /**
+     * Enables {@linkplain Instrument instrumentation} of a node, where the node is presumed to be
+     * part of a well-formed Truffle AST that is not being executed. If this node has not already
+     * been probed, modifies the AST by inserting a {@linkplain WrapperNode wrapper node} between
+     * the node and its parent; the wrapper node must be provided by implementations of
+     * {@link #createWrapperNode()}. No more than one {@link Probe} may be associated with a node,
+     * so a {@linkplain WrapperNode wrapper} may not wrap another {@linkplain WrapperNode wrapper}.
+     *
+     * @return a (possibly newly created) {@link Probe} associated with this node.
+     * @throws ProbeException (unchecked) when a probe cannot be created, leaving the AST unchanged
+     */
+    public final Probe probe() {
+
+        if (this instanceof WrapperNode) {
+            throw new ProbeException(ProbeFailure.Reason.WRAPPER_NODE, null, this, null);
+        }
+
+        if (parent == null) {
+            throw new ProbeException(ProbeFailure.Reason.NO_PARENT, null, this, null);
+        }
+
+        if (parent instanceof WrapperNode) {
+            return ((WrapperNode) parent).getProbe();
+        }
+
+        if (!isInstrumentable()) {
+            throw new ProbeException(ProbeFailure.Reason.NOT_INSTRUMENTABLE, parent, this, null);
+        }
+
+        // Create a new wrapper/probe with this node as its child.
+        final WrapperNode wrapper = createWrapperNode();
+
+        if (wrapper == null || !(wrapper instanceof Node)) {
+            throw new ProbeException(ProbeFailure.Reason.NO_WRAPPER, parent, this, wrapper);
+        }
+
+        final Node wrapperNode = (Node) wrapper;
+
+        if (!this.isSafelyReplaceableBy(wrapperNode)) {
+            throw new ProbeException(ProbeFailure.Reason.WRAPPER_TYPE, parent, this, wrapper);
+        }
+
+        // Connect it to a Probe
+        final Probe probe = ProbeNode.insertProbe(wrapper);
+
+        // Replace this node in the AST with the wrapper
+        this.replace(wrapperNode);
+
+        return probe;
+    }
+
+    /**
+     * Converts this node to a textual representation useful for debugging.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(getClass().getSimpleName());
+        Map<String, Object> properties = getDebugProperties();
+        boolean hasProperties = false;
+        for (Map.Entry<String, Object> entry : properties.entrySet()) {
+            sb.append(hasProperties ? "," : "<");
+            hasProperties = true;
+            sb.append(entry.getKey()).append("=").append(entry.getValue());
+        }
+        if (hasProperties) {
+            sb.append(">");
+        }
+        sb.append("@").append(Integer.toHexString(hashCode()));
+        return sb.toString();
+    }
+
+    public final void atomic(Runnable closure) {
+        RootNode rootNode = getRootNode();
+        synchronized (rootNode != null ? rootNode : GIL) {
+            assert enterAtomic();
+            try {
+                closure.run();
+            } finally {
+                assert exitAtomic();
+            }
+        }
+    }
+
+    public final <T> T atomic(Callable<T> closure) {
+        try {
+            RootNode rootNode = getRootNode();
+            synchronized (rootNode != null ? rootNode : GIL) {
+                assert enterAtomic();
+                try {
+                    return closure.call();
+                } finally {
+                    assert exitAtomic();
+                }
+            }
+        } catch (RuntimeException | Error e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns a user-readable description of the purpose of the Node, or "" if no description is
+     * available.
+     */
+    public String getDescription() {
+        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
+        if (info != null) {
+            return info.description();
+        }
+        return "";
+    }
+
+    /**
+     * Returns a string representing the language this node has been implemented for. If the
+     * language is unknown, returns "".
+     */
+    public String getLanguage() {
+        NodeInfo info = getClass().getAnnotation(NodeInfo.class);
+        if (info != null && info.language() != null && info.language().length() > 0) {
+            return info.language();
+        }
+        if (parent != null) {
+            return parent.getLanguage();
+        }
+        return "";
+    }
+
+    private static final Object GIL = new Object();
+
+    private static final ThreadLocal<Integer> IN_ATOMIC_BLOCK = new ThreadLocal<Integer>() {
+        @Override
+        protected Integer initialValue() {
+            return 0;
+        }
+    };
+
+    private static boolean inAtomicBlock() {
+        return IN_ATOMIC_BLOCK.get() > 0;
+    }
+
+    private static boolean enterAtomic() {
+        IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() + 1);
+        return true;
+    }
+
+    private static boolean exitAtomic() {
+        IN_ATOMIC_BLOCK.set(IN_ATOMIC_BLOCK.get() - 1);
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+
+/**
+ * Information about a {@link Node} class. A single instance of this class is allocated for every
+ * subclass of {@link Node} that is used.
+ */
+public final class NodeClass {
+    private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
+        @SuppressWarnings("unchecked")
+        @Override
+        protected NodeClass computeValue(final Class<?> clazz) {
+            assert Node.class.isAssignableFrom(clazz);
+            return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
+                public NodeClass run() {
+                    return new NodeClass((Class<? extends Node>) clazz);
+                }
+            });
+        }
+    };
+
+    // The comprehensive list of all fields.
+    private final NodeFieldAccessor[] fields;
+    // Separate arrays for the frequently accessed fields.
+    private final NodeFieldAccessor parentField;
+    private final NodeFieldAccessor nodeClassField;
+    private final NodeFieldAccessor[] childFields;
+    private final NodeFieldAccessor[] childrenFields;
+    private final NodeFieldAccessor[] cloneableFields;
+
+    private final Class<? extends Node> clazz;
+
+    public static NodeClass get(Class<? extends Node> clazz) {
+        return nodeClasses.get(clazz);
+    }
+
+    public static NodeClass get(Node clazz) {
+        return clazz.getNodeClass();
+    }
+
+    public NodeClass(Class<? extends Node> clazz) {
+        List<NodeFieldAccessor> fieldsList = new ArrayList<>();
+        NodeFieldAccessor parentFieldTmp = null;
+        NodeFieldAccessor nodeClassFieldTmp = null;
+        List<NodeFieldAccessor> childFieldList = new ArrayList<>();
+        List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
+        List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
+
+        for (Field field : NodeUtil.getAllFields(clazz)) {
+            if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
+                continue;
+            }
+
+            NodeFieldAccessor nodeField;
+            if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
+                assert Node.class.isAssignableFrom(field.getType());
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
+                parentFieldTmp = nodeField;
+            } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) {
+                assert NodeClass.class.isAssignableFrom(field.getType());
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field);
+                nodeClassFieldTmp = nodeField;
+            } else if (field.getAnnotation(Child.class) != null) {
+                checkChildField(field);
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field);
+                childFieldList.add(nodeField);
+            } else if (field.getAnnotation(Children.class) != null) {
+                checkChildrenField(field);
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILDREN, field);
+                childrenFieldList.add(nodeField);
+            } else {
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.DATA, field);
+                if (NodeCloneable.class.isAssignableFrom(field.getType())) {
+                    cloneableFieldList.add(nodeField);
+                }
+            }
+            fieldsList.add(nodeField);
+        }
+
+        if (parentFieldTmp == null) {
+            throw new AssertionError("parent field not found");
+        }
+
+        this.fields = fieldsList.toArray(new NodeFieldAccessor[fieldsList.size()]);
+        this.nodeClassField = nodeClassFieldTmp;
+        this.parentField = parentFieldTmp;
+        this.childFields = childFieldList.toArray(new NodeFieldAccessor[childFieldList.size()]);
+        this.childrenFields = childrenFieldList.toArray(new NodeFieldAccessor[childrenFieldList.size()]);
+        this.cloneableFields = cloneableFieldList.toArray(new NodeFieldAccessor[cloneableFieldList.size()]);
+        this.clazz = clazz;
+    }
+
+    public NodeFieldAccessor getNodeClassField() {
+        return nodeClassField;
+    }
+
+    public NodeFieldAccessor[] getCloneableFields() {
+        return cloneableFields;
+    }
+
+    private static boolean isNodeType(Class<?> clazz) {
+        return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
+    }
+
+    private static void checkChildField(Field field) {
+        if (!isNodeType(field.getType())) {
+            throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
+        }
+        if (Modifier.isFinal(field.getModifiers())) {
+            throw new AssertionError("@Child field must not be final (" + field + ")");
+        }
+    }
+
+    private static void checkChildrenField(Field field) {
+        if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
+            throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
+        }
+        if (!Modifier.isFinal(field.getModifiers())) {
+            throw new AssertionError("@Children field must be final (" + field + ")");
+        }
+    }
+
+    public NodeFieldAccessor[] getFields() {
+        return fields;
+    }
+
+    public NodeFieldAccessor getParentField() {
+        return parentField;
+    }
+
+    public NodeFieldAccessor[] getChildFields() {
+        return childFields;
+    }
+
+    public NodeFieldAccessor[] getChildrenFields() {
+        return childrenFields;
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NodeClass) {
+            NodeClass other = (NodeClass) obj;
+            return clazz.equals(other.clazz);
+        }
+        return false;
+    }
+
+    public Iterator<Node> makeIterator(Node node) {
+        assert clazz.isInstance(node);
+        return new NodeIterator(this, node);
+    }
+
+    private static final class NodeIterator implements Iterator<Node> {
+        private final NodeFieldAccessor[] childFields;
+        private final NodeFieldAccessor[] childrenFields;
+        private final Node node;
+        private final int childrenCount;
+        private int index;
+
+        protected NodeIterator(NodeClass nodeClass, Node node) {
+            this.childFields = nodeClass.getChildFields();
+            this.childrenFields = nodeClass.getChildrenFields();
+            this.node = node;
+            this.childrenCount = childrenCount();
+            this.index = 0;
+        }
+
+        private int childrenCount() {
+            int nodeCount = childFields.length;
+            for (NodeFieldAccessor childrenField : childrenFields) {
+                Object[] children = ((Object[]) childrenField.getObject(node));
+                if (children != null) {
+                    nodeCount += children.length;
+                }
+            }
+            return nodeCount;
+        }
+
+        private Node nodeAt(int idx) {
+            int nodeCount = childFields.length;
+            if (idx < nodeCount) {
+                return (Node) childFields[idx].getObject(node);
+            } else {
+                for (NodeFieldAccessor childrenField : childrenFields) {
+                    Object[] nodeArray = (Object[]) childrenField.getObject(node);
+                    if (idx < nodeCount + nodeArray.length) {
+                        return (Node) nodeArray[idx - nodeCount];
+                    }
+                    nodeCount += nodeArray.length;
+                }
+            }
+            return null;
+        }
+
+        private void forward() {
+            if (index < childrenCount) {
+                index++;
+            }
+        }
+
+        public boolean hasNext() {
+            return index < childrenCount;
+        }
+
+        public Node next() {
+            try {
+                return nodeAt(index);
+            } finally {
+                forward();
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCloneable.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * Declarative base class for node fields that are to be cloned together with the containing node.
+ */
+public abstract class NodeCloneable implements Cloneable {
+    @Override
+    protected Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeCost.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Represents a rough estimate for the cost of a {@link Node}. This estimate can be used by runtime
+ * systems or guest languages to implement heuristics based on Truffle ASTs.
+ *
+ * @see Node#getCost()
+ */
+public enum NodeCost {
+
+    /**
+     * This node has literally no costs and should be ignored for heuristics. This is particularly
+     * useful for wrapper and profiling nodes which should not influence the heuristics.
+     */
+    NONE,
+
+    /**
+     * This node has a {@link CompilerDirectives#transferToInterpreter()} or
+     * {@link CompilerDirectives#transferToInterpreterAndInvalidate()} as its first unconditional
+     * statement.
+     */
+    UNINITIALIZED,
+
+    /**
+     * This node represents a specialized monomorphic version of an operation.
+     */
+    MONOMORPHIC,
+
+    /**
+     * This node represents a polymorphic version of an operation. For multiple chained polymorphic
+     * nodes the first may return {@link #MONOMORPHIC} and all additional nodes should return
+     * {@link #POLYMORPHIC}.
+     */
+    POLYMORPHIC,
+
+    /**
+     * This node represents a megamorphic version of an operation. This value should only be used if
+     * the operation implementation supports monomorphism and polymorphism otherwise
+     * {@link #MONOMORPHIC} should be used instead.
+     */
+    MEGAMORPHIC;
+
+    public boolean isTrivial() {
+        return this == NONE || this == UNINITIALIZED;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
+
+/**
+ * Information about a field in a {@link Node} class.
+ */
+public abstract class NodeFieldAccessor {
+
+    public static enum NodeFieldKind {
+        /** The reference to the {@link NodeClass}. */
+        NODE_CLASS,
+        /** The single {@link Node#getParent() parent} field. */
+        PARENT,
+        /** A field annotated with {@link Child}. */
+        CHILD,
+        /** A field annotated with {@link Children}. */
+        CHILDREN,
+        /** A normal non-child data field of the node. */
+        DATA
+    }
+
+    private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe");
+
+    private final NodeFieldKind kind;
+    private final String name;
+    protected final Class<?> type;
+    protected final long offset;
+
+    protected NodeFieldAccessor(NodeFieldKind kind, Field field) {
+        this.kind = kind;
+        this.type = field.getType();
+        this.name = field.getName();
+        this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field);
+    }
+
+    protected static NodeFieldAccessor create(NodeFieldKind kind, Field field) {
+        if (USE_UNSAFE) {
+            return new UnsafeNodeField(kind, field);
+        } else {
+            return new ReflectionNodeField(kind, field);
+        }
+    }
+
+    public NodeFieldKind getKind() {
+        return kind;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public long getOffset() {
+        return offset;
+    }
+
+    public abstract void putObject(Node receiver, Object value);
+
+    public abstract Object getObject(Node receiver);
+
+    public abstract Object loadValue(Node node);
+
+    @Override
+    public int hashCode() {
+        return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NodeFieldAccessor) {
+            NodeFieldAccessor other = (NodeFieldAccessor) obj;
+            return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
+        }
+        return false;
+    }
+
+    private static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    private static final FieldOffsetProvider unsafeFieldOffsetProvider = new FieldOffsetProvider() {
+
+        @Override
+        public long objectFieldOffset(Field field) {
+            return unsafe.objectFieldOffset(field);
+        }
+
+        @Override
+        public int getTypeSize(Class<?> clazz) {
+            if (!clazz.isPrimitive()) {
+                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+            } else if (clazz == int.class) {
+                return Unsafe.ARRAY_INT_INDEX_SCALE;
+            } else {
+                throw new UnsupportedOperationException("unsupported field type: " + clazz);
+            }
+        }
+    };
+
+    private static final class UnsafeNodeField extends NodeFieldAccessor {
+
+        protected UnsafeNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+        }
+
+        @Override
+        public void putObject(Node receiver, Object value) {
+            if (!type.isPrimitive() && value == null || type.isInstance(value)) {
+                unsafe.putObject(receiver, offset, value);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public Object getObject(Node receiver) {
+            if (!type.isPrimitive()) {
+                return unsafe.getObject(receiver, offset);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public Object loadValue(Node node) {
+            if (type == boolean.class) {
+                return unsafe.getBoolean(node, offset);
+            } else if (type == byte.class) {
+                return unsafe.getByte(node, offset);
+            } else if (type == short.class) {
+                return unsafe.getShort(node, offset);
+            } else if (type == char.class) {
+                return unsafe.getChar(node, offset);
+            } else if (type == int.class) {
+                return unsafe.getInt(node, offset);
+            } else if (type == long.class) {
+                return unsafe.getLong(node, offset);
+            } else if (type == float.class) {
+                return unsafe.getFloat(node, offset);
+            } else if (type == double.class) {
+                return unsafe.getDouble(node, offset);
+            } else {
+                return unsafe.getObject(node, offset);
+            }
+        }
+    }
+
+    private static final class ReflectionNodeField extends NodeFieldAccessor {
+        private final Field field;
+
+        protected ReflectionNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+            this.field = field;
+            field.setAccessible(true);
+        }
+
+        @Override
+        public void putObject(Node receiver, Object value) {
+            assert !type.isPrimitive() && value == null || type.isInstance(value);
+            try {
+                field.set(receiver, value);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        @Override
+        public Object getObject(Node receiver) {
+            assert !type.isPrimitive();
+            try {
+                return field.get(receiver);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        @Override
+        public Object loadValue(Node node) {
+            try {
+                if (type == boolean.class) {
+                    return field.getBoolean(node);
+                } else if (type == byte.class) {
+                    return field.getByte(node);
+                } else if (type == short.class) {
+                    return field.getShort(node);
+                } else if (type == char.class) {
+                    return field.getChar(node);
+                } else if (type == int.class) {
+                    return field.getInt(node);
+                } else if (type == long.class) {
+                    return field.getLong(node);
+                } else if (type == float.class) {
+                    return field.getFloat(node);
+                } else if (type == double.class) {
+                    return field.getDouble(node);
+                } else {
+                    return field.get(node);
+                }
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInfo.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation for providing additional information on nodes.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface NodeInfo {
+
+    /**
+     * Short name representing the node that can be used for debugging.
+     *
+     * @return the short name
+     */
+    String shortName() default "";
+
+    /**
+     * Provides a rough estimate for the cost of the annotated {@link Node}. This estimate can be
+     * used by runtime systems or guest languages to implement heuristics based on Truffle ASTs.
+     *
+     * @see Node#getCost()
+     * @see NodeCost
+     */
+    NodeCost cost() default NodeCost.MONOMORPHIC;
+
+    /**
+     * A human readable explanation of the purpose of the annotated {@link Node}. Can be used e.g.
+     * for debugging or visualization purposes.
+     *
+     * @return the description
+     */
+    String description() default "";
+
+    /**
+     * A description, providing a user-readable explanation of the source language of the annotated
+     * {@link Node}. Can be used e.g. for debugging or visualization purposes. Typically this
+     * information is set only in an abstract base node for the language implementation.
+     *
+     * @return the description
+     */
+    String language() default "";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeInterface.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * Common base interface for all Truffle nodes.
+ *
+ * @see Node
+ */
+public interface NodeInterface {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Utility class that manages the special access methods for node instances.
+ */
+public final class NodeUtil {
+
+    /**
+     * Interface that allows the customization of field offsets used for {@link Unsafe} field
+     * accesses.
+     */
+    public interface FieldOffsetProvider {
+
+        long objectFieldOffset(Field field);
+
+        int getTypeSize(Class<?> clazz);
+    }
+
+    static Iterator<Node> makeIterator(Node node) {
+        return node.getNodeClass().makeIterator(node);
+    }
+
+    public static Iterator<Node> makeRecursiveIterator(Node node) {
+        return new RecursiveNodeIterator(node);
+    }
+
+    private static final class RecursiveNodeIterator implements Iterator<Node> {
+        private final List<Iterator<Node>> iteratorStack = new ArrayList<>();
+
+        public RecursiveNodeIterator(final Node node) {
+            iteratorStack.add(new Iterator<Node>() {
+
+                private boolean visited;
+
+                public void remove() {
+                    throw new UnsupportedOperationException();
+                }
+
+                public Node next() {
+                    if (visited) {
+                        throw new NoSuchElementException();
+                    }
+                    visited = true;
+                    return node;
+                }
+
+                public boolean hasNext() {
+                    return !visited;
+                }
+            });
+        }
+
+        public boolean hasNext() {
+            return peekIterator() != null;
+        }
+
+        public Node next() {
+            Iterator<Node> iterator = peekIterator();
+            if (iterator == null) {
+                throw new NoSuchElementException();
+            }
+
+            Node node = iterator.next();
+            if (node != null) {
+                Iterator<Node> childIterator = makeIterator(node);
+                if (childIterator.hasNext()) {
+                    iteratorStack.add(childIterator);
+                }
+            }
+            return node;
+        }
+
+        private Iterator<Node> peekIterator() {
+            int tos = iteratorStack.size() - 1;
+            while (tos >= 0) {
+                Iterator<Node> iterable = iteratorStack.get(tos);
+                if (iterable.hasNext()) {
+                    return iterable;
+                } else {
+                    iteratorStack.remove(tos--);
+                }
+            }
+            return null;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T cloneNode(T orig) {
+        return (T) orig.deepCopy();
+    }
+
+    static Node deepCopyImpl(Node orig) {
+        final Node clone = orig.copy();
+        NodeClass nodeClass = clone.getNodeClass();
+
+        nodeClass.getParentField().putObject(clone, null);
+
+        for (NodeFieldAccessor childField : nodeClass.getChildFields()) {
+            Node child = (Node) childField.getObject(orig);
+            if (child != null) {
+                Node clonedChild = child.deepCopy();
+                nodeClass.getParentField().putObject(clonedChild, clone);
+                childField.putObject(clone, clonedChild);
+            }
+        }
+        for (NodeFieldAccessor childrenField : nodeClass.getChildrenFields()) {
+            Object[] children = (Object[]) childrenField.getObject(orig);
+            if (children != null) {
+                Object[] clonedChildren = (Object[]) Array.newInstance(children.getClass().getComponentType(), children.length);
+                for (int i = 0; i < children.length; i++) {
+                    if (children[i] != null) {
+                        Node clonedChild = ((Node) children[i]).deepCopy();
+                        clonedChildren[i] = clonedChild;
+                        nodeClass.getParentField().putObject(clonedChild, clone);
+                    }
+                }
+                childrenField.putObject(clone, clonedChildren);
+            }
+        }
+        for (NodeFieldAccessor cloneableField : nodeClass.getCloneableFields()) {
+            Object cloneable = cloneableField.getObject(clone);
+            if (cloneable != null && cloneable == cloneableField.getObject(orig)) {
+                cloneableField.putObject(clone, ((NodeCloneable) cloneable).clone());
+            }
+        }
+        return clone;
+    }
+
+    public static List<Node> findNodeChildren(Node node) {
+        List<Node> nodes = new ArrayList<>();
+        NodeClass nodeClass = node.getNodeClass();
+
+        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
+            Object child = nodeField.getObject(node);
+            if (child != null) {
+                nodes.add((Node) child);
+            }
+        }
+        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
+            Object[] children = (Object[]) nodeField.getObject(node);
+            if (children != null) {
+                for (Object child : children) {
+                    if (child != null) {
+                        nodes.add((Node) child);
+                    }
+                }
+            }
+        }
+
+        return nodes;
+    }
+
+    public static <T extends Node> T nonAtomicReplace(Node oldNode, T newNode, CharSequence reason) {
+        oldNode.replaceHelper(newNode, reason);
+        return newNode;
+    }
+
+    public static boolean replaceChild(Node parent, Node oldChild, Node newChild) {
+        NodeClass nodeClass = parent.getNodeClass();
+
+        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
+            if (nodeField.getObject(parent) == oldChild) {
+                assert assertAssignable(nodeField, newChild);
+                nodeField.putObject(parent, newChild);
+                return true;
+            }
+        }
+
+        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
+            Object arrayObject = nodeField.getObject(parent);
+            if (arrayObject != null) {
+                Object[] array = (Object[]) arrayObject;
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i] == oldChild) {
+                        assert assertAssignable(nodeField, newChild);
+                        array[i] = newChild;
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean assertAssignable(NodeFieldAccessor field, Object newValue) {
+        if (newValue == null) {
+            return true;
+        }
+        if (field.getKind() == NodeFieldKind.CHILD) {
+            if (field.getType().isAssignableFrom(newValue.getClass())) {
+                return true;
+            } else {
+                assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                return false;
+            }
+        } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+            if (field.getType().getComponentType().isAssignableFrom(newValue.getClass())) {
+                return true;
+            } else {
+                assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
+                return false;
+            }
+        }
+        throw new IllegalArgumentException();
+    }
+
+    /**
+     * Finds the field in a parent node, if any, that holds a specified child node.
+     *
+     * @return the field (possibly an array) holding the child, {@code null} if not found.
+     */
+    public static NodeFieldAccessor findChildField(Node parent, Node child) {
+        assert child != null;
+        NodeClass parentNodeClass = parent.getNodeClass();
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
+            if (field.getObject(parent) == child) {
+                return field;
+            }
+        }
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
+            Object arrayObject = field.getObject(parent);
+            if (arrayObject != null) {
+                Object[] array = (Object[]) arrayObject;
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i] == child) {
+                        return field;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Determines whether a proposed child replacement would be safe: structurally and type.
+     */
+    public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) {
+        assert newChild != null;
+        if (parent != null) {
+            final NodeFieldAccessor field = findChildField(parent, oldChild);
+            if (field != null) {
+                switch (field.getKind()) {
+                    case CHILD:
+                        return field.getType().isAssignableFrom(newChild.getClass());
+                    case CHILDREN:
+                        return field.getType().getComponentType().isAssignableFrom(newChild.getClass());
+                    default:
+                        throw new IllegalStateException();
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Executes a closure for every non-null child of the parent node.
+     *
+     * @return {@code true} if all children were visited, {@code false} otherwise
+     */
+    public static boolean forEachChild(Node parent, NodeVisitor visitor) {
+        Objects.requireNonNull(visitor);
+        NodeClass parentNodeClass = parent.getNodeClass();
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
+            Object child = field.getObject(parent);
+            if (child != null) {
+                if (!visitor.visit((Node) child)) {
+                    return false;
+                }
+            }
+        }
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
+            Object arrayObject = field.getObject(parent);
+            if (arrayObject != null) {
+                Object[] array = (Object[]) arrayObject;
+                for (int i = 0; i < array.length; i++) {
+                    Object child = array[i];
+                    if (child != null) {
+                        if (!visitor.visit((Node) child)) {
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    static boolean forEachChildRecursive(Node parent, NodeVisitor visitor) {
+        NodeClass parentNodeClass = parent.getNodeClass();
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
+            if (!visitChild((Node) field.getObject(parent), visitor)) {
+                return false;
+            }
+        }
+
+        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
+            Object arrayObject = field.getObject(parent);
+            if (arrayObject == null) {
+                continue;
+            }
+            Object[] array = (Object[]) arrayObject;
+            for (int i = 0; i < array.length; i++) {
+                if (!visitChild((Node) array[i], visitor)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private static boolean visitChild(Node child, NodeVisitor visitor) {
+        if (child == null) {
+            return true;
+        }
+        if (!visitor.visit(child)) {
+            return false;
+        }
+        if (!forEachChildRecursive(child, visitor)) {
+            return false;
+        }
+        return true;
+    }
+
+    /** Returns all declared fields in the class hierarchy. */
+    static Field[] getAllFields(Class<? extends Object> clazz) {
+        Field[] declaredFields = clazz.getDeclaredFields();
+        if (clazz.getSuperclass() != null) {
+            return concat(getAllFields(clazz.getSuperclass()), declaredFields);
+        }
+        return declaredFields;
+    }
+
+    public static <T> T[] concat(T[] first, T[] second) {
+        T[] result = Arrays.copyOf(first, first.length + second.length);
+        System.arraycopy(second, 0, result, first.length, second.length);
+        return result;
+    }
+
+    /**
+     * Get the nth parent of a node, where the 0th parent is the node itself. Returns null if there
+     * are less than n ancestors.
+     */
+    public static Node getNthParent(Node node, int n) {
+        Node parent = node;
+
+        for (int i = 0; i < n; i++) {
+            parent = parent.getParent();
+
+            if (parent == null) {
+                return null;
+            }
+        }
+
+        return parent;
+    }
+
+    /** find annotation in class/interface hierarchy. */
+    public static <T extends Annotation> T findAnnotation(Class<?> clazz, Class<T> annotationClass) {
+        if (clazz.getAnnotation(annotationClass) != null) {
+            return clazz.getAnnotation(annotationClass);
+        } else {
+            for (Class<?> intf : clazz.getInterfaces()) {
+                if (intf.getAnnotation(annotationClass) != null) {
+                    return intf.getAnnotation(annotationClass);
+                }
+            }
+            if (clazz.getSuperclass() != null) {
+                return findAnnotation(clazz.getSuperclass(), annotationClass);
+            }
+        }
+        return null;
+    }
+
+    public static <T> T findParent(Node start, Class<T> clazz) {
+        Node parent = start.getParent();
+        if (parent == null) {
+            return null;
+        } else if (clazz.isInstance(parent)) {
+            return clazz.cast(parent);
+        } else {
+            return findParent(parent, clazz);
+        }
+    }
+
+    public static <T> List<T> findAllParents(Node start, Class<T> clazz) {
+        List<T> parents = new ArrayList<>();
+        T parent = findParent(start, clazz);
+        while (parent != null) {
+            parents.add(parent);
+            parent = findParent((Node) parent, clazz);
+        }
+        return parents;
+    }
+
+    public static List<Node> collectNodes(Node parent, Node child) {
+        List<Node> nodes = new ArrayList<>();
+        Node current = child;
+        while (current != null) {
+            nodes.add(current);
+            if (current == parent) {
+                return nodes;
+            }
+            current = current.getParent();
+        }
+        throw new IllegalArgumentException("Node " + parent + " is not a parent of " + child + ".");
+    }
+
+    public static <T> T findFirstNodeInstance(Node root, Class<T> clazz) {
+        if (clazz.isInstance(root)) {
+            return clazz.cast(root);
+        }
+        for (Node child : root.getChildren()) {
+            T node = findFirstNodeInstance(child, clazz);
+            if (node != null) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    public static <T> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
+        final List<T> nodeList = new ArrayList<>();
+        root.accept(new NodeVisitor() {
+            public boolean visit(Node node) {
+                if (clazz.isInstance(node)) {
+                    nodeList.add(clazz.cast(node));
+                }
+                return true;
+            }
+        });
+        return nodeList;
+    }
+
+    public static int countNodes(Node root) {
+        return countNodes(root, NodeCountFilter.NO_FILTER);
+    }
+
+    public static int countNodes(Node root, NodeCountFilter filter) {
+        NodeCounter counter = new NodeCounter(filter);
+        root.accept(counter);
+        return counter.count;
+    }
+
+    public interface NodeCountFilter {
+
+        NodeCountFilter NO_FILTER = new NodeCountFilter() {
+
+            public boolean isCounted(Node node) {
+                return true;
+            }
+        };
+
+        boolean isCounted(Node node);
+
+    }
+
+    public static String printCompactTreeToString(Node node) {
+        StringWriter out = new StringWriter();
+        printCompactTree(new PrintWriter(out), null, node, 1);
+        return out.toString();
+    }
+
+    public static void printCompactTree(OutputStream out, Node node) {
+        printCompactTree(new PrintWriter(out), null, node, 1);
+    }
+
+    private static void printCompactTree(PrintWriter p, Node parent, Node node, int level) {
+        if (node == null) {
+            return;
+        }
+        for (int i = 0; i < level; i++) {
+            p.print("  ");
+        }
+        if (parent == null) {
+            p.println(nodeName(node));
+        } else {
+            p.print(getNodeFieldName(parent, node, "unknownField"));
+            p.print(" = ");
+            p.println(nodeName(node));
+        }
+
+        for (Node child : node.getChildren()) {
+            printCompactTree(p, node, child, level + 1);
+        }
+        p.flush();
+    }
+
+    public static String printSourceAttributionTree(Node node) {
+        StringWriter out = new StringWriter();
+        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
+        return out.toString();
+    }
+
+    public static void printSourceAttributionTree(OutputStream out, Node node) {
+        printSourceAttributionTree(new PrintWriter(out), null, node, 1);
+    }
+
+    public static void printSourceAttributionTree(PrintWriter out, Node node) {
+        printSourceAttributionTree(out, null, node, 1);
+    }
+
+    private static void printSourceAttributionTree(PrintWriter p, Node parent, Node node, int level) {
+        if (node == null) {
+            return;
+        }
+        if (parent == null) {
+            // Add some preliminary information before starting with the root node
+            final SourceSection sourceSection = node.getSourceSection();
+            if (sourceSection != null) {
+                final String txt = sourceSection.getSource().getCode();
+                p.println("Full source len=(" + txt.length() + ")  ___" + txt + "___");
+                p.println("AST source attribution:");
+            }
+        }
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < level; i++) {
+            sb.append("| ");
+        }
+
+        if (parent != null) {
+            sb.append(getNodeFieldName(parent, node, ""));
+        }
+
+        sb.append("  (" + node.getClass().getSimpleName() + ")  ");
+
+        sb.append(printSyntaxTags(node));
+
+        sb.append(displaySourceAttribution(node));
+        p.println(sb.toString());
+
+        for (Node child : node.getChildren()) {
+            printSourceAttributionTree(p, node, child, level + 1);
+        }
+        p.flush();
+    }
+
+    private static String getNodeFieldName(Node parent, Node node, String defaultName) {
+        NodeFieldAccessor[] fields = parent.getNodeClass().getFields();
+        for (NodeFieldAccessor field : fields) {
+            Object value = field.loadValue(parent);
+            if (field.getKind() == NodeFieldKind.CHILD && value == node) {
+                return field.getName();
+            } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                int index = 0;
+                for (Object arrayNode : (Object[]) value) {
+                    if (arrayNode == node) {
+                        return field.getName() + "[" + index + "]";
+                    }
+                    index++;
+                }
+            }
+        }
+        return defaultName;
+    }
+
+    /**
+     * Returns a string listing the {@linkplain SyntaxTag syntax tags}, if any, associated with a
+     * node:
+     * <ul>
+     * <li>"[{@linkplain StandardSyntaxTag#STATEMENT STATEMENT},
+     * {@linkplain StandardSyntaxTag#ASSIGNMENT ASSIGNMENT}]" if tags have been applied;</li>
+     * <li>"[]" if the node supports tags, but none are present; and</li>
+     * <li>"" if the node does not support tags.</li>
+     * </ul>
+     */
+    public static String printSyntaxTags(final Object node) {
+        if (node instanceof WrapperNode) {
+            final Probe probe = ((WrapperNode) node).getProbe();
+            final Collection<SyntaxTag> syntaxTags = probe.getSyntaxTags();
+            final StringBuilder sb = new StringBuilder();
+            String prefix = "";
+            sb.append("[");
+            for (SyntaxTag tag : syntaxTags) {
+                sb.append(prefix);
+                prefix = ",";
+                sb.append(tag.toString());
+            }
+            sb.append("]");
+            return sb.toString();
+        }
+        return "";
+    }
+
+    /**
+     * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This
+     * print method does not check for cycles in the node structure.
+     *
+     * @param out the stream to print to.
+     * @param node the root node to write
+     */
+    public static void printTree(OutputStream out, Node node) {
+        printTree(new PrintWriter(out), node);
+    }
+
+    public static String printTreeToString(Node node) {
+        StringWriter out = new StringWriter();
+        printTree(new PrintWriter(out), node);
+        return out.toString();
+    }
+
+    public static void printTree(PrintWriter p, Node node) {
+        printTree(p, node, 1);
+        p.println();
+        p.flush();
+    }
+
+    private static void printTree(PrintWriter p, Node node, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(nodeName(node));
+
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
+        String sep = "";
+        p.print("(");
+        for (NodeFieldAccessor field : NodeClass.get(node).getFields()) {
+            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
+                childFields.add(field);
+            } else if (field.getKind() == NodeFieldKind.DATA) {
+                p.print(sep);
+                sep = ", ";
+
+                p.print(field.getName());
+                p.print(" = ");
+                p.print(field.loadValue(node));
+            }
+        }
+        p.print(")");
+
+        if (childFields.size() != 0) {
+            p.print(" {");
+            for (NodeFieldAccessor field : childFields) {
+                printNewLine(p, level);
+                p.print(field.getName());
+
+                Object value = field.loadValue(node);
+                if (value == null) {
+                    p.print(" = null ");
+                } else if (field.getKind() == NodeFieldKind.CHILD) {
+                    p.print(" = ");
+                    printTree(p, (Node) value, level + 1);
+                } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                    printChildren(p, level, value);
+                }
+            }
+            printNewLine(p, level - 1);
+            p.print("}");
+        }
+    }
+
+    private static void printChildren(PrintWriter p, int level, Object value) {
+        String sep;
+        Object[] children = (Object[]) value;
+        p.print(" = [");
+        sep = "";
+        for (Object child : children) {
+            p.print(sep);
+            sep = ", ";
+            printTree(p, (Node) child, level + 1);
+        }
+        p.print("]");
+    }
+
+    private static void printNewLine(PrintWriter p, int level) {
+        p.println();
+        for (int i = 0; i < level; i++) {
+            p.print("    ");
+        }
+    }
+
+    private static String nodeName(Node node) {
+        return node.getClass().getSimpleName();
+    }
+
+    private static String displaySourceAttribution(Node node) {
+        final SourceSection section = node.getSourceSection();
+        if (section instanceof NullSourceSection) {
+            return "source: " + section.getShortDescription();
+        }
+        if (section != null) {
+            final String srcText = section.getCode();
+            final StringBuilder sb = new StringBuilder();
+            sb.append("source:");
+            sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")");
+            sb.append(" line=" + section.getLineLocation().getLineNumber());
+            sb.append(" len=" + srcText.length());
+            sb.append(" text=\"" + srcText + "\"");
+            return sb.toString();
+        }
+        return "";
+    }
+
+    public static boolean verify(Node root) {
+        Iterable<Node> children = root.getChildren();
+        for (Node child : children) {
+            if (child != null) {
+                if (child.getParent() != root) {
+                    throw new AssertionError(toStringWithClass(child) + ": actual parent=" + toStringWithClass(child.getParent()) + " expected parent=" + toStringWithClass(root));
+                }
+                verify(child);
+            }
+        }
+        return true;
+    }
+
+    private static String toStringWithClass(Object obj) {
+        return obj == null ? "null" : obj + "(" + obj.getClass().getName() + ")";
+    }
+
+    static void traceRewrite(Node oldNode, Node newNode, CharSequence reason) {
+        if (TruffleOptions.TraceRewritesFilterFromCost != null) {
+            if (filterByKind(oldNode, TruffleOptions.TraceRewritesFilterFromCost)) {
+                return;
+            }
+        }
+
+        if (TruffleOptions.TraceRewritesFilterToCost != null) {
+            if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
+                return;
+            }
+        }
+
+        String filter = TruffleOptions.TraceRewritesFilterClass;
+        Class<? extends Node> from = oldNode.getClass();
+        Class<? extends Node> to = newNode.getClass();
+        if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
+            return;
+        }
+
+        final SourceSection reportedSourceSection = oldNode.getEncapsulatingSourceSection();
+
+        PrintStream out = System.out;
+        out.printf("[truffle]   rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", oldNode.toString(), formatNodeInfo(oldNode), formatNodeInfo(newNode),
+                        reason != null && reason.length() > 0 ? reason : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
+    }
+
+    private static String formatNodeInfo(Node node) {
+        String cost = "?";
+        switch (node.getCost()) {
+            case NONE:
+                cost = "G";
+                break;
+            case MONOMORPHIC:
+                cost = "M";
+                break;
+            case POLYMORPHIC:
+                cost = "P";
+                break;
+            case MEGAMORPHIC:
+                cost = "G";
+                break;
+            default:
+                cost = "?";
+                break;
+        }
+        return cost + " " + node.getClass().getSimpleName();
+    }
+
+    private static boolean filterByKind(Node node, NodeCost cost) {
+        return node.getCost() == cost;
+    }
+
+    private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
+        Class<?> currentFrom = from;
+        while (currentFrom != null) {
+            if (currentFrom.getName().contains(filter)) {
+                return false;
+            }
+            currentFrom = currentFrom.getSuperclass();
+        }
+        return true;
+    }
+
+    private static final class NodeCounter implements NodeVisitor {
+
+        public int count;
+        private final NodeCountFilter filter;
+
+        public NodeCounter(NodeCountFilter filter) {
+            this.filter = filter;
+        }
+
+        public boolean visit(Node node) {
+            if (filter.isCounted(node)) {
+                count++;
+            }
+            return true;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+/**
+ * Visitor for trees of nodes.
+ */
+public interface NodeVisitor {
+
+    /**
+     * This visitor method is called for every node in the tree. Its return value determines if the
+     * children of this node should be excluded in the iteration.
+     *
+     * @param node the node that is currently visited
+     * @return {@code true} if the children should be visited too, {@code false} otherwise
+     */
+    boolean visit(Node node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RepeatingNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.frame.*;
+
+/**
+ * Experimental API: may change significantly without notice.
+ */
+public interface RepeatingNode extends NodeInterface {
+
+    boolean executeRepeating(VirtualFrame frame);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/RootNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A root node is a node with a method to execute it given only a frame as a parameter. Therefore, a
+ * root node can be used to create a call target using
+ * {@link TruffleRuntime#createCallTarget(RootNode)}.
+ */
+public abstract class RootNode extends Node {
+
+    private RootCallTarget callTarget;
+    @CompilationFinal private FrameDescriptor frameDescriptor;
+
+    protected RootNode() {
+        this(null, null);
+    }
+
+    protected RootNode(SourceSection sourceSection) {
+        this(sourceSection, null);
+    }
+
+    protected RootNode(SourceSection sourceSection, FrameDescriptor frameDescriptor) {
+        super(sourceSection);
+        if (frameDescriptor == null) {
+            this.frameDescriptor = new FrameDescriptor();
+        } else {
+            this.frameDescriptor = frameDescriptor;
+        }
+    }
+
+    @Override
+    public Node copy() {
+        RootNode root = (RootNode) super.copy();
+        root.frameDescriptor = frameDescriptor;
+        return root;
+    }
+
+    /**
+     * Returns <code>true</code> if this {@link RootNode} is allowed to be cloned. The runtime
+     * system might decide to create deep copies of the {@link RootNode} in order to gather context
+     * sensitive profiling feedback. The default implementation returns <code>false</code>. Guest
+     * language specific implementations may want to return <code>true</code> here to indicate that
+     * gathering call site specific profiling information might make sense for this {@link RootNode}
+     * .
+     *
+     * @return <code>true</code> if cloning is allowed else <code>false</code>.
+     */
+    public boolean isCloningAllowed() {
+        return false;
+    }
+
+    /**
+     * Reports the execution count of a loop that is a child of this node. The optimization
+     * heuristics can use the loop count to guide compilation and inlining.
+     */
+    public final void reportLoopCount(int count) {
+        if (getCallTarget() instanceof LoopCountReceiver) {
+            ((LoopCountReceiver) getCallTarget()).reportLoopCount(count);
+        }
+    }
+
+    /**
+     * Executes this function using the specified frame and returns the result value.
+     *
+     * @param frame the frame of the currently executing guest language method
+     * @return the value of the execution
+     */
+    public abstract Object execute(VirtualFrame frame);
+
+    public final RootCallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    public final FrameDescriptor getFrameDescriptor() {
+        return frameDescriptor;
+    }
+
+    public final void setCallTarget(RootCallTarget callTarget) {
+        this.callTarget = callTarget;
+    }
+
+    /**
+     * Returns the {@link ExecutionContext} associated with this <code>RootNode</code>. This allows
+     * the correct <code>ExecutionContext</code> to be determined for a <code>RootNode</code> (and
+     * so also for a {@link RootCallTarget} and a {@link FrameInstance} obtained from the call
+     * stack) without prior knowledge of the language it has come from.
+     *
+     * Used for instance to determine the language of a <code>RootNode<code>:
+     *
+     * <pre>
+     * <code>
+     * rootNode.getExecutionContext().getLanguageShortName();
+     * </code> </pre>
+     *
+     * Returns <code>null</code> by default.
+     */
+    public ExecutionContext getExecutionContext() {
+        return null;
+    }
+
+    /**
+     * Get compiler options specific to this <code>RootNode</code>.
+     */
+    public CompilerOptions getCompilerOptions() {
+        final ExecutionContext context = getExecutionContext();
+
+        if (context == null) {
+            return DefaultCompilerOptions.INSTANCE;
+        } else {
+            return context.getCompilerOptions();
+        }
+    }
+
+    /**
+     * Apply all registered instances of {@link ASTProber} to the AST, if any, held by this root
+     * node. This can only be done once the AST is complete, notably once all parent pointers are
+     * correctly assigned. But it also must be done before any AST cloning or execution.
+     * <p>
+     * If this is not done, then the AST will not be subject to debugging or any other
+     * instrumentation-supported tooling.
+     * <p>
+     * Implementations should ensure that instrumentation is never applied more than once to an AST,
+     * as this is not guaranteed to be error-free.
+     *
+     * @see Probe#registerASTProber(com.oracle.truffle.api.instrument.ASTProber)
+     */
+    public void applyInstrumentation() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/SlowPathException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * An exception thrown to enter a slow path. The Truffle optimizer has special knowledge of this
+ * exception class and will never compile a catch block that catches this exception type.
+ */
+public class SlowPathException extends Exception {
+
+    private static final long serialVersionUID = 3676602078425211386L;
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException() {
+        CompilerDirectives.transferToInterpreter();
+    }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(String message, Throwable cause) {
+        super(message, cause);
+        CompilerDirectives.transferToInterpreter();
+    }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(String message) {
+        super(message);
+        CompilerDirectives.transferToInterpreter();
+    }
+
+    /**
+     * Creates an exception thrown to enter a slow path.
+     */
+    public SlowPathException(Throwable cause) {
+        super(cause);
+        CompilerDirectives.transferToInterpreter();
+    }
+
+    /**
+     * For performance reasons, this exception does not record any stack trace information.
+     */
+    @SuppressWarnings("sync-override")
+    @Override
+    public Throwable fillInStackTrace() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * An exception that should be thrown if the return value cannot be represented as a value of the
+ * return type. The Truffle optimizer has special knowledge of this exception class and will never
+ * compile a catch block that catches this exception type.
+ */
+public final class UnexpectedResultException extends SlowPathException {
+
+    private static final long serialVersionUID = 3676602078425211386L;
+    private final Object result;
+
+    /**
+     * Creates the exception with the alternative result that cannot be represented as a value of
+     * the return type.
+     *
+     * @param result the alternative result
+     */
+    public UnexpectedResultException(Object result) {
+        CompilerDirectives.transferToInterpreter();
+        this.result = result;
+    }
+
+    /**
+     * @return the unexpected result
+     */
+    public Object getResult() {
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes.serial;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Experimental API. May change without notice.
+ */
+public final class PostOrderDeserializer {
+
+    private static final Unsafe unsafe = loadUnsafe();
+
+    private final SerializerConstantPool cp;
+
+    private final HierarchicalStack stack = new HierarchicalStack();
+
+    /**
+     * Constructs a new serializer using a custom {@link SerializerConstantPool} implementation. For
+     * the {@link SerializerConstantPool} implementation at least the following methods must be
+     * implemented:
+     * <ul>
+     * <li>{@link SerializerConstantPool#getInt(int)}</li>
+     * <li>{@link SerializerConstantPool#getClass(int)}</li>
+     * </ul>
+     */
+    public PostOrderDeserializer(SerializerConstantPool cp) {
+        this.cp = cp;
+    }
+
+    /**
+     * Deserializes the byte stream and returns the deserialized Truffle AST node.
+     *
+     * @param bytes the trimmed byte array containing the serialized data
+     * @param expectedType the expected root node type. Throws an exception if the root node is not
+     *            assignable from this type.
+     * @return the deserialized Truffle AST represented by the root Node.
+     *
+     * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not
+     *             supported by the constant pool implementation.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Node> T deserialize(byte[] bytes, Class<T> expectedType) throws UnsupportedConstantPoolTypeException {
+        VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(bytes);
+
+        while (buffer.hasRemaining()) {
+            int classCPI = buffer.get();
+            if (classCPI == VariableLengthIntBuffer.NULL) {
+                pushNode(null);
+            } else {
+                Class<?> clazz = cp.getClass(classCPI);
+                if (clazz.isArray()) {
+                    int lengthCPI = buffer.get();
+                    if (lengthCPI == VariableLengthIntBuffer.NULL) {
+                        pushArray(null);
+                    } else {
+                        pushArray((Node[]) Array.newInstance(clazz.getComponentType(), cp.getInt(lengthCPI)));
+                    }
+                } else {
+                    pushNode(invokeDeserialize(buffer, clazz.asSubclass(Node.class)));
+                }
+            }
+        }
+        T returnNode = (T) popNode(null, expectedType);
+
+        assert stack.dynamicStack.isEmpty();
+
+        return returnNode;
+    }
+
+    private void pushNode(Node node) {
+        stack.push(node);
+    }
+
+    private void pushArray(Node[] array) {
+        stack.pushStack(array);
+    }
+
+    private Node[] popArray(Node parent, Class<?> expectedType) {
+        Node[] array = (Node[]) stack.popStack();
+        if (array != null) {
+            assertType(array, expectedType);
+            for (int i = 0; i < array.length; i++) {
+                updateParent(parent, array[i]);
+            }
+        }
+        return array;
+    }
+
+    private Node popNode(Node parent, Class<?> expectedType) {
+        Object o = stack.pop();
+        assertType(o, expectedType);
+        updateParent(parent, (Node) o);
+        return (Node) o;
+    }
+
+    private static void assertType(Object o, Class<?> expectedType) {
+        if (o != null && !expectedType.isAssignableFrom(o.getClass())) {
+            throw new AssertionError("Expected element type '" + expectedType.getName() + "' but was '" + o.getClass().getName() + "'.");
+        }
+    }
+
+    private Node invokeDeserialize(VariableLengthIntBuffer buffer, Class<? extends Node> nodeClass) throws UnsupportedConstantPoolTypeException {
+        if (nodeClass == null) {
+            return null;
+        }
+
+        Object object;
+        try {
+            object = unsafe.allocateInstance(nodeClass);
+        } catch (InstantiationException e) {
+            throw new RuntimeException("Unable to allocate truffle node " + nodeClass, e);
+        }
+        if (!(object instanceof Node)) {
+            throw new RuntimeException("Class is not a truffle node " + nodeClass);
+        }
+
+        Node node = (Node) object;
+
+        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
+        deserializeChildrenFields(node, nodeFields);
+        deserializeChildFields(node, nodeFields);
+        deserializeDataFields(buffer, node, nodeFields);
+
+        return node;
+    }
+
+    private void deserializeDataFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
+        for (int i = 0; i < nodeFields.length; i++) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.DATA) {
+                Class<?> fieldClass = field.getType();
+                long offset = field.getOffset();
+
+                // source sections are not serialized
+                // TODO add support for source sections
+                if (field.getType().isAssignableFrom(SourceSection.class)) {
+                    continue;
+                }
+
+                int cpi = buffer.get();
+                if (cpi == VariableLengthIntBuffer.NULL) {
+                    deserializeDataFieldsLengthNull(nodeInstance, fieldClass, offset);
+                } else {
+                    deserializeDataFieldsDefault(nodeInstance, fieldClass, offset, cpi);
+                }
+            }
+        }
+    }
+
+    private void deserializeDataFieldsDefault(Node nodeInstance, Class<?> fieldClass, long offset, int cpi) {
+        if (fieldClass == int.class) {
+            unsafe.putInt(nodeInstance, offset, cp.getInt(cpi));
+        } else if (fieldClass == long.class) {
+            unsafe.putLong(nodeInstance, offset, cp.getLong(cpi));
+        } else if (fieldClass == float.class) {
+            unsafe.putFloat(nodeInstance, offset, cp.getFloat(cpi));
+        } else if (fieldClass == double.class) {
+            unsafe.putDouble(nodeInstance, offset, cp.getDouble(cpi));
+        } else if (fieldClass == byte.class) {
+            unsafe.putByte(nodeInstance, offset, (byte) cp.getInt(cpi));
+        } else if (fieldClass == short.class) {
+            unsafe.putShort(nodeInstance, offset, (short) cp.getInt(cpi));
+        } else if (fieldClass == char.class) {
+            unsafe.putChar(nodeInstance, offset, (char) cp.getInt(cpi));
+        } else if (fieldClass == boolean.class) {
+            unsafe.putBoolean(nodeInstance, offset, cp.getInt(cpi) == 1 ? true : false);
+        } else if (fieldClass == Integer.class) {
+            unsafe.putObject(nodeInstance, offset, cp.getInt(cpi));
+        } else if (fieldClass == Long.class) {
+            unsafe.putObject(nodeInstance, offset, cp.getLong(cpi));
+        } else if (fieldClass == Float.class) {
+            unsafe.putObject(nodeInstance, offset, cp.getFloat(cpi));
+        } else if (fieldClass == Double.class) {
+            unsafe.putObject(nodeInstance, offset, cp.getDouble(cpi));
+        } else if (fieldClass == Byte.class) {
+            unsafe.putObject(nodeInstance, offset, (byte) cp.getInt(cpi));
+        } else if (fieldClass == Short.class) {
+            unsafe.putObject(nodeInstance, offset, (short) cp.getInt(cpi));
+        } else if (fieldClass == Character.class) {
+            unsafe.putObject(nodeInstance, offset, (char) cp.getInt(cpi));
+        } else if (fieldClass == Boolean.class) {
+            unsafe.putObject(nodeInstance, offset, cp.getInt(cpi) == 1 ? Boolean.TRUE : Boolean.FALSE);
+        } else {
+            unsafe.putObject(nodeInstance, offset, cp.getObject(fieldClass, cpi));
+        }
+    }
+
+    private static void deserializeDataFieldsLengthNull(Node nodeInstance, Class<?> fieldClass, long offset) {
+        if (fieldClass == int.class) {
+            unsafe.putInt(nodeInstance, offset, 0);
+        } else if (fieldClass == long.class) {
+            unsafe.putLong(nodeInstance, offset, 0L);
+        } else if (fieldClass == float.class) {
+            unsafe.putFloat(nodeInstance, offset, 0.0F);
+        } else if (fieldClass == double.class) {
+            unsafe.putDouble(nodeInstance, offset, 0.0D);
+        } else if (fieldClass == byte.class) {
+            unsafe.putByte(nodeInstance, offset, (byte) 0);
+        } else if (fieldClass == short.class) {
+            unsafe.putShort(nodeInstance, offset, (short) 0);
+        } else if (fieldClass == char.class) {
+            unsafe.putChar(nodeInstance, offset, (char) 0);
+        } else if (fieldClass == boolean.class) {
+            unsafe.putBoolean(nodeInstance, offset, false);
+        } else {
+            unsafe.putObject(nodeInstance, offset, null);
+        }
+    }
+
+    private void deserializeChildFields(Node parent, NodeFieldAccessor[] nodeFields) {
+        for (int i = nodeFields.length - 1; i >= 0; i--) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.CHILD) {
+                unsafe.putObject(parent, field.getOffset(), popNode(parent, field.getType()));
+            }
+        }
+    }
+
+    private void deserializeChildrenFields(Node parent, NodeFieldAccessor[] nodeFields) {
+        for (int i = nodeFields.length - 1; i >= 0; i--) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.CHILDREN) {
+                unsafe.putObject(parent, field.getOffset(), popArray(parent, field.getType()));
+            }
+        }
+    }
+
+    private static Node updateParent(Node parent, Node child) {
+        if (child != null) {
+            NodeClass nodeClass = NodeClass.get(child.getClass());
+            nodeClass.getNodeClassField().putObject(child, nodeClass);
+            nodeClass.getParentField().putObject(child, parent);
+        }
+        return child;
+    }
+
+    private static Unsafe loadUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    private static class HierarchicalStack {
+
+        private static final Object NULL_STACK = new Object();
+
+        private final List<Object> dynamicStack = new ArrayList<>();
+
+        void pushStack(Object[] array) {
+            if (array == null) {
+                dynamicStack.add(NULL_STACK);
+            } else {
+                dynamicStack.add(new FixedSizeNodeStack(array));
+            }
+        }
+
+        private FixedSizeNodeStack getTosStack() {
+            if (dynamicStack.isEmpty()) {
+                return null;
+            }
+            Object peekTos = dynamicStack.get(dynamicStack.size() - 1);
+            if (peekTos != null && peekTos.getClass() == FixedSizeNodeStack.class) {
+                return (FixedSizeNodeStack) peekTos;
+            }
+            return null;
+        }
+
+        Object[] popStack() {
+            Object tos = dynamicStack.remove(dynamicStack.size() - 1);
+            if (tos == NULL_STACK) {
+                return null;
+            }
+            return ((FixedSizeNodeStack) tos).getArray();
+        }
+
+        void push(Object o) {
+            FixedSizeNodeStack tosStack = getTosStack();
+            if (tosStack != null && !tosStack.isFull()) {
+                tosStack.push(o);
+            } else {
+                dynamicStack.add(o);
+            }
+        }
+
+        Object pop() {
+            FixedSizeNodeStack tosStack = getTosStack();
+            Object value;
+            if (tosStack != null) {
+                assert !tosStack.isEmpty();
+                value = tosStack.pop();
+            } else {
+                value = dynamicStack.remove(dynamicStack.size() - 1);
+            }
+            assert value != NULL_STACK;
+            return value;
+        }
+
+    }
+
+    private static class FixedSizeNodeStack {
+
+        private final Object[] array;
+
+        private int tos;
+
+        FixedSizeNodeStack(Object[] array) {
+            this.array = array;
+        }
+
+        boolean isFull() {
+            return tos == array.length;
+        }
+
+        boolean isEmpty() {
+            return tos == 0;
+        }
+
+        private void push(Object node) {
+            if (tos >= array.length) {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (tos++), node);
+        }
+
+        private Object pop() {
+            if (tos <= 0) {
+                throw new ArrayIndexOutOfBoundsException();
+            }
+            return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) (--tos));
+        }
+
+        private Object[] getArray() {
+            return array;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes.serial;
+
+import java.lang.reflect.*;
+import java.nio.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Experimental API. May change without notice.
+ */
+public final class PostOrderSerializer {
+
+    private static final Unsafe unsafe = loadUnsafe();
+
+    private final SerializerConstantPool cp;
+
+    /**
+     * Constructs a new deserializer using a custom {@link SerializerConstantPool} implementation.
+     * For the {@link SerializerConstantPool} implementation at least the following methods must be
+     * implemented:
+     * <ul>
+     * <li>{@link SerializerConstantPool#putInt(int)}</li>
+     * <li>{@link SerializerConstantPool#putClass(Class)}</li>
+     * </ul>
+     */
+    public PostOrderSerializer(SerializerConstantPool cp) {
+        this.cp = cp;
+    }
+
+    /**
+     * Serializes the node AST and returns the serialized data as byte array.
+     *
+     * @param node the root node that represents the Truffle AST that should be serialized.
+     * @return a trimmed byte array that contains the serialized data.
+     *
+     * @throws UnsupportedConstantPoolTypeException thrown if a type is encountered that is not
+     *             supported by the constant pool implementation.
+     */
+    public byte[] serialize(Node node) throws UnsupportedConstantPoolTypeException {
+        VariableLengthIntBuffer buffer = new VariableLengthIntBuffer(ByteBuffer.allocate(512));
+        serialize(buffer, node);
+        return buffer.getBytes();
+    }
+
+    private void serialize(VariableLengthIntBuffer buffer, Node node) throws UnsupportedConstantPoolTypeException {
+        if (node == null) {
+            buffer.put(VariableLengthIntBuffer.NULL);
+            return;
+        }
+        Class<? extends Node> nodeClass = node.getClass();
+
+        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
+        serializeChildFields(buffer, node, nodeFields);
+        serializeChildrenFields(buffer, node, nodeFields);
+        buffer.put(cp.putClass(node.getClass()));
+        serializeDataFields(buffer, node, nodeFields);
+    }
+
+    private void serializeDataFields(VariableLengthIntBuffer buffer, Node node, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
+        for (int i = 0; i < nodeFields.length; i++) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.DATA) {
+                Class<?> fieldClass = field.getType();
+                long offset = field.getOffset();
+                int cpi;
+
+                if (field.getType().isAssignableFrom(SourceSection.class)) {
+                    continue;
+                }
+
+                if (fieldClass == int.class) {
+                    cpi = cp.putInt(unsafe.getInt(node, offset));
+                } else if (fieldClass == long.class) {
+                    cpi = cp.putLong(unsafe.getLong(node, offset));
+                } else if (fieldClass == float.class) {
+                    cpi = cp.putFloat(unsafe.getFloat(node, offset));
+                } else if (fieldClass == double.class) {
+                    cpi = cp.putDouble(unsafe.getDouble(node, offset));
+                } else if (fieldClass == byte.class) {
+                    cpi = cp.putInt(unsafe.getByte(node, offset));
+                } else if (fieldClass == short.class) {
+                    cpi = cp.putInt(unsafe.getShort(node, offset));
+                } else if (fieldClass == char.class) {
+                    cpi = cp.putInt(unsafe.getChar(node, offset));
+                } else if (fieldClass == boolean.class) {
+                    cpi = cp.putInt(unsafe.getBoolean(node, offset) ? 1 : 0);
+                } else {
+                    cpi = serializeDataFieldsObject(node, fieldClass, offset);
+                }
+
+                buffer.put(cpi);
+            }
+        }
+    }
+
+    private int serializeDataFieldsObject(Node node, Class<?> fieldClass, long offset) {
+        Object value = unsafe.getObject(node, offset);
+        if (value == null) {
+            return VariableLengthIntBuffer.NULL;
+        } else if (fieldClass == Integer.class) {
+            return cp.putInt((Integer) value);
+        } else if (fieldClass == Long.class) {
+            return cp.putLong((Long) value);
+        } else if (fieldClass == Float.class) {
+            return cp.putFloat((Float) value);
+        } else if (fieldClass == Double.class) {
+            return cp.putDouble((Double) value);
+        } else if (fieldClass == Byte.class) {
+            return cp.putInt((Byte) value);
+        } else if (fieldClass == Short.class) {
+            return cp.putInt((Short) value);
+        } else if (fieldClass == Character.class) {
+            return cp.putInt((Character) value);
+        } else if (fieldClass == Boolean.class) {
+            return cp.putInt((Boolean) value ? 1 : 0);
+        } else {
+            return cp.putObject(fieldClass, value);
+        }
+    }
+
+    private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
+        for (int i = 0; i < nodeFields.length; i++) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.CHILDREN) {
+                Object childArrayObject = unsafe.getObject(nodeInstance, field.getOffset());
+                if (childArrayObject != null && !(childArrayObject instanceof Node[])) {
+                    throw new AssertionError("Node children must be instanceof Node[]");
+                }
+
+                buffer.put(cp.putClass(field.getType()));
+
+                Node[] childArray = (Node[]) childArrayObject;
+                if (childArray == null) {
+                    buffer.put(VariableLengthIntBuffer.NULL);
+                } else {
+                    buffer.put(cp.putInt(childArray.length));
+
+                    for (int j = 0; j < childArray.length; j++) {
+                        serialize(buffer, childArray[j]);
+                    }
+                }
+            }
+        }
+    }
+
+    private void serializeChildFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
+        for (int i = 0; i < nodeFields.length; i++) {
+            NodeFieldAccessor field = nodeFields[i];
+            if (field.getKind() == NodeFieldKind.CHILD) {
+                Object childObject = unsafe.getObject(nodeInstance, field.getOffset());
+                if (childObject != null && !(childObject instanceof Node)) {
+                    throw new AssertionError("Node children must be instanceof Node");
+                }
+                serialize(buffer, (Node) childObject);
+            }
+        }
+    }
+
+    private static Unsafe loadUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/SerializerConstantPool.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes.serial;
+
+/**
+ * Experimental API. May change without notice. This interface is used as bridge between the
+ * {@link PostOrderDeserializer}, {@link PostOrderSerializer} and underlying constant pool
+ * implementation. A constant pool stores a value and returns an identifying index, with which the
+ * object can later be returned from the pool again. All methods of this class are optional and may
+ * throw a {@link UnsupportedOperationException}.
+ */
+public interface SerializerConstantPool {
+
+    /**
+     * Returns the constant pool index of a value that is not a java native type, a java
+     * native-wrapper class or a {@link Class} instance. The implementor should support all
+     * additional types that are necessary to serialize a truffle AST for a specific truffle
+     * implementation. If a type is not supported by this constant pool implementation a
+     * {@link UnsupportedConstantPoolTypeException} should be thrown.
+     *
+     * @param clazz the {@link Class} of the value
+     * @param value the value to be stored. Must be at least a subclass of the given clazz.
+     * @return the constant pool index
+     * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in
+     *             the constant pool.
+     */
+    int putObject(Class<?> clazz, Object value) throws UnsupportedConstantPoolTypeException;
+
+    /**
+     * Stores a value in the constant pool that is not a java native type, a java native-wrapper
+     * class or a {@link Class} instance. The implementor should support all additional types that
+     * are necessary to serialize a truffle AST for a specific truffle implementation. If a type is
+     * not supported by this constant pool implementation a
+     * {@link UnsupportedConstantPoolTypeException} should be thrown.
+     *
+     * @param clazz the {@link Class} of the value in the constant pool.
+     * @param cpi the previously returned index
+     * @return the value stored inside the constant pool
+     * @throws UnsupportedConstantPoolTypeException if a type is not supported for persistence in
+     *             the constant pool.
+     * @throws IllegalArgumentException if the provided cpi is not a valid constant pool index.
+     */
+    Object getObject(Class<?> clazz, int cpi) throws UnsupportedConstantPoolTypeException;
+
+    /**
+     * Stores a Class instance in the constant pool and returns the constant pool index.
+     *
+     * @param value the class to store
+     * @return the new or existing constant pool index of the Class
+     */
+    int putClass(Class<?> value);
+
+    /**
+     * Returns the {@link Class} instance to the given constant pool index.
+     *
+     * @param cpi the constant pool index
+     * @return stored value
+     * @throws IllegalArgumentException if the constant pool indes is invalid.
+     */
+    Class<?> getClass(int cpi);
+
+    /**
+     * Stores an int value in the constant pool and returns the constant pool index.
+     *
+     * @param value the value to store
+     * @return the new or existing constant pool index of the value
+     */
+    int putInt(int value);
+
+    /**
+     * Returns the stored int value to the given constant pool index from the constant pool.
+     *
+     * @param cpi the constant pool index
+     * @return stored value
+     * @throws IllegalArgumentException if the constant pool index is invalid.
+     */
+    int getInt(int cpi);
+
+    /**
+     * Stores a long value in the constant pool and returns the constant pool index.
+     *
+     * @param value the value to store
+     * @return the new or existing constant pool index of the value
+     */
+    int putLong(long value);
+
+    /**
+     * Returns the stored long value to the given constant pool index from the constant pool.
+     *
+     * @param cpi the constant pool index
+     * @return the stored value
+     * @throws IllegalArgumentException if the constant pool index is invalid.
+     */
+    long getLong(int cpi);
+
+    /**
+     * Stores a double value in the constant pool and returns the constant pool index.
+     *
+     * @param value the value to store
+     * @return the new or existing constant pool index of the value
+     */
+    int putDouble(double value);
+
+    /**
+     * Returns the stored double value to the given constant pool index from the constant pool.
+     *
+     * @param cpi the constant pool index
+     * @return the stored value
+     * @throws IllegalArgumentException if the constant pool index is invalid.
+     */
+    double getDouble(int cpi);
+
+    /**
+     * Stores a float value in the constant pool and returns the constant pool index.
+     *
+     * @param value the value to store
+     * @return the new or existing constant pool index of the value
+     */
+    int putFloat(float value);
+
+    /**
+     * Returns the stored float value to the given constant pool index from the constant pool.
+     *
+     * @param cpi the constant pool index
+     * @return the stored value
+     * @throws IllegalArgumentException if the constant pool index is invalid.
+     */
+    float getFloat(int cpi);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/UnsupportedConstantPoolTypeException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes.serial;
+
+/**
+ * Experimental API. May change without notice.
+ */
+public class UnsupportedConstantPoolTypeException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public UnsupportedConstantPoolTypeException() {
+        super();
+    }
+
+    public UnsupportedConstantPoolTypeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public UnsupportedConstantPoolTypeException(String message) {
+        super(message);
+    }
+
+    public UnsupportedConstantPoolTypeException(Throwable cause) {
+        super(cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/VariableLengthIntBuffer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.nodes.serial;
+
+import java.nio.*;
+
+/**
+ * Experimental API. May change without notice. Simple variable length unsigned int buffer backed by
+ * a byte buffer.
+ */
+public class VariableLengthIntBuffer {
+
+    public static final int NULL = -1;
+
+    private ByteBuffer buffer;
+
+    public VariableLengthIntBuffer(ByteBuffer buffer) {
+        this.buffer = buffer;
+    }
+
+    public VariableLengthIntBuffer(byte[] array) {
+        buffer = ByteBuffer.wrap(array);
+    }
+
+    /**
+     * Returns the backing byte buffer.
+     */
+    public ByteBuffer getBuffer() {
+        return buffer;
+    }
+
+    public byte[] getBytes() {
+        int pos = buffer.position();
+        byte[] bytes = new byte[buffer.position()];
+        buffer.rewind();
+        buffer.get(bytes);
+        buffer.position(pos);
+        return bytes;
+    }
+
+    public int get() {
+        byte peekByte = buffer.get(buffer.position());
+        if ((peekByte & 0x80) == 0) {
+            // single byte encoding with prefix 0 (range 127)
+            return buffer.get(); // no bit to be masked
+        } else {
+            if (peekByte == (byte) 0xFF) {
+                buffer.get(); // skip one byte
+                return NULL;
+            }
+            int result = buffer.getInt() & 0x7FFF_FFFF; // first bit masked out
+            assert (result & 0x4000_0000) == 0;
+            return result;
+        }
+    }
+
+    public void put(int i) {
+        ensureCapacity();
+        if (i == NULL) {
+            buffer.put((byte) 0xFF);
+        } else if ((i & 0xFFFF_FF80) == 0) { // 7 bits data
+            buffer.put((byte) i);
+        } else if ((i & 0xC000_0000) == 0) { // 32 bits data
+            buffer.putInt(i | 0x8000_0000); // append leading 1
+        } else {
+            throw new IllegalArgumentException("Integer out of encodeable " + i);
+        }
+    }
+
+    private void ensureCapacity() {
+        if (buffer.position() + 4 > buffer.capacity()) {
+            ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
+
+            int pos = buffer.position();
+            buffer.rewind();
+            newBuffer.put(buffer);
+            newBuffer.position(pos);
+
+            buffer = newBuffer;
+        }
+    }
+
+    public boolean hasRemaining() {
+        return buffer.hasRemaining();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/script/TruffleScriptEngineFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.script;
+
+import javax.script.*;
+
+/**
+ * Tool access to the creation of Truffle execution engines.
+ */
+public abstract class TruffleScriptEngineFactory implements ScriptEngineFactory {
+
+    // TODO (mlvdv) first step, based on a suggestion from NetBeans
+    /**
+     * To be called by each concrete factory just after each engine instance is created, presenting
+     * an opportunity for an IDE to interrupt in a language-independent way.
+     *
+     * @param engine a just-created engine
+     */
+    protected final void engineCreated(ScriptEngine engine) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/BytesDecoder.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+import java.nio.charset.*;
+import java.util.*;
+
+/**
+ * For a language where strings do not map into Java strings, provides utilities to find line
+ * endings and to decode raw bytes into an approximate representation for tools to display.
+ * <p>
+ * See {@link Source#fromBytes}.
+ */
+public interface BytesDecoder {
+
+    String decode(byte[] bytes, int byteIndex, int length);
+
+    void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker);
+
+    public interface LineMarker {
+
+        void markLine(int index);
+
+    }
+
+    public static class UTF8BytesDecoder implements BytesDecoder {
+
+        @Override
+        public String decode(byte[] bytes, int byteIndex, int length) {
+            return new String(Arrays.copyOfRange(bytes, byteIndex, byteIndex + length), StandardCharsets.UTF_8);
+        }
+
+        @Override
+        public void decodeLines(byte[] bytes, int byteIndex, int length, LineMarker lineMarker) {
+            for (int n = byteIndex; n < byteIndex + length; n++) {
+                if (bytes[n] == '\n') {
+                    lineMarker.markLine(n + 1);
+                }
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/LineLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+import java.util.*;
+
+/**
+ * A specification for a location in guest language source, expressed as a line number in a specific
+ * instance of {@link Source}, suitable for hash table keys with equality defined in terms of
+ * content.
+ */
+public interface LineLocation {
+
+    Source getSource();
+
+    /**
+     * Gets the 1-based number of a line in the source.
+     */
+    int getLineNumber();
+
+    String getShortDescription();
+
+    /**
+     * Default comparator by (1) textual path name, (2) line number.
+     */
+    Comparator<LineLocation> COMPARATOR = new Comparator<LineLocation>() {
+
+        public int compare(LineLocation l1, LineLocation l2) {
+            final int sourceResult = l1.getSource().getPath().compareTo(l2.getSource().getPath());
+            if (sourceResult != 0) {
+                return sourceResult;
+            }
+            return Integer.compare(l1.getLineNumber(), l2.getLineNumber());
+        }
+
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/NullSourceSection.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+/**
+ * A special subtype of {@link SourceSection} that represents unavailable source, e.g. for language
+ * <em>builtins</em>.
+ */
+public class NullSourceSection implements SourceSection {
+
+    private final String kind;
+    private final String name;
+    private final String asCode;
+
+    /**
+     * Placeholder for source that is unavailable, e.g. for language <em>builtins</em>.
+     *
+     * @param kind the general category, e.g. "JS builtin"
+     * @param name specific name for this section
+     */
+    public NullSourceSection(String kind, String name) {
+        this(kind, name, kind);
+    }
+
+    /**
+     * Placeholder for source that is unavailable, e.g. for language <em>builtins</em>.
+     *
+     * @param kind the general category, e.g. "JS builtin"
+     * @param name specific name for this section
+     * @param asCode string to return when {@link #getCode()} is called
+     */
+    public NullSourceSection(String kind, String name, String asCode) {
+        this.kind = kind;
+        this.name = name;
+        this.asCode = asCode;
+    }
+
+    public final Source getSource() {
+        return null;
+    }
+
+    public final int getStartLine() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final LineLocation getLineLocation() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final int getStartColumn() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public int getEndLine() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public int getEndColumn() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final int getCharIndex() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final int getCharLength() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final int getCharEndIndex() {
+        throw new UnsupportedOperationException(this.toString());
+    }
+
+    public final String getIdentifier() {
+        return name;
+    }
+
+    public final String getCode() {
+        return asCode;
+    }
+
+    public final String getShortDescription() {
+        return kind + ": " + name;
+    }
+
+    @Override
+    public String toString() {
+        return getShortDescription();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1553 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+import java.io.*;
+import java.lang.ref.*;
+import java.net.*;
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+
+/**
+ * Representation of a guest language source code unit and its contents. Sources originate in
+ * several ways:
+ * <ul>
+ * <li><strong>Literal:</strong> An anonymous text string: not named and not indexed. These should
+ * be considered value objects; equality is defined based on contents.<br>
+ * See {@link Source#fromText(CharSequence, String)}</li>
+ * <p>
+ * <li><strong>Named Literal:</strong> A text string that can be retrieved by name as if it were a
+ * file, but without any assumption that the name is related to a file path. Creating a new literal
+ * with an already existing name will replace its predecessor in the index.<br>
+ * See {@link Source#fromNamedText(CharSequence, String)}<br>
+ * See {@link Source#find(String)}</li>
+ * <p>
+ * <li><strong>File:</strong> Each file is represented as a canonical object, indexed by the
+ * absolute, canonical path name of the file. File contents are <em>read lazily</em> and contents
+ * optionally <em>cached</em>. <br>
+ * See {@link Source#fromFileName(String)}<br>
+ * See {@link Source#fromFileName(String, boolean)}<br>
+ * See {@link Source#find(String)}</li>
+ * <p>
+ * <li><strong>URL:</strong> Each URL source is represented as a canonical object, indexed by the
+ * URL. Contents are <em>read eagerly</em> and <em>cached</em>. <br>
+ * See {@link Source#fromURL(URL, String)}<br>
+ * See {@link Source#find(String)}</li>
+ * <p>
+ * <li><strong>Reader:</strong> Contents are <em>read eagerly</em> and treated as an anonymous
+ * (non-indexed) <em>Literal</em> . <br>
+ * See {@link Source#fromReader(Reader, String)}</li>
+ * <p>
+ * <li><strong>Sub-Source:</strong> A representation of the contents of a sub-range of another
+ * {@link Source}.<br>
+ * See @link {@link Source#subSource(Source, int, int)}<br>
+ * See @link {@link Source#subSource(Source, int)}</li>
+ * <p>
+ * <li><strong>AppendableSource:</strong> Literal contents are provided by the client,
+ * incrementally, after the instance is created.<br>
+ * See {@link Source#fromAppendableText(String)}<br>
+ * See {@link Source#fromNamedAppendableText(String)}</li>
+ * </ul>
+ * <p>
+ * <strong>File cache:</strong>
+ * <ol>
+ * <li>File content caching is optional, <em>on</em> by default.</li>
+ * <li>The first access to source file contents will result in the contents being read, and (if
+ * enabled) cached.</li>
+ * <li>If file contents have been cached, access to contents via {@link Source#getInputStream()} or
+ * {@link Source#getReader()} will be provided from the cache.</li>
+ * <li>Any access to file contents via the cache will result in a timestamp check and possible cache
+ * reload.</li>
+ * </ol>
+ * <p>
+ *
+ * @see SourceTag
+ * @see SourceListener
+ */
+public abstract class Source {
+
+    // TODO (mlvdv) consider canonicalizing and reusing SourceSection instances
+    // TOOD (mlvdv) connect SourceSections into a spatial tree for fast geometric lookup
+
+    public enum Tags implements SourceTag {
+
+        /**
+         * From bytes.
+         */
+        FROM_BYTES("bytes", "read from bytes"),
+
+        /**
+         * Read from a file.
+         */
+        FROM_FILE("file", "read from a file"),
+
+        /**
+         * From literal text.
+         */
+        FROM_LITERAL("literal", "from literal text"),
+
+        /**
+         * From a {@linkplain java.io.Reader Reader}.
+         */
+        FROM_READER("reader", "read from a Java Reader"),
+
+        /**
+         * Read from a URL.
+         */
+        FROM_URL("URL", "read from a URL");
+
+        private final String name;
+        private final String description;
+
+        private Tags(String name, String description) {
+            this.name = name;
+            this.description = description;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+    }
+
+    /**
+     * All Sources that have been created.
+     */
+    private static final List<WeakReference<Source>> allSources = Collections.synchronizedList(new ArrayList<WeakReference<Source>>());
+
+    /**
+     * Index of all named sources.
+     */
+    private static final Map<String, WeakReference<Source>> nameToSource = new HashMap<>();
+
+    private static boolean fileCacheEnabled = true;
+
+    private static final List<SourceListener> sourceListeners = new ArrayList<>();
+
+    /**
+     * Locates an existing instance by the name under which it was indexed.
+     */
+    public static Source find(String name) {
+        final WeakReference<Source> nameRef = nameToSource.get(name);
+        return nameRef == null ? null : nameRef.get();
+    }
+
+    /**
+     * Gets the canonical representation of a source file, whose contents will be read lazily and
+     * then cached.
+     *
+     * @param fileName name
+     * @param reset forces any existing {@link Source} cache to be cleared, forcing a re-read
+     * @return canonical representation of the file's contents.
+     * @throws IOException if the file can not be read
+     */
+    public static Source fromFileName(String fileName, boolean reset) throws IOException {
+
+        final WeakReference<Source> nameRef = nameToSource.get(fileName);
+        Source source = nameRef == null ? null : nameRef.get();
+        if (source == null) {
+            final File file = new File(fileName);
+            if (!file.canRead()) {
+                throw new IOException("Can't read file " + fileName);
+            }
+            final String path = file.getCanonicalPath();
+            final WeakReference<Source> pathRef = nameToSource.get(path);
+            source = pathRef == null ? null : pathRef.get();
+            if (source == null) {
+                source = new FileSource(file, fileName, path);
+                nameToSource.put(path, new WeakReference<>(source));
+            }
+        }
+        if (reset) {
+            source.reset();
+        }
+        notifyNewSource(source).tagAs(Tags.FROM_FILE);
+        return source;
+    }
+
+    /**
+     * Gets the canonical representation of a source file, whose contents will be read lazily and
+     * then cached.
+     *
+     * @param fileName name
+     * @return canonical representation of the file's contents.
+     * @throws IOException if the file can not be read
+     */
+    public static Source fromFileName(String fileName) throws IOException {
+        return fromFileName(fileName, false);
+    }
+
+    /**
+     * Gets the canonical representation of a source file, whose contents have already been read and
+     * need not be read again. It is confirmed that the file resolves to a file name, so it can be
+     * indexed by canonical path. It is not confirmed that the text supplied agrees with the file's
+     * contents or even whether the file is readable.
+     *
+     * @param chars textual source code already read from the file
+     * @param fileName
+     * @return canonical representation of the file's contents.
+     * @throws IOException if the file cannot be found
+     */
+    public static Source fromFileName(CharSequence chars, String fileName) throws IOException {
+
+        final WeakReference<Source> nameRef = nameToSource.get(fileName);
+        Source source = nameRef == null ? null : nameRef.get();
+        if (source == null) {
+            final File file = new File(fileName);
+            // We are going to trust that the fileName is readable.
+            final String path = file.getCanonicalPath();
+            final WeakReference<Source> pathRef = nameToSource.get(path);
+            source = pathRef == null ? null : pathRef.get();
+            if (source == null) {
+                source = new FileSource(file, fileName, path, chars);
+                nameToSource.put(path, new WeakReference<>(source));
+            }
+        }
+        notifyNewSource(source).tagAs(Tags.FROM_FILE);
+        return source;
+    }
+
+    /**
+     * Creates an anonymous source from literal text: not named and not indexed.
+     *
+     * @param chars textual source code
+     * @param description a note about the origin, for error messages and debugging
+     * @return a newly created, non-indexed source representation
+     */
+    public static Source fromText(CharSequence chars, String description) {
+        assert chars != null;
+        final LiteralSource source = new LiteralSource(description, chars.toString());
+        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
+        return source;
+    }
+
+    /**
+     * Creates an anonymous source from literal text that is provided incrementally after creation:
+     * not named and not indexed.
+     *
+     * @param description a note about the origin, for error messages and debugging
+     * @return a newly created, non-indexed, initially empty, appendable source representation
+     */
+    public static Source fromAppendableText(String description) {
+        final Source source = new AppendableLiteralSource(description);
+        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
+        return source;
+    }
+
+    /**
+     * Creates a source from literal text that can be retrieved by name, with no assumptions about
+     * the structure or meaning of the name. If the name is already in the index, the new instance
+     * will replace the previously existing instance in the index.
+     *
+     * @param chars textual source code
+     * @param name string to use for indexing/lookup
+     * @return a newly created, source representation
+     */
+    public static Source fromNamedText(CharSequence chars, String name) {
+        final Source source = new LiteralSource(name, chars.toString());
+        nameToSource.put(name, new WeakReference<>(source));
+        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
+        return source;
+    }
+
+    /**
+     * Creates a source from literal text that is provided incrementally after creation and which
+     * can be retrieved by name, with no assumptions about the structure or meaning of the name. If
+     * the name is already in the index, the new instance will replace the previously existing
+     * instance in the index.
+     *
+     * @param name string to use for indexing/lookup
+     * @return a newly created, indexed, initially empty, appendable source representation
+     */
+    public static Source fromNamedAppendableText(String name) {
+        final Source source = new AppendableLiteralSource(name);
+        nameToSource.put(name, new WeakReference<>(source));
+        notifyNewSource(source).tagAs(Tags.FROM_LITERAL);
+        return source;
+    }
+
+    /**
+     * Creates a {@linkplain Source Source instance} that represents the contents of a sub-range of
+     * an existing {@link Source}.
+     *
+     * @param base an existing Source instance
+     * @param baseCharIndex 0-based index of the first character of the sub-range
+     * @param length the number of characters in the sub-range
+     * @return a new instance representing a sub-range of another Source
+     * @throws IllegalArgumentException if the specified sub-range is not contained in the base
+     */
+    public static Source subSource(Source base, int baseCharIndex, int length) {
+        final SubSource subSource = SubSource.create(base, baseCharIndex, length);
+        return subSource;
+    }
+
+    /**
+     * Creates a {@linkplain Source Source instance} that represents the contents of a sub-range at
+     * the end of an existing {@link Source}.
+     *
+     * @param base an existing Source instance
+     * @param baseCharIndex 0-based index of the first character of the sub-range
+     * @return a new instance representing a sub-range at the end of another Source
+     * @throws IllegalArgumentException if the index is out of range
+     */
+    public static Source subSource(Source base, int baseCharIndex) {
+        return subSource(base, baseCharIndex, base.getLength() - baseCharIndex);
+    }
+
+    /**
+     * Creates a source whose contents will be read immediately from a URL and cached.
+     *
+     * @param url
+     * @param description identifies the origin, possibly useful for debugging
+     * @return a newly created, non-indexed source representation
+     * @throws IOException if reading fails
+     */
+    public static Source fromURL(URL url, String description) throws IOException {
+        final URLSource source = URLSource.get(url, description);
+        notifyNewSource(source).tagAs(Tags.FROM_URL);
+        return source;
+    }
+
+    /**
+     * Creates a source whose contents will be read immediately and cached.
+     *
+     * @param reader
+     * @param description a note about the origin, possibly useful for debugging
+     * @return a newly created, non-indexed source representation
+     * @throws IOException if reading fails
+     */
+    public static Source fromReader(Reader reader, String description) throws IOException {
+        final LiteralSource source = new LiteralSource(description, read(reader));
+        notifyNewSource(source).tagAs(Tags.FROM_READER);
+        return source;
+    }
+
+    /**
+     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
+     * is not compatible with Java strings, or if your parser returns byte indices instead of
+     * character indices. The returned source is then indexed by byte, not by character.
+     *
+     * @param bytes the raw bytes of the source
+     * @param description a note about the origin, possibly useful for debugging
+     * @param decoder how to decode the bytes into Java strings
+     * @return a newly created, non-indexed source representation
+     */
+    public static Source fromBytes(byte[] bytes, String description, BytesDecoder decoder) {
+        return fromBytes(bytes, 0, bytes.length, description, decoder);
+    }
+
+    /**
+     * Creates a source from raw bytes. This can be used if the encoding of strings in your language
+     * is not compatible with Java strings, or if your parser returns byte indices instead of
+     * character indices. The returned source is then indexed by byte, not by character. Offsets are
+     * relative to byteIndex.
+     *
+     * @param bytes the raw bytes of the source
+     * @param byteIndex where the string starts in the byte array
+     * @param length the length of the string in the byte array
+     * @param description a note about the origin, possibly useful for debugging
+     * @param decoder how to decode the bytes into Java strings
+     * @return a newly created, non-indexed source representation
+     */
+    public static Source fromBytes(byte[] bytes, int byteIndex, int length, String description, BytesDecoder decoder) {
+        final BytesSource source = new BytesSource(description, bytes, byteIndex, length, decoder);
+        notifyNewSource(source).tagAs(Tags.FROM_BYTES);
+        return source;
+    }
+
+    // TODO (mlvdv) enable per-file choice whether to cache?
+    /**
+     * Enables/disables caching of file contents, <em>disabled</em> by default. Caching of sources
+     * created from literal text or readers is always enabled.
+     */
+    public static void setFileCaching(boolean enabled) {
+        fileCacheEnabled = enabled;
+    }
+
+    /**
+     * Returns all {@link Source}s holding a particular {@link SyntaxTag}, or the whole collection
+     * of Sources if the specified tag is {@code null}.
+     *
+     * @return A collection of Sources containing the given tag.
+     */
+    public static Collection<Source> findSourcesTaggedAs(SourceTag tag) {
+        final List<Source> taggedSources = new ArrayList<>();
+        synchronized (allSources) {
+            for (WeakReference<Source> ref : allSources) {
+                Source source = ref.get();
+                if (source != null) {
+                    if (tag == null || source.isTaggedAs(tag)) {
+                        taggedSources.add(ref.get());
+                    }
+                }
+            }
+        }
+        return taggedSources;
+    }
+
+    /**
+     * Adds a {@link SourceListener} to receive events.
+     */
+    public static void addSourceListener(SourceListener listener) {
+        assert listener != null;
+        sourceListeners.add(listener);
+    }
+
+    /**
+     * Removes a {@link SourceListener}. Ignored if listener not found.
+     */
+    public static void removeSourceListener(SourceListener listener) {
+        sourceListeners.remove(listener);
+    }
+
+    private static Source notifyNewSource(Source source) {
+        allSources.add(new WeakReference<>(source));
+        for (SourceListener listener : sourceListeners) {
+            listener.sourceCreated(source);
+        }
+        return source;
+    }
+
+    private static String read(Reader reader) throws IOException {
+        final BufferedReader bufferedReader = new BufferedReader(reader);
+        final StringBuilder builder = new StringBuilder();
+        final char[] buffer = new char[1024];
+
+        while (true) {
+            final int n = bufferedReader.read(buffer);
+            if (n == -1) {
+                break;
+            }
+            builder.append(buffer, 0, n);
+        }
+
+        return builder.toString();
+    }
+
+    private final ArrayList<SourceTag> tags = new ArrayList<>();
+
+    private Source() {
+    }
+
+    private TextMap textMap = null;
+
+    protected abstract void reset();
+
+    public final boolean isTaggedAs(SourceTag tag) {
+        assert tag != null;
+        return tags.contains(tag);
+    }
+
+    public final Collection<SourceTag> getSourceTags() {
+        return Collections.unmodifiableCollection(tags);
+    }
+
+    /**
+     * Adds a {@linkplain SourceTag tag} to the set of tags associated with this {@link Source};
+     * {@code no-op} if already in the set.
+     *
+     * @return this
+     */
+    public final Source tagAs(SourceTag tag) {
+        assert tag != null;
+        if (!tags.contains(tag)) {
+            tags.add(tag);
+            for (SourceListener listener : sourceListeners) {
+                listener.sourceTaggedAs(this, tag);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Returns the name of this resource holding a guest language program. An example would be the
+     * name of a guest language source code file.
+     *
+     * @return the name of the guest language program
+     */
+    public abstract String getName();
+
+    /**
+     * Returns a short version of the name of the resource holding a guest language program (as
+     * described in @getName). For example, this could be just the name of the file, rather than a
+     * full path.
+     *
+     * @return the short name of the guest language program
+     */
+    public abstract String getShortName();
+
+    /**
+     * The normalized, canonical name if the source is a file.
+     */
+    public abstract String getPath();
+
+    /**
+     * The URL if the source is retrieved via URL.
+     */
+    public abstract URL getURL();
+
+    /**
+     * Access to the source contents.
+     */
+    public abstract Reader getReader();
+
+    /**
+     * Access to the source contents.
+     */
+    public final InputStream getInputStream() {
+        return new ByteArrayInputStream(getCode().getBytes());
+    }
+
+    /**
+     * Gets the number of characters in the source.
+     */
+    public final int getLength() {
+        return getTextMap().length();
+    }
+
+    /**
+     * Returns the complete text of the code.
+     */
+    public abstract String getCode();
+
+    /**
+     * Returns a subsection of the code test.
+     */
+    public String getCode(int charIndex, int charLength) {
+        return getCode().substring(charIndex, charIndex + charLength);
+    }
+
+    /**
+     * Gets the text (not including a possible terminating newline) in a (1-based) numbered line.
+     */
+    public final String getCode(int lineNumber) {
+        final int offset = getTextMap().lineStartOffset(lineNumber);
+        final int length = getTextMap().lineLength(lineNumber);
+        return getCode().substring(offset, offset + length);
+    }
+
+    /**
+     * The number of text lines in the source, including empty lines; characters at the end of the
+     * source without a terminating newline count as a line.
+     */
+    public final int getLineCount() {
+        return getTextMap().lineCount();
+    }
+
+    /**
+     * Given a 0-based character offset, return the 1-based number of the line that includes the
+     * position.
+     *
+     * @throws IllegalArgumentException if the offset is outside the text contents
+     */
+    public final int getLineNumber(int offset) throws IllegalArgumentException {
+        return getTextMap().offsetToLine(offset);
+    }
+
+    /**
+     * Given a 0-based character offset, return the 1-based number of the column at the position.
+     *
+     * @throws IllegalArgumentException if the offset is outside the text contents
+     */
+    public final int getColumnNumber(int offset) throws IllegalArgumentException {
+        return getTextMap().offsetToCol(offset);
+    }
+
+    /**
+     * Given a 1-based line number, return the 0-based offset of the first character in the line.
+     *
+     * @throws IllegalArgumentException if there is no such line in the text
+     */
+    public final int getLineStartOffset(int lineNumber) throws IllegalArgumentException {
+        return getTextMap().lineStartOffset(lineNumber);
+    }
+
+    /**
+     * The number of characters (not counting a possible terminating newline) in a (1-based)
+     * numbered line.
+     *
+     * @throws IllegalArgumentException if there is no such line in the text
+     */
+    public final int getLineLength(int lineNumber) throws IllegalArgumentException {
+        return getTextMap().lineLength(lineNumber);
+    }
+
+    /**
+     * Append text to a Source explicitly created as <em>Appendable</em>.
+     *
+     * @param chars the text to append
+     * @throws UnsupportedOperationException by concrete subclasses that do not support appending
+     */
+    public void appendCode(CharSequence chars) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Creates a representation of a contiguous region of text in the source.
+     * <p>
+     * This method performs no checks on the validity of the arguments.
+     * <p>
+     * The resulting representation defines hash/equality around equivalent location, presuming that
+     * {@link Source} representations are canonical.
+     *
+     * @param identifier terse description of the region
+     * @param startLine 1-based line number of the first character in the section
+     * @param startColumn 1-based column number of the first character in the section
+     * @param charIndex the 0-based index of the first character of the section
+     * @param length the number of characters in the section
+     * @return newly created object representing the specified region
+     */
+    public final SourceSection createSection(String identifier, int startLine, int startColumn, int charIndex, int length) {
+        return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length);
+    }
+
+    /**
+     * Creates a representation of a contiguous region of text in the source. Computes the
+     * {@code charIndex} value by building a {@linkplain TextMap map} of lines in the source.
+     * <p>
+     * Checks the position arguments for consistency with the source.
+     * <p>
+     * The resulting representation defines hash/equality around equivalent location, presuming that
+     * {@link Source} representations are canonical.
+     *
+     * @param identifier terse description of the region
+     * @param startLine 1-based line number of the first character in the section
+     * @param startColumn 1-based column number of the first character in the section
+     * @param length the number of characters in the section
+     * @return newly created object representing the specified region
+     * @throws IllegalArgumentException if arguments are outside the text of the source
+     * @throws IllegalStateException if the source is one of the "null" instances
+     */
+    public final SourceSection createSection(String identifier, int startLine, int startColumn, int length) {
+        final int lineStartOffset = getTextMap().lineStartOffset(startLine);
+        if (startColumn > getTextMap().lineLength(startLine)) {
+            throw new IllegalArgumentException("column out of range");
+        }
+        final int startOffset = lineStartOffset + startColumn - 1;
+        return new DefaultSourceSection(this, identifier, startLine, startColumn, startOffset, length);
+    }
+
+    /**
+     * Creates a representation of a contiguous region of text in the source. Computes the
+     * {@code (startLine, startColumn)} values by building a {@linkplain TextMap map} of lines in
+     * the source.
+     * <p>
+     * Checks the position arguments for consistency with the source.
+     * <p>
+     * The resulting representation defines hash/equality around equivalent location, presuming that
+     * {@link Source} representations are canonical.
+     *
+     *
+     * @param identifier terse description of the region
+     * @param charIndex 0-based position of the first character in the section
+     * @param length the number of characters in the section
+     * @return newly created object representing the specified region
+     * @throws IllegalArgumentException if either of the arguments are outside the text of the
+     *             source
+     * @throws IllegalStateException if the source is one of the "null" instances
+     */
+    public final SourceSection createSection(String identifier, int charIndex, int length) throws IllegalArgumentException {
+        checkRange(charIndex, length);
+        final int startLine = getLineNumber(charIndex);
+        final int startColumn = charIndex - getLineStartOffset(startLine) + 1;
+        return new DefaultSourceSection(this, identifier, startLine, startColumn, charIndex, length);
+    }
+
+    protected void checkRange(int charIndex, int length) {
+        if (!(charIndex >= 0 && length >= 0 && charIndex + length <= getCode().length())) {
+            throw new IllegalArgumentException("text positions out of range");
+        }
+    }
+
+    /**
+     * Creates a representation of a line of text in the source identified only by line number, from
+     * which the character information will be computed.
+     *
+     * @param identifier terse description of the line
+     * @param lineNumber 1-based line number of the first character in the section
+     * @return newly created object representing the specified line
+     * @throws IllegalArgumentException if the line does not exist the source
+     * @throws IllegalStateException if the source is one of the "null" instances
+     */
+    public final SourceSection createSection(String identifier, int lineNumber) {
+        final int charIndex = getTextMap().lineStartOffset(lineNumber);
+        final int length = getTextMap().lineLength(lineNumber);
+        return createSection(identifier, charIndex, length);
+    }
+
+    /**
+     * Creates a representation of a line number in this source, suitable for use as a hash table
+     * key with equality defined to mean equivalent location.
+     *
+     * @param lineNumber a 1-based line number in this source
+     * @return a representation of a line in this source
+     */
+    public final LineLocation createLineLocation(int lineNumber) {
+        return new LineLocationImpl(this, lineNumber);
+    }
+
+    /**
+     * An object suitable for using as a key into a hashtable that defines equivalence between
+     * different source types.
+     */
+    protected Object getHashKey() {
+        return getName();
+    }
+
+    protected final TextMap getTextMap() {
+        if (textMap == null) {
+            textMap = createTextMap();
+        }
+        return textMap;
+    }
+
+    protected final void clearTextMap() {
+        textMap = null;
+    }
+
+    protected TextMap createTextMap() {
+        final String code = getCode();
+        if (code == null) {
+            throw new RuntimeException("can't read file " + getName());
+        }
+        return TextMap.fromString(code);
+    }
+
+    private static final class LiteralSource extends Source {
+
+        private final String description;
+        private final String code;
+
+        public LiteralSource(String description, String code) {
+            this.description = description;
+            this.code = code;
+        }
+
+        @Override
+        public String getName() {
+            return description;
+        }
+
+        @Override
+        public String getShortName() {
+            return description;
+        }
+
+        @Override
+        public String getCode() {
+            return code;
+        }
+
+        @Override
+        public String getPath() {
+            return description;
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            return new StringReader(code);
+        }
+
+        @Override
+        protected void reset() {
+        }
+
+        @Override
+        public int hashCode() {
+            return description.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (obj instanceof LiteralSource) {
+                LiteralSource other = (LiteralSource) obj;
+                return description.equals(other.description);
+            }
+            return false;
+        }
+    }
+
+    private static final class AppendableLiteralSource extends Source {
+        private String description;
+        final List<CharSequence> codeList = new ArrayList<>();
+
+        public AppendableLiteralSource(String description) {
+            this.description = description;
+        }
+
+        @Override
+        public String getName() {
+            return description;
+        }
+
+        @Override
+        public String getShortName() {
+            return description;
+        }
+
+        @Override
+        public String getCode() {
+            return getCodeFromIndex(0);
+        }
+
+        @Override
+        public String getPath() {
+            return description;
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            return new StringReader(getCode());
+        }
+
+        @Override
+        protected void reset() {
+        }
+
+        private String getCodeFromIndex(int index) {
+            StringBuilder sb = new StringBuilder();
+            for (int i = index; i < codeList.size(); i++) {
+                CharSequence s = codeList.get(i);
+                sb.append(s);
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public void appendCode(CharSequence chars) {
+            codeList.add(chars);
+            clearTextMap();
+        }
+
+    }
+
+    private static final class FileSource extends Source {
+
+        private final File file;
+        private final String name; // Name used originally to describe the source
+        private final String path;  // Normalized path description of an actual file
+
+        private String code = null;  // A cache of the file's contents
+        private long timeStamp;      // timestamp of the cache in the file system
+
+        public FileSource(File file, String name, String path) {
+            this(file, name, path, null);
+        }
+
+        public FileSource(File file, String name, String path, CharSequence chars) {
+            this.file = file.getAbsoluteFile();
+            this.name = name;
+            this.path = path;
+            if (chars != null) {
+                this.code = chars.toString();
+            }
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getShortName() {
+            return file.getName();
+        }
+
+        @Override
+        protected Object getHashKey() {
+            return path;
+        }
+
+        @Override
+        public String getCode() {
+            if (fileCacheEnabled) {
+                if (code == null || timeStamp != file.lastModified()) {
+                    try {
+                        code = read(getReader());
+                        timeStamp = file.lastModified();
+                    } catch (IOException e) {
+                    }
+                }
+                return code;
+            }
+            try {
+                return read(new FileReader(file));
+            } catch (IOException e) {
+            }
+            return null;
+        }
+
+        @Override
+        public String getPath() {
+            return path;
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            if (code != null && timeStamp == file.lastModified()) {
+                return new StringReader(code);
+            }
+            try {
+                return new FileReader(file);
+            } catch (FileNotFoundException e) {
+
+                throw new RuntimeException("Can't find file " + path, e);
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return path.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof FileSource) {
+                FileSource other = (FileSource) obj;
+                return path.equals(other.path);
+            }
+            return false;
+        }
+
+        @Override
+        protected void reset() {
+            this.code = null;
+        }
+    }
+
+    private static final class URLSource extends Source {
+
+        private static final Map<URL, WeakReference<URLSource>> urlToSource = new HashMap<>();
+
+        public static URLSource get(URL url, String name) throws IOException {
+            WeakReference<URLSource> sourceRef = urlToSource.get(url);
+            URLSource source = sourceRef == null ? null : sourceRef.get();
+            if (source == null) {
+                source = new URLSource(url, name);
+                urlToSource.put(url, new WeakReference<>(source));
+            }
+            return source;
+        }
+
+        private final URL url;
+        private final String name;
+        private String code = null;  // A cache of the source contents
+
+        public URLSource(URL url, String name) throws IOException {
+            this.url = url;
+            this.name = name;
+            code = read(new InputStreamReader(url.openStream()));
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getShortName() {
+            return name;
+        }
+
+        @Override
+        public String getPath() {
+            return url.getPath();
+        }
+
+        @Override
+        public URL getURL() {
+            return url;
+        }
+
+        @Override
+        public Reader getReader() {
+            return new StringReader(code);
+        }
+
+        @Override
+        public String getCode() {
+            return code;
+        }
+
+        @Override
+        protected void reset() {
+        }
+    }
+
+    private static final class SubSource extends Source {
+        private final Source base;
+        private final int baseIndex;
+        private final int subLength;
+
+        private static SubSource create(Source base, int baseIndex, int length) {
+            if (baseIndex < 0 || length < 0 || baseIndex + length > base.getLength()) {
+                throw new IllegalArgumentException("text positions out of range");
+            }
+            return new SubSource(base, baseIndex, length);
+        }
+
+        private SubSource(Source base, int baseIndex, int length) {
+            this.base = base;
+            this.baseIndex = baseIndex;
+            this.subLength = length;
+        }
+
+        @Override
+        protected void reset() {
+            assert false;
+        }
+
+        @Override
+        public String getName() {
+            return base.getName();
+        }
+
+        @Override
+        public String getShortName() {
+            return base.getShortName();
+        }
+
+        @Override
+        public String getPath() {
+            return base.getPath();
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            assert false;
+            return null;
+        }
+
+        @Override
+        public String getCode() {
+            return base.getCode(baseIndex, subLength);
+        }
+    }
+
+    private static final class BytesSource extends Source {
+
+        private final String name;
+        private final byte[] bytes;
+        private final int byteIndex;
+        private final int length;
+        private final BytesDecoder decoder;
+
+        public BytesSource(String name, byte[] bytes, int byteIndex, int length, BytesDecoder decoder) {
+            this.name = name;
+            this.bytes = bytes;
+            this.byteIndex = byteIndex;
+            this.length = length;
+            this.decoder = decoder;
+        }
+
+        @Override
+        protected void reset() {
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getShortName() {
+            return name;
+        }
+
+        @Override
+        public String getPath() {
+            return name;
+        }
+
+        @Override
+        public URL getURL() {
+            return null;
+        }
+
+        @Override
+        public Reader getReader() {
+            return null;
+        }
+
+        @Override
+        public String getCode() {
+            return decoder.decode(bytes, byteIndex, length);
+        }
+
+        @Override
+        public String getCode(int byteOffset, int codeLength) {
+            return decoder.decode(bytes, byteIndex + byteOffset, codeLength);
+        }
+
+        @Override
+        protected void checkRange(int charIndex, int rangeLength) {
+            if (!(charIndex >= 0 && rangeLength >= 0 && charIndex + rangeLength <= length)) {
+                throw new IllegalArgumentException("text positions out of range");
+            }
+        }
+
+        @Override
+        protected TextMap createTextMap() {
+            return TextMap.fromBytes(bytes, byteIndex, length, decoder);
+        }
+    }
+
+    private static final class DefaultSourceSection implements SourceSection {
+
+        private final Source source;
+        private final String identifier;
+        private final int startLine;
+        private final int startColumn;
+        private final int charIndex;
+        private final int charLength;
+
+        /**
+         * Creates a new object representing a contiguous text section within the source code of a
+         * guest language program's text.
+         * <p>
+         * The starting location of the section is specified using two different coordinate:
+         * <ul>
+         * <li><b>(row, column)</b>: rows and columns are 1-based, so the first character in a
+         * source file is at position {@code (1,1)}.</li>
+         * <li><b>character index</b>: 0-based offset of the character from the beginning of the
+         * source, so the first character in a file is at index {@code 0}.</li>
+         * </ul>
+         * The <b>newline</b> that terminates each line counts as a single character for the purpose
+         * of a character index. The (row,column) coordinates of a newline character should never
+         * appear in a text section.
+         * <p>
+         *
+         * @param source object representing the complete source program that contains this section
+         * @param identifier an identifier used when printing the section
+         * @param startLine the 1-based number of the start line of the section
+         * @param startColumn the 1-based number of the start column of the section
+         * @param charIndex the 0-based index of the first character of the section
+         * @param charLength the length of the section in number of characters
+         */
+        public DefaultSourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) {
+            this.source = source;
+            this.identifier = identifier;
+            this.startLine = startLine;
+            this.startColumn = startColumn;
+            this.charIndex = charIndex;
+            this.charLength = charLength;
+        }
+
+        @Override
+        public Source getSource() {
+            return source;
+        }
+
+        @Override
+        public int getStartLine() {
+            return startLine;
+        }
+
+        @Override
+        public LineLocation getLineLocation() {
+            return source.createLineLocation(startLine);
+        }
+
+        @Override
+        public int getStartColumn() {
+            return startColumn;
+        }
+
+        public int getEndLine() {
+            return source.getLineNumber(charIndex + charLength - 1);
+        }
+
+        public int getEndColumn() {
+            return source.getColumnNumber(charIndex + charLength - 1);
+        }
+
+        @Override
+        public int getCharIndex() {
+            return charIndex;
+        }
+
+        @Override
+        public int getCharLength() {
+            return charLength;
+        }
+
+        @Override
+        public int getCharEndIndex() {
+            return charIndex + charLength;
+        }
+
+        @Override
+        public String getIdentifier() {
+            return identifier;
+        }
+
+        @Override
+        public String getCode() {
+            return getSource().getCode(charIndex, charLength);
+        }
+
+        @Override
+        public String getShortDescription() {
+            return String.format("%s:%d", source.getShortName(), startLine);
+        }
+
+        @Override
+        public String toString() {
+            return getCode();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + charIndex;
+            result = prime * result + charLength;
+            result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
+            result = prime * result + ((source == null) ? 0 : source.hashCode());
+            result = prime * result + startColumn;
+            result = prime * result + startLine;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (!(obj instanceof DefaultSourceSection)) {
+                return false;
+            }
+            DefaultSourceSection other = (DefaultSourceSection) obj;
+            if (charIndex != other.charIndex) {
+                return false;
+            }
+            if (charLength != other.charLength) {
+                return false;
+            }
+            if (identifier == null) {
+                if (other.identifier != null) {
+                    return false;
+                }
+            } else if (!identifier.equals(other.identifier)) {
+                return false;
+            }
+            if (source == null) {
+                if (other.source != null) {
+                    return false;
+                }
+            } else if (!source.equals(other.source)) {
+                return false;
+            }
+            if (startColumn != other.startColumn) {
+                return false;
+            }
+            if (startLine != other.startLine) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private static final class LineLocationImpl implements LineLocation {
+        private final Source source;
+        private final int line;
+
+        public LineLocationImpl(Source source, int line) {
+            assert source != null;
+            this.source = source;
+            this.line = line;
+        }
+
+        @Override
+        public Source getSource() {
+            return source;
+        }
+
+        @Override
+        public int getLineNumber() {
+            return line;
+        }
+
+        @Override
+        public String getShortDescription() {
+            return source.getShortName() + ":" + line;
+        }
+
+        @Override
+        public String toString() {
+            return "Line[" + getShortDescription() + "]";
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + line;
+            result = prime * result + source.getHashKey().hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (!(obj instanceof LineLocationImpl)) {
+                return false;
+            }
+            LineLocationImpl other = (LineLocationImpl) obj;
+            if (line != other.line) {
+                return false;
+            }
+            return source.getHashKey().equals(other.source.getHashKey());
+        }
+
+    }
+
+    /**
+     * A utility for converting between coordinate systems in a string of text interspersed with
+     * newline characters. The coordinate systems are:
+     * <ul>
+     * <li>0-based character offset from the beginning of the text, where newline characters count
+     * as a single character and the first character in the text occupies position 0.</li>
+     * <li>1-based position in the 2D space of lines and columns, in which the first position in the
+     * text is at (1,1).</li>
+     * </ul>
+     * <p>
+     * This utility is based on positions occupied by characters, not text stream positions as in a
+     * text editor. The distinction shows up in editors where you can put the cursor just past the
+     * last character in a buffer; this is necessary, among other reasons, so that you can put the
+     * edit cursor in a new (empty) buffer. For the purposes of this utility, however, there are no
+     * character positions in an empty text string and there are no lines in an empty text string.
+     * <p>
+     * A newline character designates the end of a line and occupies a column position.
+     * <p>
+     * If the text ends with a character other than a newline, then the characters following the
+     * final newline character count as a line, even though not newline-terminated.
+     * <p>
+     * <strong>Limitations:</strong>
+     * <ul>
+     * <li>Does not handle multiple character encodings correctly.</li>
+     * <li>Treats tabs as occupying 1 column.</li>
+     * <li>Does not handle multiple-character line termination sequences correctly.</li>
+     * </ul>
+     */
+    private static final class TextMap {
+
+        // 0-based offsets of newline characters in the text, with sentinel
+        private final int[] nlOffsets;
+
+        // The number of characters in the text, including newlines (which count as 1).
+        private final int textLength;
+
+        // Is the final text character a newline?
+        final boolean finalNL;
+
+        public TextMap(int[] nlOffsets, int textLength, boolean finalNL) {
+            this.nlOffsets = nlOffsets;
+            this.textLength = textLength;
+            this.finalNL = finalNL;
+        }
+
+        /**
+         * Constructs map permitting translation between 0-based character offsets and 1-based
+         * lines/columns.
+         */
+        public static TextMap fromString(String text) {
+            final int textLength = text.length();
+            final ArrayList<Integer> lines = new ArrayList<>();
+            lines.add(0);
+            int offset = 0;
+
+            while (offset < text.length()) {
+                final int nlIndex = text.indexOf('\n', offset);
+                if (nlIndex >= 0) {
+                    offset = nlIndex + 1;
+                    lines.add(offset);
+                } else {
+                    break;
+                }
+            }
+            lines.add(Integer.MAX_VALUE);
+
+            final int[] nlOffsets = new int[lines.size()];
+            for (int line = 0; line < lines.size(); line++) {
+                nlOffsets[line] = lines.get(line);
+            }
+
+            final boolean finalNL = textLength > 0 && (textLength == nlOffsets[nlOffsets.length - 2]);
+
+            return new TextMap(nlOffsets, textLength, finalNL);
+        }
+
+        public static TextMap fromBytes(byte[] bytes, int byteIndex, int length, BytesDecoder bytesDecoder) {
+            final ArrayList<Integer> lines = new ArrayList<>();
+            lines.add(0);
+
+            bytesDecoder.decodeLines(bytes, byteIndex, length, new BytesDecoder.LineMarker() {
+
+                public void markLine(int index) {
+                    lines.add(index);
+                }
+            });
+
+            lines.add(Integer.MAX_VALUE);
+
+            final int[] nlOffsets = new int[lines.size()];
+            for (int line = 0; line < lines.size(); line++) {
+                nlOffsets[line] = lines.get(line);
+            }
+
+            final boolean finalNL = length > 0 && (length == nlOffsets[nlOffsets.length - 2]);
+
+            return new TextMap(nlOffsets, length, finalNL);
+        }
+
+        /**
+         * Converts 0-based character offset to 1-based number of the line containing the character.
+         *
+         * @throws IllegalArgumentException if the offset is outside the string.
+         */
+        public int offsetToLine(int offset) throws IllegalArgumentException {
+            if (offset < 0 || offset >= textLength) {
+                throw new IllegalArgumentException("offset out of bounds");
+            }
+            int line = 1;
+            while (offset >= nlOffsets[line]) {
+                line++;
+            }
+            return line;
+        }
+
+        /**
+         * Converts 0-based character offset to 1-based number of the column occupied by the
+         * character.
+         * <p>
+         * Tabs are not expanded; they occupy 1 column.
+         *
+         * @throws IllegalArgumentException if the offset is outside the string.
+         */
+        public int offsetToCol(int offset) throws IllegalArgumentException {
+            return 1 + offset - nlOffsets[offsetToLine(offset) - 1];
+        }
+
+        /**
+         * The number of characters in the mapped text.
+         */
+        public int length() {
+            return textLength;
+        }
+
+        /**
+         * The number of lines in the text; if characters appear after the final newline, then they
+         * also count as a line, even though not newline-terminated.
+         */
+        public int lineCount() {
+            if (textLength == 0) {
+                return 0;
+            }
+            return finalNL ? nlOffsets.length - 2 : nlOffsets.length - 1;
+        }
+
+        /**
+         * Converts 1-based line number to the 0-based offset of the line's first character; this
+         * would be the offset of a newline if the line is empty.
+         *
+         * @throws IllegalArgumentException if there is no such line in the text.
+         */
+        public int lineStartOffset(int line) throws IllegalArgumentException {
+            if (textLength == 0 || lineOutOfRange(line)) {
+                throw new IllegalArgumentException("line out of bounds");
+            }
+            return nlOffsets[line - 1];
+        }
+
+        /**
+         * Gets the number of characters in a line, identified by 1-based line number;
+         * <em>does not</em> include the final newline, if any.
+         *
+         * @throws IllegalArgumentException if there is no such line in the text.
+         */
+        public int lineLength(int line) throws IllegalArgumentException {
+            if (textLength == 0 || lineOutOfRange(line)) {
+                throw new IllegalArgumentException("line out of bounds");
+            }
+            if (line == nlOffsets.length - 1 && !finalNL) {
+                return textLength - nlOffsets[line - 1];
+            }
+            return (nlOffsets[line] - nlOffsets[line - 1]) - 1;
+
+        }
+
+        /**
+         * Is the line number out of range.
+         */
+        private boolean lineOutOfRange(int line) {
+            return line <= 0 || line >= nlOffsets.length || (line == nlOffsets.length - 1 && finalNL);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+/**
+ * An observer of events related to {@link Source}s: creating and tagging.
+ */
+public interface SourceListener {
+
+    /**
+     * Notifies that a new {@link Source} has just been created.
+     */
+    void sourceCreated(Source source);
+
+    /**
+     * Notifies that a {@link SourceTag} has been newly added to the set of tags associated with a
+     * {@link Source} via {@link Source#tagAs(SourceTag)}.
+     * <p>
+     * The {@linkplain SourceTag tags} at a {@link Source} are a <em>set</em>; this notification
+     * will only be delivered the first time a particular {@linkplain SourceTag tag} is added at a
+     * {@link Source}.
+     *
+     * @param source where a tag has been added
+     * @param tag the tag that has been newly added (subsequent additions of the tag are
+     *            unreported).
+     */
+    void sourceTaggedAs(Source source, SourceTag tag);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceSection.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+/**
+ * Description of contiguous section of text within a {@link Source} of program code; supports
+ * multiple modes of access to the text and its location. A special {@linkplain NullSourceSection
+ * null subtype} should be used for code that is not available from source, e.g language builtins.
+ *
+ * @see Source#createSection(String, int, int, int, int)
+ * @see Source#createSection(String, int, int, int)
+ * @see Source#createSection(String, int, int)
+ * @see Source#createSection(String, int)
+ * @see NullSourceSection
+ */
+public interface SourceSection {
+
+    // TODO support alternate text representations/encodings
+
+    /**
+     * Representation of the source program that contains this section.
+     *
+     * @return the source object
+     */
+    Source getSource();
+
+    /**
+     * Returns 1-based line number of the first character in this section (inclusive).
+     *
+     * @return the starting line number
+     */
+    int getStartLine();
+
+    /**
+     * Gets a representation of the first line of the section, suitable for a hash key.
+     */
+    LineLocation getLineLocation();
+
+    /**
+     * Returns the 1-based column number of the first character in this section (inclusive).
+     *
+     * @return the starting column number
+     */
+    int getStartColumn();
+
+    /**
+     * Returns 1-based line number of the last character in this section (inclusive).
+     *
+     * @return the starting line number
+     */
+    int getEndLine();
+
+    /**
+     * Returns the 1-based column number of the last character in this section (inclusive).
+     *
+     * @return the starting column number
+     */
+    int getEndColumn();
+
+    /**
+     * Returns the 0-based index of the first character in this section.
+     *
+     * @return the starting character index
+     */
+    int getCharIndex();
+
+    /**
+     * Returns the length of this section in characters.
+     *
+     * @return the number of characters in the section
+     */
+    int getCharLength();
+
+    /**
+     * Returns the index of the text position immediately following the last character in the
+     * section.
+     *
+     * @return the end position of the section
+     */
+    int getCharEndIndex();
+
+    /**
+     * Returns terse text describing this source section, typically used for printing the section.
+     *
+     * @return the identifier of the section
+     */
+    String getIdentifier();
+
+    /**
+     * Returns text described by this section.
+     *
+     * @return the code as a String object
+     */
+    String getCode();
+
+    /**
+     * Returns a short description of the source section, using just the file name, rather than its
+     * full path.
+     *
+     * @return a short description of the source section
+     */
+    String getShortDescription();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/SourceTag.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.source;
+
+/**
+ * Categorical information (best implemented as enums} about particular sources of Guest Language
+ * code that can be useful to configure behavior of both the language runtime and external tools.
+ * These might include {@linkplain Source.Tags standard tags} noting, for example, whether the
+ * source was read from a file and whether it should be considered library code.
+ * <p>
+ * The need for additional tags is likely to arise, in some cases because of issue specific to a
+ * Guest Language, but also for help configuring the behavior of particular tools.
+ *
+ * @see Source
+ * @see Source.Tags
+ */
+public interface SourceTag {
+
+    /**
+     * Human-friendly name of a category of code sources, e.g. "file", or "library".
+     *
+     */
+    String name();
+
+    /**
+     * Criteria and example uses for the tag.
+     */
+    String getDescription();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccess.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.unsafe;
+
+public interface UnsafeAccess {
+
+    /**
+     * Casts the given value to the value of the given type without any checks. The class must
+     * evaluate to a constant. The condition parameter gives a hint to the compiler under which
+     * circumstances this cast can be moved to an earlier location in the program.
+     *
+     * @param value the value that is known to have the specified type
+     * @param type the specified new type of the value
+     * @param condition the condition that makes this cast safe also at an earlier location of the
+     *            program
+     * @param nonNull whether value is known to never be null
+     * @return the value to be casted to the new type
+     */
+    <T> T uncheckedCast(Object value, Class<T> type, boolean condition, boolean nonNull);
+
+    /**
+     * Unsafe access to a boolean value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    boolean getBoolean(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to a byte value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    byte getByte(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to a short value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    short getShort(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to an int value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    int getInt(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to a long value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    long getLong(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to a float value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    float getFloat(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to a double value within an object. The condition parameter gives a hint to the
+     * compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    double getDouble(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Unsafe access to an Object value within an object. The condition parameter gives a hint to
+     * the compiler under which circumstances this access can be moved to an earlier location in the
+     * program. The location identity gives a hint to the compiler for improved global value
+     * numbering.
+     *
+     * @param receiver the object that is accessed
+     * @param offset the offset at which to access the object in bytes
+     * @param condition the condition that makes this access safe also at an earlier location in the
+     *            program
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     * @return the accessed value
+     */
+    Object getObject(Object receiver, long offset, boolean condition, Object locationIdentity);
+
+    /**
+     * Write a boolean value within an object. The location identity gives a hint to the compiler
+     * for improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putBoolean(Object receiver, long offset, boolean value, Object locationIdentity);
+
+    /**
+     * Write a byte value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putByte(Object receiver, long offset, byte value, Object locationIdentity);
+
+    /**
+     * Write a short value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putShort(Object receiver, long offset, short value, Object locationIdentity);
+
+    /**
+     * Write an int value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putInt(Object receiver, long offset, int value, Object locationIdentity);
+
+    /**
+     * Write a long value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putLong(Object receiver, long offset, long value, Object locationIdentity);
+
+    /**
+     * Write a float value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putFloat(Object receiver, long offset, float value, Object locationIdentity);
+
+    /**
+     * Write a double value within an object. The location identity gives a hint to the compiler for
+     * improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putDouble(Object receiver, long offset, double value, Object locationIdentity);
+
+    /**
+     * Write an Object value within an object. The location identity gives a hint to the compiler
+     * for improved global value numbering.
+     *
+     * @param receiver the object that is written to
+     * @param offset the offset at which to write to the object in bytes
+     * @param value the value to be written
+     * @param locationIdentity the location identity token that can be used for improved global
+     *            value numbering or null
+     */
+    void putObject(Object receiver, long offset, Object value, Object locationIdentity);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/unsafe/UnsafeAccessFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.unsafe;
+
+import sun.misc.*;
+
+public interface UnsafeAccessFactory {
+    UnsafeAccess createUnsafeAccess(Unsafe unsafe);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AlwaysValidAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption that is always valid. Used as a placeholder where an assumption is needed but never
+ * invalidated.
+ */
+public final class AlwaysValidAssumption implements Assumption {
+
+    public static final AlwaysValidAssumption INSTANCE = new AlwaysValidAssumption();
+
+    private AlwaysValidAssumption() {
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+    }
+
+    @Override
+    public void invalidate() {
+        throw new UnsupportedOperationException("Cannot invalidate this assumption - it is always valid");
+    }
+
+    @Override
+    public String getName() {
+        return getClass().getName();
+    }
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/AssumedValue.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A value that the compiler can assume is constant, but can be changed by invalidation.
+ * <p>
+ * Compiled code that uses the value will be invalidated each time the value changes, so you should
+ * take care to only change values infrequently, or to monitor the number of times the value has
+ * changed and at some point to replace the value with something more generic so that it does not
+ * have to be changed and code does not have to keep being recompiled.
+ */
+public class AssumedValue<T> {
+
+    private final String name;
+
+    @CompilationFinal private T value;
+    @CompilationFinal private Assumption assumption;
+
+    public AssumedValue(T initialValue) {
+        this(null, initialValue);
+    }
+
+    public AssumedValue(String name, T initialValue) {
+        this.name = name;
+        value = initialValue;
+        assumption = Truffle.getRuntime().createAssumption(name);
+    }
+
+    /**
+     * Get the current value, updating it if it has been {@link #set}. The compiler may be able to
+     * make this method return a constant value, but still accommodate mutation.
+     */
+    public T get() {
+        try {
+            assumption.check();
+        } catch (InvalidAssumptionException e) {
+            // No need to rewrite anything - just pick up the new values
+        }
+
+        return value;
+    }
+
+    /**
+     * Set a new value, which will be picked up the next time {@link #get} is called.
+     */
+    public void set(T newValue) {
+        CompilerDirectives.transferToInterpreter();
+
+        value = newValue;
+        final Assumption oldAssumption = assumption;
+        assumption = Truffle.getRuntime().createAssumption(name);
+        oldAssumption.invalidate();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Utility class to speculate on conditions to be never true or to be never false. Condition
+ * profiles are intended to be used as part of if conditions.
+ *
+ * @see ConditionProfile#createBinaryProfile()
+ */
+public final class BinaryConditionProfile extends ConditionProfile {
+
+    @CompilationFinal private boolean wasTrue;
+    @CompilationFinal private boolean wasFalse;
+
+    BinaryConditionProfile() {
+        /* package protected constructor */
+    }
+
+    @Override
+    public boolean profile(boolean value) {
+        if (value) {
+            if (!wasTrue) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                wasTrue = true;
+            }
+            return true;
+        } else {
+            if (!wasFalse) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                wasFalse = true;
+            }
+            return false;
+        }
+    }
+
+    public boolean wasTrue() {
+        return wasTrue;
+    }
+
+    public boolean wasFalse() {
+        return wasFalse;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Utility class to speculate on branches to be never visited. If the {@link #enter()} method is
+ * invoked first the optimized code is invalidated and the branch where {@link #enter()} is invoked
+ * is enabled for compilation. Otherwise if the {@link #enter()} method was never invoked the branch
+ * will not get compiled.
+ *
+ * All {@code BranchProfile} instances must be held in {@code final} fields for compiler
+ * optimizations to take effect.
+ */
+public final class BranchProfile extends NodeCloneable {
+
+    @CompilationFinal private boolean visited;
+
+    private BranchProfile() {
+    }
+
+    public void enter() {
+        if (!visited) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            visited = true;
+        }
+    }
+
+    public boolean isVisited() {
+        return visited;
+    }
+
+    public static BranchProfile create() {
+        return new BranchProfile();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), visited ? "visited" : "not-visited", hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as
+ * part of if conditions.
+ *
+ * Example usage:
+ *
+ * <pre>
+ * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
+ *
+ * int value = ...;
+ * if (zero.profile(value == 0)) {
+ *   return 0;
+ * } else {
+ *   return value;
+ * }
+ *
+ * </pre>
+ *
+ * All instances of {@code ConditionProfile} (and subclasses) must be held in {@code final} fields
+ * for compiler optimizations to take effect.
+ *
+ * @see #createCountingProfile()
+ * @see #createBinaryProfile()
+ */
+public abstract class ConditionProfile extends NodeCloneable {
+    ConditionProfile() {
+    }
+
+    public abstract boolean profile(boolean value);
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never
+     * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
+     * method returns a condition profile that also counts the number of times the condition was
+     * true and false. This information is reported to the underlying optimization system using
+     * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
+     * intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see #createBinaryProfile()
+     */
+    public static ConditionProfile createCountingProfile() {
+        return new CountingConditionProfile();
+    }
+
+    /**
+     * Returns a {@link ConditionProfile} that speculates on conditions to be never true or to be
+     * never false. Condition profiles are intended to be used as part of if conditions.
+     *
+     * @see ConditionProfile
+     * @see ConditionProfile#createCountingProfile()
+     */
+    public static ConditionProfile createBinaryProfile() {
+        return new BinaryConditionProfile();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Utility class to speculate on conditions to be never true or to be never false. Additionally to
+ * {@link BinaryConditionProfile} this implementation of {@link ConditionProfile} also counts the
+ * number of times the condition was true and false. This information is reported to the underlying
+ * optimization system using {@link CompilerDirectives#injectBranchProbability(double, boolean)}.
+ * Condition profiles are intended to be used as part of if conditions.
+ *
+ * @see ConditionProfile#createCountingProfile()
+ */
+public final class CountingConditionProfile extends ConditionProfile {
+
+    @CompilationFinal private int trueCount;
+    @CompilationFinal private int falseCount;
+
+    CountingConditionProfile() {
+        /* package protected constructor */
+    }
+
+    @Override
+    public boolean profile(boolean value) {
+        if (value) {
+            if (trueCount == 0) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+            }
+            if (CompilerDirectives.inInterpreter()) {
+                trueCount++;
+            }
+        } else {
+            if (falseCount == 0) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+            }
+            if (CompilerDirectives.inInterpreter()) {
+                falseCount++;
+            }
+        }
+        return CompilerDirectives.injectBranchProbability((double) trueCount / (double) (trueCount + falseCount), value);
+    }
+
+    public int getTrueCount() {
+        return trueCount;
+    }
+
+    public int getFalseCount() {
+        return falseCount;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(trueCount=%s, falseCount=%s)@%x", getClass().getSimpleName(), trueCount, falseCount, hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CyclicAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import java.util.concurrent.atomic.*;
+
+import com.oracle.truffle.api.*;
+
+/**
+ * Holds an {@link Assumption}, and knows how to recreate it with the same properties on
+ * invalidation. Used so that mutability is isolated in this class, and all other classes that need
+ * an assumption that may be recreated can have a final reference to an object of this class. Note
+ * that you should be careful that repeated invalidations do not cause a deoptimization loop in that
+ * same way that you would with any other assumption.
+ */
+public class CyclicAssumption {
+
+    private final String name;
+    private final AtomicReference<Assumption> assumption;
+
+    public CyclicAssumption(String name) {
+        this.name = name;
+        this.assumption = new AtomicReference<>(Truffle.getRuntime().createAssumption(name));
+    }
+
+    public void invalidate() {
+        Assumption newAssumption = Truffle.getRuntime().createAssumption(name);
+        Assumption oldAssumption = assumption.getAndSet(newAssumption);
+        oldAssumption.invalidate();
+    }
+
+    public Assumption getAssumption() {
+        return assumption.get();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ExactClassValueProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Represents a {@link ValueProfile} that speculates on the exact class of a value.
+ */
+public final class ExactClassValueProfile extends ValueProfile {
+
+    @CompilationFinal protected Class<?> cachedClass;
+
+    ExactClassValueProfile() {
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T profile(T value) {
+        if (cachedClass != Object.class) {
+            if (cachedClass != null && cachedClass.isInstance(value)) {
+                return (T) cachedClass.cast(value);
+            } else {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (cachedClass == null && value != null) {
+                    cachedClass = value.getClass();
+                } else {
+                    cachedClass = Object.class;
+                }
+            }
+        }
+        return value;
+    }
+
+    public boolean isGeneric() {
+        return cachedClass == Object.class;
+    }
+
+    public boolean isUninitialized() {
+        return cachedClass == null;
+    }
+
+    public Class<?> getCachedClass() {
+        return cachedClass;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : cachedClass.getName()), hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IdentityValueProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Represents a {@link ValueProfile} that speculates on the object identity of a value.
+ */
+public final class IdentityValueProfile extends ValueProfile {
+
+    private static final Object UNINITIALIZED = new Object();
+    private static final Object GENERIC = new Object();
+
+    @CompilationFinal protected Object cachedValue = UNINITIALIZED;
+
+    IdentityValueProfile() {
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> T profile(T value) {
+        if (cachedValue != GENERIC) {
+            if (cachedValue == value) {
+                return (T) cachedValue;
+            } else {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                if (cachedValue == UNINITIALIZED) {
+                    cachedValue = value;
+                } else {
+                    cachedValue = GENERIC;
+                }
+            }
+        }
+        return value;
+    }
+
+    public boolean isGeneric() {
+        return getCachedValue() == GENERIC;
+    }
+
+    public boolean isUninitialized() {
+        return getCachedValue() == UNINITIALIZED;
+    }
+
+    public Object getCachedValue() {
+        return cachedValue;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), isUninitialized() ? "uninitialized" : (isGeneric() ? "generic" : String.format("@%x", Objects.hash(cachedValue))), hashCode());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/JSONHelper.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Helper function that allows to dump the AST during creation to a JSON format.
+ */
+public class JSONHelper {
+
+    private static StringBuilder AstJsonDumpBuilder = new StringBuilder();
+
+    public static void dumpNewChild(Node parentNode, Node childNode) {
+        if (AstJsonDumpBuilder != null) {
+            AstJsonDumpBuilder.append("{ \"action\": \"insertNode\", \"parentId\": \"" + getID(parentNode) + "\", \"newId\": \"" + getID(childNode) + "\" },\n");
+        }
+    }
+
+    public static void dumpReplaceChild(Node oldNode, Node newNode, CharSequence reason) {
+        if (AstJsonDumpBuilder != null) {
+            AstJsonDumpBuilder.append("{ \"action\": \"replaceNode\", \"oldId\": \"" + getID(oldNode) + "\", \"newId\": \"" + getID(newNode) + "\", \"reason\": " + quote(reason) + " },\n");
+        }
+    }
+
+    public static void dumpNewNode(Node newNode) {
+        if (AstJsonDumpBuilder != null) {
+            AstJsonDumpBuilder.append("{ \"action\": \"createNode\", \"newId\": \"" + getID(newNode) + "\", \"type\": \"" + getType(newNode) + "\", \"description\": \"" + newNode.getDescription() +
+                            "\", \"language\": \"" + newNode.getLanguage() + "\"" + getSourceSectionInfo(newNode) + " },\n");
+        }
+    }
+
+    private static String getSourceSectionInfo(Node newNode) {
+        SourceSection sourceSection = newNode.getSourceSection();
+        if (sourceSection != null) {
+            return ", \"identifier\": \"" + sourceSection.getIdentifier() + "\" ";
+        } else {
+            return "";
+        }
+    }
+
+    public static String getResult() {
+        return AstJsonDumpBuilder.toString();
+    }
+
+    private static String getID(Node newChild) {
+        return String.valueOf(newChild.hashCode());
+    }
+
+    private static String getType(Node node) {
+        return node.getClass().getSimpleName();
+    }
+
+    private static String quote(CharSequence value) {
+        StringBuilder builder = new StringBuilder(value.length() + 2);
+        builder.append('"');
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            switch (c) {
+                case '"':
+                    builder.append("\\\"");
+                    break;
+                case '\\':
+                    builder.append("\\\\");
+                    break;
+                case '\b':
+                    builder.append("\\b");
+                    break;
+                case '\f':
+                    builder.append("\\f");
+                    break;
+                case '\n':
+                    builder.append("\\n");
+                    break;
+                case '\r':
+                    builder.append("\\r");
+                    break;
+                case '\t':
+                    builder.append("\\t");
+                    break;
+                default: {
+                    if (c < ' ') {
+                        builder.append("\\u00");
+                        builder.append(Character.forDigit((c >> 4) & 0xF, 16));
+                        builder.append(Character.forDigit(c & 0xF, 16));
+                    } else {
+                        builder.append(c);
+                    }
+                }
+            }
+        }
+        builder.append('"');
+        return builder.toString();
+    }
+
+    public static void restart() {
+        AstJsonDumpBuilder = new StringBuilder();
+    }
+
+    public static JSONObjectBuilder object() {
+        return new JSONObjectBuilder();
+    }
+
+    public static JSONArrayBuilder array() {
+        return new JSONArrayBuilder();
+    }
+
+    public abstract static class JSONStringBuilder {
+        @Override
+        public final String toString() {
+            StringBuilder sb = new StringBuilder();
+            appendTo(sb);
+            return sb.toString();
+        }
+
+        protected abstract void appendTo(StringBuilder sb);
+
+        protected static void appendValue(StringBuilder sb, Object value) {
+            if (value instanceof JSONStringBuilder) {
+                ((JSONStringBuilder) value).appendTo(sb);
+            } else if (value instanceof Integer || value instanceof Boolean || value == null) {
+                sb.append(value);
+            } else {
+                sb.append(quote(String.valueOf(value)));
+            }
+        }
+    }
+
+    public static final class JSONObjectBuilder extends JSONStringBuilder {
+        private final Map<String, Object> contents = new LinkedHashMap<>();
+
+        private JSONObjectBuilder() {
+        }
+
+        public JSONObjectBuilder add(String key, String value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JSONObjectBuilder add(String key, Number value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JSONObjectBuilder add(String key, Boolean value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        public JSONObjectBuilder add(String key, JSONStringBuilder value) {
+            contents.put(key, value);
+            return this;
+        }
+
+        @Override
+        protected void appendTo(StringBuilder sb) {
+            sb.append("{");
+            boolean comma = false;
+            for (Map.Entry<String, Object> entry : contents.entrySet()) {
+                if (comma) {
+                    sb.append(", ");
+                }
+                sb.append(quote(entry.getKey()));
+                sb.append(": ");
+                appendValue(sb, entry.getValue());
+                comma = true;
+            }
+            sb.append("}");
+        }
+    }
+
+    public static final class JSONArrayBuilder extends JSONStringBuilder {
+        private final List<Object> contents = new ArrayList<>();
+
+        private JSONArrayBuilder() {
+        }
+
+        public JSONArrayBuilder add(String value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JSONArrayBuilder add(Number value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JSONArrayBuilder add(Boolean value) {
+            contents.add(value);
+            return this;
+        }
+
+        public JSONArrayBuilder add(JSONStringBuilder value) {
+            contents.add(value);
+            return this;
+        }
+
+        @Override
+        protected void appendTo(StringBuilder sb) {
+            sb.append("[");
+            boolean comma = false;
+            for (Object value : contents) {
+                if (comma) {
+                    sb.append(", ");
+                }
+                appendValue(sb, value);
+                comma = true;
+            }
+            sb.append("]");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/NeverValidAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption that is never valid. Used as a placeholder where an assumption is needed that
+ * should be invalid from the start.
+ */
+public final class NeverValidAssumption implements Assumption {
+
+    public static final NeverValidAssumption INSTANCE = new NeverValidAssumption();
+
+    private NeverValidAssumption() {
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        throw new InvalidAssumptionException();
+    }
+
+    @Override
+    public void invalidate() {
+    }
+
+    @Override
+    public String getName() {
+        return getClass().getName();
+    }
+
+    @Override
+    public boolean isValid() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+
+/**
+ * Represents a {@link ValueProfile} that speculates on the primitive equality or object identity of
+ * values.
+ * <p>
+ * Note that for {@code float} and {@code double} values we compare primitive equality via
+ * {@link Float#floatToRawIntBits} and {@link Double#doubleToRawLongBits}, so that for example
+ * {@code -0.0} is not considered the same as {@code 0.0}, even though primitive equality would
+ * normally say that it was.
+ */
+public class PrimitiveValueProfile extends ValueProfile {
+
+    private static final Object UNINITIALIZED = new Object();
+    private static final Object GENERIC = new Object();
+
+    @CompilationFinal private Object cachedValue = UNINITIALIZED;
+
+    PrimitiveValueProfile() {
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object profile(Object value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Byte) {
+                if (value instanceof Byte && (byte) snapshot == (byte) value) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Short) {
+                if (value instanceof Short && (short) snapshot == (short) value) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Integer) {
+                if (value instanceof Integer && (int) snapshot == (int) value) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Long) {
+                if (value instanceof Long && (long) snapshot == (long) value) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Float) {
+                if (value instanceof Float && exactCompare((float) snapshot, (float) value)) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Double) {
+                if (value instanceof Double && exactCompare((double) snapshot, (double) value)) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Boolean) {
+                if (value instanceof Boolean && (boolean) snapshot == (boolean) value) {
+                    return snapshot;
+                }
+            } else if (snapshot instanceof Character) {
+                if (value instanceof Character && (char) snapshot == (char) value) {
+                    return snapshot;
+                }
+            } else if (snapshot == value) {
+                return snapshot;
+            }
+            cacheMiss(value);
+        }
+        return value;
+    }
+
+    public byte profile(byte value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Byte && (byte) snapshot == value) {
+                return (byte) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public short profile(short value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Short && (short) snapshot == value) {
+                return (short) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public int profile(int value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Integer && (int) snapshot == value) {
+                return (int) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public long profile(long value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Long && (long) snapshot == value) {
+                return (long) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public float profile(float value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Float && exactCompare((float) snapshot, value)) {
+                return (float) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public double profile(double value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Double && exactCompare((double) snapshot, value)) {
+                return (double) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public boolean profile(boolean value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Boolean && (boolean) snapshot == value) {
+                return (boolean) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public char profile(char value) {
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Character && (char) snapshot == value) {
+                return (char) snapshot;
+            } else {
+                cacheMiss(value);
+            }
+        }
+        return value;
+    }
+
+    public boolean isGeneric() {
+        return cachedValue == GENERIC;
+    }
+
+    public boolean isUninitialized() {
+        return cachedValue == UNINITIALIZED;
+    }
+
+    public Object getCachedValue() {
+        return cachedValue;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s(%s)@%x", getClass().getSimpleName(), formatValue(), hashCode());
+    }
+
+    private void cacheMiss(Object value) {
+        // TODO should we try to handle this more atomically?
+        CompilerDirectives.transferToInterpreterAndInvalidate();
+        if (cachedValue == UNINITIALIZED) {
+            cachedValue = value;
+        } else {
+            cachedValue = GENERIC;
+        }
+    }
+
+    public static boolean exactCompare(float a, float b) {
+        /*
+         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
+         * differentiate.
+         */
+        return Float.floatToRawIntBits(a) == Float.floatToRawIntBits(b);
+    }
+
+    public static boolean exactCompare(double a, double b) {
+        /*
+         * -0.0 == 0.0, but you can tell the difference through other means, so we need to
+         * differentiate.
+         */
+        return Double.doubleToRawLongBits(a) == Double.doubleToRawLongBits(b);
+    }
+
+    private String formatValue() {
+        Object snapshot = this.cachedValue;
+        if (snapshot == null) {
+            return "null";
+        } else if (snapshot == UNINITIALIZED) {
+            return "uninitialized";
+        } else if (snapshot == GENERIC) {
+            return "generic";
+        } else if (snapshot instanceof Byte || snapshot instanceof Short || snapshot instanceof Integer || snapshot instanceof Long || snapshot instanceof Float || snapshot instanceof Double ||
+                        snapshot instanceof Boolean || snapshot instanceof Character) {
+            return String.format("%s=%s", snapshot.getClass().getSimpleName(), snapshot);
+        } else {
+            return String.format("%s@%x", snapshot.getClass().getSimpleName(), Objects.hash(snapshot));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/UnionAssumption.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * An assumption that combines two other assumptions. A check on this assumption checks both of the
+ * child assumptions.
+ */
+public class UnionAssumption implements Assumption {
+
+    private final String name;
+    private final Assumption first;
+    private final Assumption second;
+
+    public UnionAssumption(String name, Assumption first, Assumption second) {
+        this.name = name;
+        this.first = first;
+        this.second = second;
+    }
+
+    public UnionAssumption(Assumption first, Assumption second) {
+        this(null, first, second);
+    }
+
+    @Override
+    public void check() throws InvalidAssumptionException {
+        first.check();
+        second.check();
+    }
+
+    @Override
+    public void invalidate() {
+        first.invalidate();
+        second.invalidate();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public boolean isValid() {
+        return first.isValid() && second.isValid();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.utilities;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Utility class to speculate on certain properties of values.
+ *
+ * Example usage:
+ *
+ * <pre>
+ * private final ValueProfile classProfile = ValueProfile.createClassProfile();
+ *
+ * return classProfile.profile(value);
+ * </pre>
+ *
+ * All instances of {@code ValueProfile} (and subclasses) must be held in {@code final} fields for
+ * compiler optimizations to take effect.
+ *
+ * @see #createPrimitiveProfile()
+ * @see #createIdentityProfile()
+ * @see #createClassProfile()
+ */
+public abstract class ValueProfile extends NodeCloneable {
+
+    public abstract <T> T profile(T value);
+
+    /**
+     * Returns a {@link PrimitiveValueProfile} that speculates on the primitive equality or object
+     * identity of a value.
+     */
+    public static PrimitiveValueProfile createPrimitiveProfile() {
+        return new PrimitiveValueProfile();
+    }
+
+    /**
+     * Returns a {@link ValueProfile} that speculates on the exact class of a value.
+     */
+    public static ValueProfile createClassProfile() {
+        return new ExactClassValueProfile();
+    }
+
+    /**
+     * Returns a {@link ValueProfile} that speculates on the object identity of a value.
+     */
+    public static ValueProfile createIdentityProfile() {
+        return new IdentityValueProfile();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.vm;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.*;
+import java.util.logging.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.TruffleLanguage.Env;
+import com.oracle.truffle.api.TruffleLanguage.Registration;
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Virtual machine for Truffle based languages. Use {@link #newVM()} to create new isolated virtual
+ * machine ready for execution of various languages. All the languages in a single virtual machine
+ * see each other exported global symbols and can cooperate. Use {@link #newVM()} multiple times to
+ * create different, isolated virtual machines completely separated from each other.
+ * <p>
+ * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly
+ * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}.
+ * Support for individual languages is initialized on demand - e.g. once a file of certain MIME type
+ * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets
+ * initialized, it remains so, until the virtual machine isn't garbage collected.
+ * <p>
+ * The <code>TruffleVM</code> is single-threaded and tries to enforce that. It records the thread it
+ * has been {@link Builder#build() created} by and checks that all subsequent calls are coming from
+ * the same thread.
+ */
+public final class TruffleVM {
+    private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName());
+    private static final SPIAccessor SPI = new SPIAccessor();
+    private final Thread initThread;
+    private final Map<String, Language> langs;
+    private final Reader in;
+    private final Writer err;
+    private final Writer out;
+
+    /**
+     * Private & temporary only constructor.
+     */
+    private TruffleVM() {
+        this.initThread = null;
+        this.in = null;
+        this.err = null;
+        this.out = null;
+        this.langs = null;
+    }
+
+    /**
+     * Real constructor used from the builder.
+     *
+     * @param out stdout
+     * @param err stderr
+     * @param in stdin
+     */
+    private TruffleVM(Writer out, Writer err, Reader in) {
+        this.out = out;
+        this.err = err;
+        this.in = in;
+        this.initThread = Thread.currentThread();
+        this.langs = new HashMap<>();
+        Enumeration<URL> en;
+        try {
+            en = loader().getResources("META-INF/truffle/language");
+        } catch (IOException ex) {
+            throw new IllegalStateException("Cannot read list of Truffle languages", ex);
+        }
+        while (en.hasMoreElements()) {
+            URL u = en.nextElement();
+            Properties p;
+            try {
+                p = new Properties();
+                try (InputStream is = u.openStream()) {
+                    p.load(is);
+                }
+            } catch (IOException ex) {
+                LOG.log(Level.CONFIG, "Cannot process " + u + " as language definition", ex);
+                continue;
+            }
+            for (int cnt = 1;; cnt++) {
+                String prefix = "language" + cnt + ".";
+                if (p.getProperty(prefix + "name") == null) {
+                    break;
+                }
+                Language l = new Language(prefix, p);
+                for (String mimeType : l.getMimeTypes()) {
+                    langs.put(mimeType, l);
+                }
+            }
+        }
+    }
+
+    static ClassLoader loader() {
+        ClassLoader l = TruffleVM.class.getClassLoader();
+        if (l == null) {
+            l = ClassLoader.getSystemClassLoader();
+        }
+        return l;
+    }
+
+    /**
+     * Creation of new Truffle virtual machine. Use the {@link Builder} methods to configure your
+     * virtual machine and then create one using {@link Builder#build()}:
+     *
+     * <pre>
+     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
+     *     .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
+     *     .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
+     *     .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
+     *     .{@link Builder#build() build()};
+     * </pre>
+     *
+     * It searches for {@link Registration languages registered} in the system class loader and
+     * makes them available for later evaluation via
+     * {@link #eval(java.lang.String, java.lang.String)} methods.
+     *
+     * @return new, isolated virtual machine with pre-registered languages
+     */
+    public static TruffleVM.Builder newVM() {
+        // making Builder non-static inner class is a
+        // nasty trick to avoid the Builder class to appear
+        // in Javadoc next to TruffleVM class
+        TruffleVM vm = new TruffleVM();
+        return vm.new Builder();
+    }
+
+    /**
+     * Builder for a new {@link TruffleVM}. Call various configuration methods in a chain and at the
+     * end create new {@link TruffleVM virtual machine}:
+     *
+     * <pre>
+     * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
+     *     .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
+     *     .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
+     *     .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
+     *     .{@link Builder#build() build()};
+     * </pre>
+     */
+    public final class Builder {
+        private Writer out;
+        private Writer err;
+        private Reader in;
+
+        Builder() {
+        }
+
+        /**
+         * Changes the defaut output for languages running in <em>to be created</em>
+         * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
+         *
+         * @param w the writer to use as output
+         * @return instance of this builder
+         */
+        public Builder stdOut(Writer w) {
+            out = w;
+            return this;
+        }
+
+        /**
+         * Changes the error output for languages running in <em>to be created</em>
+         * {@link TruffleVM virtual machine}. The default is to use {@link System#err}.
+         *
+         * @param w the writer to use as output
+         * @return instance of this builder
+         */
+        public Builder stdErr(Writer w) {
+            err = w;
+            return this;
+        }
+
+        /**
+         * Changes the default input for languages running in <em>to be created</em>
+         * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
+         *
+         * @param r the reader to use as input
+         * @return instance of this builder
+         */
+        public Builder stdIn(Reader r) {
+            in = r;
+            return this;
+        }
+
+        /**
+         * Creates the {@link TruffleVM Truffle virtual machine}. The configuration is taken from
+         * values passed into configuration methods in this class.
+         *
+         * @return new, isolated virtual machine with pre-registered languages
+         */
+        public TruffleVM build() {
+            if (out == null) {
+                out = new OutputStreamWriter(System.out);
+            }
+            if (err == null) {
+                err = new OutputStreamWriter(System.err);
+            }
+            if (in == null) {
+                in = new InputStreamReader(System.in);
+            }
+            return new TruffleVM(out, err, in);
+        }
+    }
+
+    /**
+     * Descriptions of languages supported in this Truffle virtual machine.
+     *
+     * @return an immutable map with keys being MIME types and values the {@link Language
+     *         descriptions} of associated languages
+     */
+    public Map<String, Language> getLanguages() {
+        return Collections.unmodifiableMap(langs);
+    }
+
+    /**
+     * Evaluates file located on a given URL. Is equivalent to loading the content of a file and
+     * executing it via {@link #eval(java.lang.String, java.lang.String)} with a MIME type guess
+     * based on the file's extension and/or content.
+     *
+     * @param location the location of a file to execute
+     * @return result of a processing the file, possibly <code>null</code>
+     * @throws IOException exception to signal I/O problems or problems with processing the file's
+     *             content
+     */
+    public Object eval(URI location) throws IOException {
+        checkThread();
+        Source s;
+        String mimeType;
+        if (location.getScheme().equals("file")) {
+            File file = new File(location);
+            s = Source.fromFileName(file.getPath(), true);
+            if (file.getName().endsWith(".c")) {
+                mimeType = "text/x-c";
+            } else if (file.getName().endsWith(".sl")) {
+                mimeType = "application/x-sl";
+            } else {
+                mimeType = Files.probeContentType(file.toPath());
+            }
+        } else {
+            URL url = location.toURL();
+            s = Source.fromURL(url, location.toString());
+            URLConnection conn = url.openConnection();
+            mimeType = conn.getContentType();
+        }
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for " + location + " with MIME type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, s);
+    }
+
+    /**
+     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
+     * {@link IOException} if there is none). And passes the specified code to it for execution.
+     *
+     * @param mimeType MIME type of the code snippet - chooses the right language
+     * @param reader the source of code snippet to execute
+     * @return result of an execution, possibly <code>null</code>
+     * @throws IOException thrown to signal errors while processing the code
+     */
+    public Object eval(String mimeType, Reader reader) throws IOException {
+        checkThread();
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, Source.fromReader(reader, mimeType));
+    }
+
+    /**
+     * Evaluates code snippet. Chooses a language registered for a given MIME type (throws
+     * {@link IOException} if there is none). And passes the specified code to it for execution.
+     *
+     * @param mimeType MIME type of the code snippet - chooses the right language
+     * @param code the code snippet to execute
+     * @return result of an execution, possibly <code>null</code>
+     * @throws IOException thrown to signal errors while processing the code
+     */
+    public Object eval(String mimeType, String code) throws IOException {
+        checkThread();
+        TruffleLanguage l = getTruffleLang(mimeType);
+        if (l == null) {
+            throw new IOException("No language for MIME type " + mimeType + " found. Supported types: " + langs.keySet());
+        }
+        return SPI.eval(l, Source.fromText(code, mimeType));
+    }
+
+    /**
+     * Looks global symbol provided by one of initialized languages up. First of all execute your
+     * program via one of your {@link #eval(java.lang.String, java.lang.String)} and then look
+     * expected symbol up using this method.
+     * <p>
+     * The names of the symbols are language dependent, but for example the Java language bindings
+     * follow the specification for method references:
+     * <ul>
+     * <li>"java.lang.Exception::new" is a reference to constructor of {@link Exception}
+     * <li>"java.lang.Integer::valueOf" is a reference to static method in {@link Integer} class
+     * </ul>
+     * Once an symbol is obtained, it remembers values for fast access and is ready for being
+     * invoked.
+     *
+     * @param globalName the name of the symbol to find
+     * @return found symbol or <code>null</code> if it has not been found
+     */
+    public Symbol findGlobalSymbol(String globalName) {
+        checkThread();
+        Object obj = null;
+        Object global = null;
+        for (Language dl : langs.values()) {
+            TruffleLanguage l = dl.getImpl();
+            obj = SPI.findExportedSymbol(l, globalName, true);
+            if (obj != null) {
+                global = SPI.languageGlobal(l);
+                break;
+            }
+        }
+        if (obj == null) {
+            for (Language dl : langs.values()) {
+                TruffleLanguage l = dl.getImpl();
+                obj = SPI.findExportedSymbol(l, globalName, false);
+                if (obj != null) {
+                    global = SPI.languageGlobal(l);
+                    break;
+                }
+            }
+        }
+        return obj == null ? null : new Symbol(obj, global);
+    }
+
+    private void checkThread() {
+        if (initThread != Thread.currentThread()) {
+            throw new IllegalStateException("TruffleVM created on " + initThread.getName() + " but used on " + Thread.currentThread().getName());
+        }
+    }
+
+    private TruffleLanguage getTruffleLang(String mimeType) {
+        checkThread();
+        Language l = langs.get(mimeType);
+        return l == null ? null : l.getImpl();
+    }
+
+    /**
+     * Represents {@link TruffleVM#findGlobalSymbol(java.lang.String) global symbol} provided by one
+     * of the initialized languages in {@link TruffleVM Truffle virtual machine}.
+     */
+    public class Symbol {
+        private final Object obj;
+        private final Object global;
+
+        Symbol(Object obj, Object global) {
+            this.obj = obj;
+            this.global = global;
+        }
+
+        /**
+         * Invokes the symbol. If the symbol represents a function, then it should be invoked with
+         * provided arguments. If the symbol represents a field, then first argument (if provided)
+         * should set the value to the field; the return value should be the actual value of the
+         * field when the <code>invoke</code> method returns.
+         *
+         * @param thiz this/self in language that support such concept; use <code>null</code> to let
+         *            the language use default this/self or ignore the value
+         * @param args arguments to pass when invoking the symbol
+         * @return the value returned by invoking the symbol
+         * @throws IOException signals problem during execution
+         */
+        public Object invoke(Object thiz, Object... args) throws IOException {
+            List<Object> arr = new ArrayList<>();
+            if (thiz == null) {
+                if (global != null) {
+                    arr.add(global);
+                }
+            } else {
+                arr.add(thiz);
+            }
+            arr.addAll(Arrays.asList(args));
+            return SPI.invoke(obj, arr.toArray());
+        }
+    }
+
+    /**
+     * Description of a language registered in {@link TruffleVM Truffle virtual machine}. Languages
+     * are registered by {@link Registration} annotation which stores necessary information into a
+     * descriptor inside of the language's JAR file. When a new {@link TruffleVM} is created, it
+     * reads all available descriptors and creates {@link Language} objects to represent them. One
+     * can obtain a {@link #getName() name} or list of supported {@link #getMimeTypes() MIME types}
+     * for each language. The actual language implementation is not initialized until
+     * {@link TruffleVM#eval(java.lang.String, java.lang.String) a code is evaluated} in it.
+     */
+    public final class Language {
+        private final Properties props;
+        private TruffleLanguage impl;
+        private final String prefix;
+        private String shortName;
+
+        Language(String prefix, Properties props) {
+            this.prefix = prefix;
+            this.props = props;
+        }
+
+        /**
+         * MIME types recognized by the language.
+         *
+         * @return returns immutable set of recognized MIME types
+         */
+        public Set<String> getMimeTypes() {
+            TreeSet<String> ts = new TreeSet<>();
+            for (int i = 0;; i++) {
+                String mt = props.getProperty(prefix + "mimeType." + i);
+                if (mt == null) {
+                    break;
+                }
+                ts.add(mt);
+            }
+            return Collections.unmodifiableSet(ts);
+        }
+
+        /**
+         * Human readable name of the language. Think of C, Ruby, JS, etc.
+         *
+         * @return string giving the language a name
+         */
+        public String getName() {
+            return props.getProperty(prefix + "name");
+        }
+
+        /**
+         * Name of the language version.
+         *
+         * @return string specifying the language version
+         */
+        public String getVersion() {
+            return props.getProperty(prefix + "version");
+        }
+
+        /**
+         * Human readable string that identifies the language and version.
+         *
+         * @return string describing the specific language version
+         */
+        public String getShortName() {
+            if (shortName == null) {
+                shortName = getName() + "(" + getVersion() + ")";
+            }
+            return shortName;
+        }
+
+        public ToolSupportProvider getToolSupport() {
+            return SPI.getToolSupport(getImpl());
+        }
+
+        public DebugSupportProvider getDebugSupport() {
+            return SPI.getDebugSupport(getImpl());
+        }
+
+        TruffleLanguage getImpl() {
+            if (impl == null) {
+                String n = props.getProperty(prefix + "className");
+                try {
+                    Class<?> langClazz = Class.forName(n, true, loader());
+                    Constructor<?> constructor = langClazz.getConstructor(Env.class);
+                    impl = SPI.attachEnv(TruffleVM.this, constructor, out, err, in);
+                } catch (Exception ex) {
+                    throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + n, ex);
+                }
+            }
+            return impl;
+        }
+
+        @Override
+        public String toString() {
+            return "[" + getShortName() + " for " + getMimeTypes() + "]";
+        }
+    } // end of Language
+
+    private static class SPIAccessor extends Accessor {
+        @Override
+        public Object importSymbol(TruffleVM vm, TruffleLanguage ownLang, String globalName) {
+            Set<Language> uniqueLang = new LinkedHashSet<>(vm.langs.values());
+            for (Language dl : uniqueLang) {
+                TruffleLanguage l = dl.getImpl();
+                if (l == ownLang) {
+                    continue;
+                }
+                Object obj = SPI.findExportedSymbol(l, globalName, true);
+                if (obj != null) {
+                    return obj;
+                }
+            }
+            for (Language dl : uniqueLang) {
+                TruffleLanguage l = dl.getImpl();
+                if (l == ownLang) {
+                    continue;
+                }
+                Object obj = SPI.findExportedSymbol(l, globalName, false);
+                if (obj != null) {
+                    return obj;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
+            return super.attachEnv(vm, langClazz, stdOut, stdErr, stdIn);
+        }
+
+        @Override
+        public Object eval(TruffleLanguage l, Source s) throws IOException {
+            return super.eval(l, s);
+        }
+
+        @Override
+        public Object findExportedSymbol(TruffleLanguage l, String globalName, boolean onlyExplicit) {
+            return super.findExportedSymbol(l, globalName, onlyExplicit);
+        }
+
+        @Override
+        public Object languageGlobal(TruffleLanguage l) {
+            return super.languageGlobal(l);
+        }
+
+        @Override
+        public Object invoke(Object obj, Object[] args) throws IOException {
+            return super.invoke(obj, args);
+        }
+
+        @Override
+        public ToolSupportProvider getToolSupport(TruffleLanguage l) {
+            return super.getToolSupport(l);
+        }
+
+        @Override
+        public DebugSupportProvider getDebugSupport(TruffleLanguage l) {
+            return super.getDebugSupport(l);
+        }
+    } // end of SPIAccessor
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/package.html	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Truffle Virtual Machine</title>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    </head>
+    <body>
+        <div>Central place to control <a href="TruffleVM.html">Truffle Virtual Machine</a> and
+        all languages hosted in it.</div>
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,212 @@
+<?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: Checks
+    Description: none
+-->
+<module name="Checker">
+  <property name="severity" value="error"/>
+  <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"/>
+    <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="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="ModifiedControlVariable"/>
+    <module name="MutableException">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="ParameterAssignment">
+      <property name="severity" value="ignore"/>
+      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+      <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">
+      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+      <property name="format" value=" ,"/>
+      <property name="message" value="illegal space before a comma"/>
+      <property name="ignoreComments" value="true"/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="[^\x00-\x7F]"/>
+      <property name="message" value="Only use ASCII characters."/>
+    </module>
+    <module name="RegexpSinglelineJava">
+      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+      <property name="message" value="Don't use old synchronized collection classes"/>
+    </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"/>
+    <property name="fileExtensions" value="java"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="severity" value="error"/>
+    <property name="fileExtensions" value="java"/>
+  </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="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 name="RegexpMultiline">
+    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+    <property name="format" value="\r\n"/>
+    <property name="message" value="illegal Windows line ending"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+    <property name="checkFormat" value=".*Header"/>
+    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+    <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+    <property name="checkFormat" value="LineLength"/>
+  </module>
+  <module name="SuppressionCommentFilter">
+    <property name="offCommentFormat" value="CheckStyle: start generated"/>
+    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+    <property name="checkFormat" value=".*Name|.*LineLength"/>
+  </module>
+</module>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/META-INF/services/javax.annotation.processing.Processor	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+com.oracle.truffle.dsl.processor.TruffleProcessor
+com.oracle.truffle.dsl.processor.verify.VerifyTruffleProcessor
+com.oracle.truffle.dsl.processor.LanguageRegistrationProcessor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/AnnotationProcessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.parser.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+class AnnotationProcessor<M extends Template> {
+
+    private final AbstractParser<M> parser;
+    private final CodeTypeElementFactory<M> factory;
+
+    private final Set<String> processedElements = new HashSet<>();
+
+    public AnnotationProcessor(AbstractParser<M> parser, CodeTypeElementFactory<M> factory) {
+        this.parser = parser;
+        this.factory = factory;
+    }
+
+    public AbstractParser<M> getParser() {
+        return parser;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public void process(Element element, boolean callback) {
+        // since it is not guaranteed to be called only once by the compiler
+        // we check for already processed elements to avoid errors when writing files.
+        if (!callback && element instanceof TypeElement) {
+            String qualifiedName = ElementUtils.getQualifiedName((TypeElement) element);
+            if (processedElements.contains(qualifiedName)) {
+                return;
+            }
+            processedElements.add(qualifiedName);
+        }
+
+        ProcessorContext context = ProcessorContext.getInstance();
+        TypeElement type = (TypeElement) element;
+
+        M model = (M) context.getTemplate(type.asType(), false);
+        boolean firstRun = !context.containsTemplate(type);
+
+        if (firstRun || !callback) {
+            context.registerTemplate(type, null);
+            model = parser.parse(element);
+            context.registerTemplate(type, model);
+
+            if (model != null) {
+                CodeTypeElement unit;
+                try {
+                    unit = factory.create(ProcessorContext.getInstance(), model);
+                } catch (Throwable e) {
+                    throw new RuntimeException(String.format("Failed to write code for %s. Parserdump:%s.", ElementUtils.getQualifiedName(type), ""), e);
+                }
+                if (unit == null) {
+                    return;
+                }
+                unit.setGeneratorAnnotationMirror(model.getTemplateTypeAnnotation());
+                unit.setGeneratorElement(model.getTemplateType());
+
+                DeclaredType overrideType = (DeclaredType) context.getType(Override.class);
+                DeclaredType unusedType = (DeclaredType) context.getType(SuppressWarnings.class);
+                unit.accept(new GenerateOverrideVisitor(overrideType), null);
+                unit.accept(new FixWarningsVisitor(context.getEnvironment(), unusedType, overrideType), null);
+
+                if (!callback) {
+                    unit.accept(new CodeWriter(context.getEnvironment(), element), null);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CodeWriter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.io.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+public final class CodeWriter extends AbstractCodeWriter {
+
+    private final Element originalElement;
+    private final ProcessingEnvironment env;
+
+    public CodeWriter(ProcessingEnvironment env, Element originalElement) {
+        this.env = env;
+        this.originalElement = originalElement;
+    }
+
+    @Override
+    protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+        JavaFileObject jfo = env.getFiler().createSourceFile(clazz.getQualifiedName(), originalElement);
+        return new BufferedWriter(jfo.openWriter());
+    }
+
+    @Override
+    protected void writeHeader() {
+        if (env == null) {
+            return;
+        }
+        String comment = CompilerFactory.getCompiler(originalElement).getHeaderComment(env, originalElement);
+        if (comment != null) {
+            writeLn(comment);
+        }
+        writeLn("// CheckStyle: start generated");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/CompileErrorException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+public class CompileErrorException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public CompileErrorException(String message) {
+        super(message);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ExpectError.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.*;
+
+public class ExpectError {
+
+    public static void assertNoErrorExpected(ProcessingEnvironment processingEnv, Element element) {
+        TypeElement eee = processingEnv.getElementUtils().getTypeElement(TruffleTypes.EXPECT_ERROR_CLASS_NAME);
+        if (eee != null) {
+            for (AnnotationMirror am : element.getAnnotationMirrors()) {
+                if (am.getAnnotationType().asElement().equals(eee)) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, "Expected an error, but none found!", element);
+                }
+            }
+        }
+    }
+
+    public static boolean isExpectedError(ProcessingEnvironment processingEnv, Element element, String message) {
+        TypeElement eee = processingEnv.getElementUtils().getTypeElement(TruffleTypes.EXPECT_ERROR_CLASS_NAME);
+        if (eee != null) {
+            for (AnnotationMirror am : element.getAnnotationMirrors()) {
+                if (am.getAnnotationType().asElement().equals(eee)) {
+                    Map<? extends ExecutableElement, ? extends AnnotationValue> vals = am.getElementValues();
+                    if (vals.size() == 1) {
+                        AnnotationValue av = vals.values().iterator().next();
+                        if (av.getValue() instanceof List) {
+                            List<?> arr = (List<?>) av.getValue();
+                            for (Object o : arr) {
+                                if (o instanceof AnnotationValue) {
+                                    AnnotationValue ov = (AnnotationValue) o;
+                                    if (message.equals(ov.getValue())) {
+                                        return true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/LanguageRegistrationProcessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.TruffleLanguage.Registration;
+
+@SupportedAnnotationTypes("com.oracle.truffle.api.*")
+public final class LanguageRegistrationProcessor extends AbstractProcessor {
+    private final List<TypeElement> registrations = new ArrayList<>();
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    private void generateFile(List<TypeElement> languages) {
+        String filename = "META-INF/truffle/language";
+        Properties p = new Properties();
+        int cnt = 0;
+        for (TypeElement l : languages) {
+            Registration annotation = l.getAnnotation(Registration.class);
+            if (annotation == null) {
+                continue;
+            }
+            String prefix = "language" + ++cnt + ".";
+            String className = processingEnv.getElementUtils().getBinaryName(l).toString();
+            p.setProperty(prefix + "name", annotation.name());
+            p.setProperty(prefix + "version", annotation.version());
+            p.setProperty(prefix + "className", className);
+            String[] mimes = annotation.mimeType();
+            for (int i = 0; i < mimes.length; i++) {
+                p.setProperty(prefix + "mimeType." + i, mimes[i]);
+            }
+        }
+        if (cnt > 0) {
+            try {
+                FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, languages.toArray(new Element[0]));
+                try (OutputStream os = file.openOutputStream()) {
+                    p.store(os, "Generated by " + LanguageRegistrationProcessor.class.getName());
+                }
+            } catch (IOException e) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), languages.get(0));
+            }
+        }
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            generateFile(registrations);
+            registrations.clear();
+            return true;
+        }
+        for (Element e : roundEnv.getElementsAnnotatedWith(Registration.class)) {
+            Registration annotation = e.getAnnotation(Registration.class);
+            if (annotation != null && e.getKind() == ElementKind.CLASS) {
+                if (!e.getModifiers().contains(Modifier.PUBLIC)) {
+                    emitError("Registered language class must be public", e);
+                    continue;
+                }
+                if (e.getEnclosingElement().getKind() != ElementKind.PACKAGE && !e.getModifiers().contains(Modifier.STATIC)) {
+                    emitError("Registered language inner-class must be static", e);
+                    continue;
+                }
+                TypeMirror truffleLang = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.class.getName()).asType();
+                if (!processingEnv.getTypeUtils().isAssignable(e.asType(), truffleLang)) {
+                    emitError("Registered language class must subclass TruffleLanguage", e);
+                    continue;
+                }
+                boolean found = false;
+                for (Element mem : e.getEnclosedElements()) {
+                    if (mem.getKind() != ElementKind.CONSTRUCTOR) {
+                        continue;
+                    }
+                    ExecutableElement ee = (ExecutableElement) mem;
+                    if (ee.getParameters().size() != 1) {
+                        continue;
+                    }
+                    if (!ee.getModifiers().contains(Modifier.PUBLIC)) {
+                        continue;
+                    }
+                    TypeMirror env = processingEnv.getElementUtils().getTypeElement(TruffleLanguage.Env.class.getCanonicalName()).asType();
+                    if (processingEnv.getTypeUtils().isSameType(ee.getParameters().get(0).asType(), env)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    emitError("Language must have a public constructor accepting TruffleLanguage.Env as parameter", e);
+                    continue;
+                }
+                assertNoErrorExpected(e);
+                registrations.add((TypeElement) e);
+            }
+        }
+
+        return true;
+    }
+
+    void assertNoErrorExpected(Element e) {
+        ExpectError.assertNoErrorExpected(processingEnv, e);
+    }
+
+    void emitError(String msg, Element e) {
+        if (ExpectError.isExpectedError(processingEnv, e, msg)) {
+            return;
+        }
+        processingEnv.getMessager().printMessage(Kind.ERROR, msg, e);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/Log.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class Log {
+
+    public static boolean isDebug() {
+        return false;
+    }
+
+    private final ProcessingEnvironment processingEnv;
+
+    public Log(ProcessingEnvironment env) {
+        this.processingEnv = env;
+    }
+
+    public void message(Kind kind, Element element, AnnotationMirror mirror, AnnotationValue value, String format, Object... args) {
+        AnnotationMirror usedMirror = mirror;
+        Element usedElement = element;
+        AnnotationValue usedValue = value;
+        String message = String.format(format, args);
+
+        if (element instanceof GeneratedElement) {
+            usedMirror = ((GeneratedElement) element).getGeneratorAnnotationMirror();
+            usedElement = ((GeneratedElement) element).getGeneratorElement();
+            usedValue = null;
+            if (usedElement != null) {
+                message = String.format("Element %s: %s", element, message);
+            }
+        }
+        processingEnv.getMessager().printMessage(kind, message, usedElement, usedMirror, usedValue);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/ProcessorContext.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class ProcessorContext {
+
+    private final ProcessingEnvironment environment;
+
+    private final Map<String, Template> models = new HashMap<>();
+
+    private final ProcessCallback callback;
+    private final Log log;
+    private final TruffleTypes truffleTypes;
+
+    ProcessorContext(ProcessingEnvironment env, ProcessCallback callback) {
+        this.environment = env;
+        this.callback = callback;
+        this.log = new Log(environment);
+        this.truffleTypes = new TruffleTypes(this);
+    }
+
+    public TruffleTypes getTruffleTypes() {
+        return truffleTypes;
+    }
+
+    public Log getLog() {
+        return log;
+    }
+
+    public ProcessingEnvironment getEnvironment() {
+        return environment;
+    }
+
+    public boolean containsTemplate(TypeElement element) {
+        return models.containsKey(ElementUtils.getQualifiedName(element));
+    }
+
+    public void registerTemplate(TypeElement element, Template model) {
+        models.put(ElementUtils.getQualifiedName(element), model);
+    }
+
+    public Template getTemplate(TypeMirror templateTypeMirror, boolean invokeCallback) {
+        String qualifiedName = ElementUtils.getQualifiedName(templateTypeMirror);
+        Template model = models.get(qualifiedName);
+        if (model == null && invokeCallback) {
+            callback.callback(ElementUtils.fromTypeMirror(templateTypeMirror));
+            model = models.get(qualifiedName);
+        }
+        return model;
+    }
+
+    public DeclaredType getDeclaredType(Class<?> element) {
+        return (DeclaredType) ElementUtils.getType(environment, element);
+    }
+
+    public boolean isType(TypeMirror type, Class<?> clazz) {
+        return ElementUtils.typeEquals(type, getType(clazz));
+    }
+
+    public TypeMirror getType(Class<?> element) {
+        return ElementUtils.getType(environment, element);
+    }
+
+    public interface ProcessCallback {
+
+        void callback(TypeElement template);
+
+    }
+
+    public TypeMirror reloadTypeElement(TypeElement type) {
+        return getType(type.getQualifiedName().toString());
+    }
+
+    private TypeMirror getType(String className) {
+        TypeElement element = environment.getElementUtils().getTypeElement(className);
+        if (element != null) {
+            return element.asType();
+        }
+        return null;
+    }
+
+    public TypeMirror reloadType(TypeMirror type) {
+        if (type instanceof CodeTypeMirror) {
+            return type;
+        } else if (type.getKind().isPrimitive()) {
+            return type;
+        }
+        Types types = getEnvironment().getTypeUtils();
+
+        switch (type.getKind()) {
+            case ARRAY:
+                return types.getArrayType(reloadType(((ArrayType) type).getComponentType()));
+            case WILDCARD:
+                return types.getWildcardType(((WildcardType) type).getExtendsBound(), ((WildcardType) type).getSuperBound());
+            case DECLARED:
+                return reloadTypeElement((TypeElement) (((DeclaredType) type).asElement()));
+        }
+        return type;
+    }
+
+    private static final ThreadLocal<ProcessorContext> instance = new ThreadLocal<>();
+
+    public static void setThreadLocalInstance(ProcessorContext context) {
+        instance.set(context);
+    }
+
+    public static ProcessorContext getInstance() {
+        return instance.get();
+    }
+
+    public List<TypeMirror> getFrameTypes() {
+        return Arrays.asList(getType(VirtualFrame.class), getType(MaterializedFrame.class), getType(Frame.class));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleProcessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.ProcessorContext.ProcessCallback;
+import com.oracle.truffle.dsl.processor.generator.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.parser.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+// @SupportedAnnotationTypes({"com.oracle.truffle.codegen.Operation",
+// "com.oracle.truffle.codegen.TypeLattice"})
+public class TruffleProcessor extends AbstractProcessor implements ProcessCallback {
+
+    private List<AnnotationProcessor<?>> generators;
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (!roundEnv.processingOver()) {
+            processImpl(roundEnv);
+        }
+        return false;
+    }
+
+    private void processImpl(RoundEnvironment env) {
+        // TODO run verifications that other annotations are not processed out of scope of the
+        // operation or typelattice.
+        try {
+            ProcessorContext.setThreadLocalInstance(new ProcessorContext(processingEnv, this));
+            for (AnnotationProcessor<?> generator : getGenerators()) {
+                AbstractParser<?> parser = generator.getParser();
+                if (parser.getAnnotationType() != null) {
+                    for (Element e : env.getElementsAnnotatedWith(parser.getAnnotationType())) {
+                        processElement(generator, e, false);
+                    }
+                }
+
+                for (Class<? extends Annotation> annotationType : parser.getTypeDelegatedAnnotationTypes()) {
+                    for (Element e : env.getElementsAnnotatedWith(annotationType)) {
+                        TypeElement processedType;
+                        if (parser.isDelegateToRootDeclaredType()) {
+                            processedType = ElementUtils.findRootEnclosingType(e);
+                        } else {
+                            processedType = ElementUtils.findNearestEnclosingType(e);
+                        }
+                        processElement(generator, processedType, false);
+                    }
+                }
+
+            }
+        } finally {
+            ProcessorContext.setThreadLocalInstance(null);
+        }
+    }
+
+    private static void processElement(AnnotationProcessor<?> generator, Element e, boolean callback) {
+        try {
+            generator.process(e, callback);
+        } catch (Throwable e1) {
+            handleThrowable(generator, e1, e);
+        }
+    }
+
+    private static void handleThrowable(AnnotationProcessor<?> generator, Throwable t, Element e) {
+        String message = "Uncaught error in " + generator.getClass().getSimpleName() + " while processing " + e + " ";
+        ProcessorContext.getInstance().getEnvironment().getMessager().printMessage(Kind.ERROR, message + ": " + ElementUtils.printException(t), e);
+    }
+
+    @Override
+    public void callback(TypeElement template) {
+        for (AnnotationProcessor<?> generator : generators) {
+            Class<? extends Annotation> annotationType = generator.getParser().getAnnotationType();
+            if (annotationType != null) {
+                Annotation annotation = template.getAnnotation(annotationType);
+                if (annotation != null) {
+                    processElement(generator, template, true);
+                }
+            }
+        }
+    }
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        Set<String> annotations = new HashSet<>();
+        List<Class<? extends Annotation>> annotationsTypes = new ArrayList<>();
+        annotationsTypes.addAll(NodeParser.ANNOTATIONS);
+        annotationsTypes.addAll(TypeSystemParser.ANNOTATIONS);
+        for (Class<? extends Annotation> type : annotationsTypes) {
+            annotations.add(type.getCanonicalName());
+        }
+        return annotations;
+    }
+
+    private List<AnnotationProcessor<?>> getGenerators() {
+        if (generators == null && processingEnv != null) {
+            generators = new ArrayList<>();
+            generators.add(new AnnotationProcessor<>(new TypeSystemParser(), new TypeSystemCodeGenerator()));
+            generators.add(new AnnotationProcessor<>(new NodeParser(), new NodeCodeGenerator()));
+        }
+        return generators;
+    }
+
+    @Override
+    public synchronized void init(ProcessingEnvironment env) {
+        this.processingEnv = env;
+        super.init(env);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public final class TruffleTypes {
+
+    public static final String EXPECT_ERROR_CLASS_NAME = "com.oracle.truffle.api.dsl.test.ExpectError";
+
+    private final DeclaredType node;
+    private final ArrayType nodeArray;
+    private final TypeMirror unexpectedValueException;
+    private final TypeMirror frame;
+    private final TypeMirror assumption;
+    private final TypeMirror invalidAssumption;
+    private final DeclaredType childAnnotation;
+    private final DeclaredType childrenAnnotation;
+    private final DeclaredType nodeInfoAnnotation;
+    private final DeclaredType nodeCost;
+    private final TypeMirror compilerDirectives;
+    private final TypeMirror compilerAsserts;
+    private final DeclaredType truffleBoundary;
+    private final DeclaredType sourceSection;
+    private final DeclaredType truffleOptions;
+    private final DeclaredType compilationFinal;
+    private final DeclaredType nodeUtil;
+    private final DeclaredType dslNode;
+    private final DeclaredType dslShare;
+    private final DeclaredType nodeFactory;
+    private final DeclaredType nodeFactoryBase;
+    private final DeclaredType dslMetadata;
+    private final DeclaredType generateNodeFactory;
+    private final TypeElement expectError;
+
+    private final List<String> errors = new ArrayList<>();
+
+    TruffleTypes(ProcessorContext context) {
+        node = getRequired(context, Node.class);
+        nodeArray = context.getEnvironment().getTypeUtils().getArrayType(node);
+        unexpectedValueException = getRequired(context, UnexpectedResultException.class);
+        frame = getRequired(context, VirtualFrame.class);
+        childAnnotation = getRequired(context, Child.class);
+        childrenAnnotation = getRequired(context, Children.class);
+        compilerDirectives = getRequired(context, CompilerDirectives.class);
+        compilerAsserts = getRequired(context, CompilerAsserts.class);
+        assumption = getRequired(context, Assumption.class);
+        invalidAssumption = getRequired(context, InvalidAssumptionException.class);
+        nodeInfoAnnotation = getRequired(context, NodeInfo.class);
+        nodeCost = getRequired(context, NodeCost.class);
+        truffleBoundary = getRequired(context, TruffleBoundary.class);
+        sourceSection = getRequired(context, SourceSection.class);
+        truffleOptions = getRequired(context, TruffleOptions.class);
+        compilationFinal = getRequired(context, CompilationFinal.class);
+        nodeUtil = getRequired(context, NodeUtil.class);
+        dslNode = getRequired(context, DSLNode.class);
+        dslShare = getRequired(context, DSLShare.class);
+        nodeFactory = getRequired(context, NodeFactory.class);
+        nodeFactoryBase = getRequired(context, NodeFactoryBase.class);
+        dslMetadata = getRequired(context, DSLMetadata.class);
+        expectError = getOptional(context, EXPECT_ERROR_CLASS_NAME);
+        generateNodeFactory = getRequired(context, GenerateNodeFactory.class);
+    }
+
+    public DeclaredType getGenerateNodeFactory() {
+        return generateNodeFactory;
+    }
+
+    public DeclaredType getDslMetadata() {
+        return dslMetadata;
+    }
+
+    public DeclaredType getNodeFactory() {
+        return nodeFactory;
+    }
+
+    public DeclaredType getNodeFactoryBase() {
+        return nodeFactoryBase;
+    }
+
+    public DeclaredType getDslNode() {
+        return dslNode;
+    }
+
+    public DeclaredType getDslShare() {
+        return dslShare;
+    }
+
+    public DeclaredType getCompilationFinal() {
+        return compilationFinal;
+    }
+
+    public TypeElement getExpectError() {
+        return expectError;
+    }
+
+    public DeclaredType getNodeInfoAnnotation() {
+        return nodeInfoAnnotation;
+    }
+
+    public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) {
+        if (errors.isEmpty()) {
+            return true;
+        }
+
+        for (String error : errors) {
+            context.getLog().message(Kind.ERROR, element, mirror, null, error);
+        }
+
+        return false;
+    }
+
+    public DeclaredType getNodeCost() {
+        return nodeCost;
+    }
+
+    private DeclaredType getRequired(ProcessorContext context, Class<?> clazz) {
+        TypeMirror type = context.getType(clazz);
+        if (type == null) {
+            errors.add(String.format("Could not find required type: %s", clazz.getSimpleName()));
+        }
+        return (DeclaredType) type;
+    }
+
+    private static TypeElement getOptional(ProcessorContext context, String name) {
+        return context.getEnvironment().getElementUtils().getTypeElement(name);
+    }
+
+    public TypeMirror getInvalidAssumption() {
+        return invalidAssumption;
+    }
+
+    public TypeMirror getAssumption() {
+        return assumption;
+    }
+
+    public TypeMirror getCompilerDirectives() {
+        return compilerDirectives;
+    }
+
+    public DeclaredType getNode() {
+        return node;
+    }
+
+    public ArrayType getNodeArray() {
+        return nodeArray;
+    }
+
+    public TypeMirror getFrame() {
+        return frame;
+    }
+
+    public TypeMirror getUnexpectedValueException() {
+        return unexpectedValueException;
+    }
+
+    public DeclaredType getChildAnnotation() {
+        return childAnnotation;
+    }
+
+    public DeclaredType getChildrenAnnotation() {
+        return childrenAnnotation;
+    }
+
+    public TypeMirror getCompilerAsserts() {
+        return compilerAsserts;
+    }
+
+    public DeclaredType getTruffleOptions() {
+        return truffleOptions;
+    }
+
+    public DeclaredType getTruffleBoundary() {
+        return truffleBoundary;
+    }
+
+    public DeclaredType getSourceSection() {
+        return sourceSection;
+    }
+
+    public DeclaredType getNodeUtil() {
+        return nodeUtil;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Copyright.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 content of this file is automatically generated. DO NOT EDIT.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpression.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public abstract class DSLExpression {
+
+    private TypeMirror resolvedTargetType;
+
+    private DSLExpression() {
+    }
+
+    public static DSLExpression parse(String input) {
+        return Parser.parse(input);
+    }
+
+    public final Set<VariableElement> findBoundVariableElements() {
+        final Set<VariableElement> variables = new HashSet<>();
+        this.accept(new AbstractDSLExpressionVisitor() {
+
+            @Override
+            public void visitVariable(Variable variable) {
+                if (variable.getReceiver() == null) {
+                    variables.add(variable.getResolvedVariable());
+                }
+            }
+
+        });
+        return variables;
+    }
+
+    public final Set<Variable> findBoundVariables() {
+        final Set<Variable> variables = new HashSet<>();
+        this.accept(new AbstractDSLExpressionVisitor() {
+
+            @Override
+            public void visitVariable(Variable variable) {
+                if (variable.getReceiver() == null) {
+                    variables.add(variable);
+                }
+            }
+
+        });
+        return variables;
+    }
+
+    public boolean containsComparisons() {
+        final AtomicBoolean found = new AtomicBoolean();
+        this.accept(new AbstractDSLExpressionVisitor() {
+            @Override
+            public void visitBinary(Binary binary) {
+                if (binary.isComparison()) {
+                    found.set(true);
+                }
+            }
+        });
+        return found.get();
+    }
+
+    public void setResolvedTargetType(TypeMirror resolvedTargetType) {
+        this.resolvedTargetType = resolvedTargetType;
+    }
+
+    public TypeMirror getResolvedTargetType() {
+        return resolvedTargetType;
+    }
+
+    public abstract TypeMirror getResolvedType();
+
+    public abstract void accept(DSLExpressionVisitor visitor);
+
+    public static final class Negate extends DSLExpression {
+
+        private final DSLExpression receiver;
+
+        public Negate(DSLExpression receiver) {
+            this.receiver = receiver;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            receiver.accept(visitor);
+            visitor.visitNegate(this);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return receiver.getResolvedType();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Negate) {
+                return receiver.equals(((Negate) obj).receiver);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return receiver.hashCode();
+        }
+    }
+
+    public static final class Binary extends DSLExpression {
+
+        private final String operator;
+        private final DSLExpression left;
+        private final DSLExpression right;
+
+        private TypeMirror resolvedType;
+
+        public Binary(String operator, DSLExpression left, DSLExpression right) {
+            this.operator = operator;
+            this.left = left;
+            this.right = right;
+        }
+
+        public boolean isComparison() {
+            return DSLExpressionResolver.COMPARABLE_OPERATORS.contains(operator) || DSLExpressionResolver.IDENTITY_OPERATORS.contains(operator);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Binary) {
+                Binary other = (Binary) obj;
+                return operator.equals(other.operator) && left.equals(other.left) && right.equals(other.right);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(operator, left, right);
+        }
+
+        public String getOperator() {
+            return operator;
+        }
+
+        public DSLExpression getLeft() {
+            return left;
+        }
+
+        public DSLExpression getRight() {
+            return right;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            left.accept(visitor);
+            right.accept(visitor);
+            visitor.visitBinary(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedType;
+        }
+
+        public void setResolvedType(TypeMirror resolvedType) {
+            this.resolvedType = resolvedType;
+        }
+
+        @Override
+        public String toString() {
+            return "Binary [left=" + left + ", operator=" + operator + ", right=" + right + ", resolvedType=" + resolvedType + "]";
+        }
+
+    }
+
+    public static final class Call extends DSLExpression {
+
+        private final DSLExpression receiver;
+        private final String name;
+        private final List<DSLExpression> parameters;
+
+        private ExecutableElement resolvedMethod;
+
+        public Call(DSLExpression receiver, String name, List<DSLExpression> parameters) {
+            this.receiver = receiver;
+            this.name = name;
+            this.parameters = parameters;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Call) {
+                Call other = (Call) obj;
+                return Objects.equals(receiver, other.receiver) && name.equals(other.name) && parameters.equals(other.parameters);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(receiver, name, parameters);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public List<DSLExpression> getParameters() {
+            return parameters;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            if (receiver != null) {
+                receiver.accept(visitor);
+            }
+            for (DSLExpression parameter : getParameters()) {
+                parameter.accept(visitor);
+            }
+            visitor.visitCall(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            if (resolvedMethod == null) {
+                return null;
+            }
+            if (resolvedMethod.getKind() == ElementKind.CONSTRUCTOR) {
+                return resolvedMethod.getEnclosingElement().asType();
+            } else {
+                return resolvedMethod.getReturnType();
+            }
+        }
+
+        public ExecutableElement getResolvedMethod() {
+            return resolvedMethod;
+        }
+
+        public void setResolvedMethod(ExecutableElement resolvedMethod) {
+            this.resolvedMethod = resolvedMethod;
+        }
+
+        @Override
+        public String toString() {
+            return "Call [receiver=" + receiver + ", name=" + name + ", parameters=" + parameters + ", resolvedMethod=" + resolvedMethod + "]";
+        }
+
+    }
+
+    public static final class Variable extends DSLExpression {
+
+        private final DSLExpression receiver;
+        private final String name;
+
+        private VariableElement resolvedVariable;
+
+        public Variable(DSLExpression receiver, String name) {
+            this.receiver = receiver;
+            this.name = name;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Variable) {
+                Variable other = (Variable) obj;
+                return Objects.equals(receiver, other.receiver) && name.equals(other.name);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(receiver, name);
+        }
+
+        public DSLExpression getReceiver() {
+            return receiver;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            if (receiver != null) {
+                receiver.accept(visitor);
+            }
+            visitor.visitVariable(this);
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedVariable != null ? resolvedVariable.asType() : null;
+        }
+
+        public void setResolvedVariable(VariableElement resolvedVariable) {
+            this.resolvedVariable = resolvedVariable;
+        }
+
+        public VariableElement getResolvedVariable() {
+            return resolvedVariable;
+        }
+
+        @Override
+        public String toString() {
+            return "Variable [receiver=" + receiver + ", name=" + name + ", resolvedVariable=" + resolvedVariable + "]";
+        }
+
+    }
+
+    public static final class IntLiteral extends DSLExpression {
+
+        private final String literal;
+
+        private int resolvedValueInt;
+        private TypeMirror resolvedType;
+
+        public IntLiteral(String literal) {
+            this.literal = literal;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof IntLiteral) {
+                IntLiteral other = (IntLiteral) obj;
+                return resolvedValueInt == other.resolvedValueInt;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return resolvedValueInt;
+        }
+
+        public String getLiteral() {
+            return literal;
+        }
+
+        public int getResolvedValueInt() {
+            return resolvedValueInt;
+        }
+
+        public void setResolvedValueInt(int resolved) {
+            this.resolvedValueInt = resolved;
+        }
+
+        @Override
+        public TypeMirror getResolvedType() {
+            return resolvedType;
+        }
+
+        public void setResolvedType(TypeMirror resolvedType) {
+            this.resolvedType = resolvedType;
+        }
+
+        @Override
+        public void accept(DSLExpressionVisitor visitor) {
+            visitor.visitIntLiteral(this);
+        }
+
+        @Override
+        public String toString() {
+            return "IntLiteral [literal=" + literal + ", resolvedValueInt=" + resolvedValueInt + ", resolvedType=" + resolvedType + "]";
+        }
+
+    }
+
+    public abstract class AbstractDSLExpressionVisitor implements DSLExpressionVisitor {
+
+        public void visitBinary(Binary binary) {
+        }
+
+        public void visitCall(Call binary) {
+        }
+
+        public void visitIntLiteral(IntLiteral binary) {
+        }
+
+        public void visitNegate(Negate negate) {
+        }
+
+        public void visitVariable(Variable binary) {
+        }
+    }
+
+    public interface DSLExpressionVisitor {
+
+        void visitBinary(Binary binary);
+
+        void visitNegate(Negate negate);
+
+        void visitCall(Call binary);
+
+        void visitVariable(Variable binary);
+
+        void visitIntLiteral(IntLiteral binary);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class DSLExpressionResolver implements DSLExpressionVisitor {
+
+    private static final List<String> LOGIC_OPERATORS = Arrays.asList("||");
+    public static final List<String> COMPARABLE_OPERATORS = Arrays.asList("<", "<=", ">", ">=");
+    public static final List<String> IDENTITY_OPERATORS = Arrays.asList("==", "!=");
+    private static final String CONSTRUCTOR_KEYWORD = "new";
+
+    private final List<VariableElement> variables = new ArrayList<>();
+    private final List<ExecutableElement> methods = new ArrayList<>();
+    private final ProcessorContext context;
+
+    private DSLExpressionResolver(ProcessorContext context) {
+        this.context = context;
+    }
+
+    public DSLExpressionResolver(ProcessorContext context, List<? extends Element> lookupElements) {
+        this(context);
+        lookup(lookupElements);
+    }
+
+    public DSLExpressionResolver copy(List<? extends Element> prefixElements) {
+        DSLExpressionResolver resolver = new DSLExpressionResolver(context);
+        resolver.lookup(prefixElements);
+        resolver.variables.addAll(variables);
+        resolver.methods.addAll(methods);
+        return resolver;
+    }
+
+    private void lookup(List<? extends Element> lookupElements) {
+        variablesIn(variables, lookupElements, false);
+        methodsIn(lookupElements);
+    }
+
+    private void methodsIn(List<? extends Element> lookupElements) {
+        for (Element variable : lookupElements) {
+            ElementKind kind = variable.getKind();
+            if (kind == ElementKind.METHOD || kind == ElementKind.CONSTRUCTOR) {
+                methods.add((ExecutableElement) variable);
+            }
+        }
+    }
+
+    private static void variablesIn(List<VariableElement> variables, List<? extends Element> lookupElements, boolean publicOnly) {
+        for (Element variable : lookupElements) {
+            ElementKind kind = variable.getKind();
+            if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER || kind == ElementKind.FIELD || kind == ElementKind.ENUM_CONSTANT) {
+                VariableElement variableElement = (VariableElement) variable;
+                if (!publicOnly || variableElement.getModifiers().contains(Modifier.PUBLIC)) {
+                    variables.add(variableElement);
+                }
+            }
+        }
+    }
+
+    private static String getMethodName(ExecutableElement method) {
+        if (method.getKind() == ElementKind.CONSTRUCTOR) {
+            return CONSTRUCTOR_KEYWORD;
+        } else {
+            return method.getSimpleName().toString();
+        }
+    }
+
+    public void visitBinary(Binary binary) {
+        String operator = binary.getOperator();
+        TypeMirror leftType = binary.getLeft().getResolvedType();
+        TypeMirror rightType = binary.getRight().getResolvedType();
+        if (!ElementUtils.areTypesCompatible(leftType, rightType)) {
+            throw new InvalidExpressionException(String.format("Incompatible operand types %s and %s.", ElementUtils.getSimpleName(leftType), ElementUtils.getSimpleName(rightType)));
+        }
+
+        TypeMirror booleanType = context.getType(boolean.class);
+        boolean valid;
+        if (LOGIC_OPERATORS.contains(operator)) {
+            valid = ElementUtils.typeEquals(leftType, booleanType);
+        } else if (COMPARABLE_OPERATORS.contains(operator)) {
+            valid = ElementUtils.isPrimitive(leftType);
+        } else if (IDENTITY_OPERATORS.contains(operator)) {
+            valid = leftType.getKind().isPrimitive() || leftType.getKind() == TypeKind.DECLARED || leftType.getKind() == TypeKind.ARRAY;
+        } else {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined.", operator));
+        }
+        binary.setResolvedType(booleanType);
+
+        if (!valid) {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type(s) %s %s.", operator, ElementUtils.getSimpleName(leftType),
+                            ElementUtils.getSimpleName(rightType)));
+        }
+    }
+
+    public void visitNegate(Negate negate) {
+        TypeMirror booleanType = context.getType(boolean.class);
+        TypeMirror resolvedType = negate.getResolvedType();
+        if (!ElementUtils.typeEquals(resolvedType, booleanType)) {
+            throw new InvalidExpressionException(String.format("The operator %s is undefined for the argument type %s.", "!", ElementUtils.getSimpleName(resolvedType)));
+        }
+    }
+
+    public void visitCall(Call call) {
+        List<ExecutableElement> lookupMethods;
+        DSLExpression receiver = call.getReceiver();
+        if (receiver == null) {
+            lookupMethods = this.methods;
+        } else {
+            TypeMirror type = receiver.getResolvedType();
+            if (type.getKind() == TypeKind.DECLARED) {
+                type = context.reloadType(type); // ensure ECJ has the type loaded
+                lookupMethods = ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()));
+            } else {
+                lookupMethods = Collections.emptyList();
+            }
+        }
+
+        ExecutableElement foundWithName = null;
+        outer: for (ExecutableElement method : lookupMethods) {
+            if (getMethodName(method).equals(call.getName())) {
+                foundWithName = method;
+
+                List<? extends VariableElement> parameters = method.getParameters();
+                if (parameters.size() != call.getParameters().size()) {
+                    continue outer;
+                }
+
+                int parameterIndex = 0;
+                for (DSLExpression expression : call.getParameters()) {
+                    TypeMirror sourceType = expression.getResolvedType();
+                    TypeMirror targetType = parameters.get(parameterIndex).asType();
+                    if (!ElementUtils.isAssignable(sourceType, targetType)) {
+                        continue outer;
+                    }
+                    expression.setResolvedTargetType(targetType);
+                    parameterIndex++;
+                }
+
+                call.setResolvedMethod(method);
+                break;
+            }
+        }
+        if (call.getResolvedMethod() == null) {
+            if (foundWithName == null) {
+                // parameter mismatch
+                throw new InvalidExpressionException(String.format("The method %s is undefined for the enclosing scope.", call.getName()));
+            } else {
+                StringBuilder arguments = new StringBuilder();
+                String sep = "";
+                for (DSLExpression expression : call.getParameters()) {
+                    arguments.append(sep).append(ElementUtils.getSimpleName(expression.getResolvedType()));
+                    sep = ", ";
+                }
+                // name mismatch
+                throw new InvalidExpressionException(String.format("The method %s in the type %s is not applicable for the arguments %s.", //
+                                ElementUtils.getReadableSignature(foundWithName), //
+                                ElementUtils.getSimpleName((TypeElement) foundWithName.getEnclosingElement()), arguments.toString()));
+            }
+        }
+    }
+
+    public void visitVariable(Variable variable) {
+        List<VariableElement> lookupVariables;
+        DSLExpression receiver = variable.getReceiver();
+        if (variable.getName().equals("null")) {
+            variable.setResolvedVariable(new CodeVariableElement(new CodeTypeMirror(TypeKind.NULL), "null"));
+        } else {
+            if (receiver == null) {
+                lookupVariables = this.variables;
+            } else {
+                TypeMirror type = receiver.getResolvedType();
+                if (type.getKind() == TypeKind.DECLARED) {
+                    type = context.reloadType(type); // ensure ECJ has the type loaded
+                    lookupVariables = new ArrayList<>();
+                    variablesIn(lookupVariables, context.getEnvironment().getElementUtils().getAllMembers((TypeElement) ((DeclaredType) type).asElement()), true);
+                } else if (type.getKind() == TypeKind.ARRAY) {
+                    lookupVariables = Arrays.<VariableElement> asList(new CodeVariableElement(context.getType(int.class), "length"));
+                } else {
+                    lookupVariables = Collections.emptyList();
+                }
+            }
+
+            for (VariableElement variableElement : lookupVariables) {
+                if (variableElement.getSimpleName().toString().equals(variable.getName())) {
+                    variable.setResolvedVariable(variableElement);
+                    break;
+                }
+            }
+        }
+
+        if (variable.getResolvedVariable() == null) {
+            throw new InvalidExpressionException(String.format("%s cannot be resolved.", variable.getName()));
+        }
+    }
+
+    public void visitIntLiteral(IntLiteral binary) {
+        try {
+            binary.setResolvedType(context.getType(int.class));
+
+            final int base;
+            final String literal;
+
+            if (binary.getLiteral().startsWith("0x")) {
+                base = 16;
+                literal = binary.getLiteral().substring(2);
+            } else if (binary.getLiteral().startsWith("0b")) {
+                base = 2;
+                literal = binary.getLiteral().substring(2);
+            } else if (binary.getLiteral().startsWith("0")) {
+                base = 8;
+                literal = binary.getLiteral();
+            } else {
+                base = 10;
+                literal = binary.getLiteral();
+            }
+
+            binary.setResolvedValueInt(Integer.parseInt(literal, base));
+        } catch (NumberFormatException e) {
+            throw new InvalidExpressionException(String.format("Type mismatch: cannot convert from String '%s' to int", binary.getLiteral()));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Expression.atg	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 is the grammar for DSL expressions that is used to automatically generate the Parser.java and Scanner.java
+ * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run
+ * "java -jar Coco.jar Expression.atg"
+ */
+
+COMPILER Expression
+
+CHARACTERS
+
+letter = 'A' .. 'Z' + 'a' .. 'z' + '_' + '$'.
+nonZeroDigit = "123456789".
+digit = '0' + nonZeroDigit .
+hexDigit = "0123456789abcdefABCDEF".
+octDigit = "01234567".
+binaryDigit = "01".
+
+TOKENS
+
+identifier = letter {letter | digit}.
+numericLiteral = "0" ( "x" { hexDigit } | "b" { binaryDigit } | { octDigit } ) | nonZeroDigit { digit }.
+
+PRAGMAS
+
+PRODUCTIONS
+
+
+Expression<out DSLExpression result>
+=
+LogicFactor<out result>
+.
+
+
+LogicFactor<out DSLExpression  result>
+=
+ComparisonFactor<out result>
+[
+    ("||")                                      (. Token op = t; .)
+    ComparisonFactor<out DSLExpression  right>  (.  result = new Binary(op.val, result, right); .)
+]
+.
+
+ComparisonFactor<out DSLExpression  result>
+=
+NegateFactor<out result>
+[
+    ("<" | "<=" | ">" | ">=" | "==" | "!=" )    (. Token op = t; .)
+    NegateFactor<out DSLExpression  right>      (.  result = new Binary(op.val, result, right); .)
+]
+.
+
+
+NegateFactor<out DSLExpression  result>
+=                                               (. boolean negated = false; .)
+[
+    "!"                                         (. negated = true; .)
+]                                        
+    Factor<out result>                          (. result = negated ? new Negate(result) : result;.)
+.
+
+
+Factor<out DSLExpression result>
+=                                               (. result = null; .)
+
+(
+    MemberExpression<out result, result>
+|
+    numericLiteral                              (. result = new IntLiteral(t.val); .)
+|
+    "("                                        
+    Expression<out result>                      
+    ")"                                        
+                                                
+)
+.
+
+MemberExpression<out DSLExpression result, DSLExpression receiver>
+=                                               (. result = null; .)
+(
+    
+    identifier                                  (. Variable variable = new Variable(receiver, t.val); .)
+                                                (. result = variable; .)
+[
+
+    "("                                         (. List<DSLExpression> parameters = new ArrayList<>();
+                                                   DSLExpression parameter; .)
+    [
+        Expression<out parameter>               (. parameters.add(parameter); .)
+        {
+            ","
+            Expression<out parameter>           (. parameters.add(parameter); .)
+        }
+    ]
+    ")"                                         (. result = new Call(variable.getReceiver(), variable.getName(), parameters); .)
+]
+                                                
+)
+[
+   "." MemberExpression<out result, result>
+]
+.
+END Expression.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/InvalidExpressionException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.expression;
+
+public class InvalidExpressionException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public InvalidExpressionException(String message) {
+        super(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,211 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+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, 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.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.util.*;
+import java.io.*;
+import java.nio.charset.*;
+
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.*;
+
+// Checkstyle: stop
+// @formatter:off
+class Parser {
+-->constants
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    
+    -->declarations
+    public Parser(InputStream input) {
+        this.scanner = new Scanner(input);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+-->pragmas
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+-->productions
+
+    private DSLExpression parseImpl() {
+        la = new Token();
+        la.val = "";
+        Get();
+        DSLExpression result = -->parseRoot
+        return result;
+    }
+
+    private static final boolean[][] set = {
+-->initialization
+    };
+
+    public static DSLExpression parse(InputStream input) {
+        Parser parser = new Parser(input);
+        DSLExpression result = parser.parseImpl();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder();
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new InvalidExpressionException(msg.toString());
+        }
+        return result;
+    }
+
+    public static DSLExpression parse(String s) {
+        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {-->errors
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Parser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.util.*;
+
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+
+// Checkstyle: stop
+// @formatter:off
+class Parser {
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _numericLiteral = 2;
+	public static final int maxT = 15;
+
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    
+    
+    public Parser(InputStream input) {
+        this.scanner = new Scanner(input);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+	DSLExpression  Expression() {
+		DSLExpression  result;
+		result = LogicFactor();
+		return result;
+	}
+
+	DSLExpression   LogicFactor() {
+		DSLExpression   result;
+		result = ComparisonFactor();
+		if (la.kind == 3) {
+			Get();
+			Token op = t; 
+			DSLExpression  right = ComparisonFactor();
+			result = new Binary(op.val, result, right); 
+		}
+		return result;
+	}
+
+	DSLExpression   ComparisonFactor() {
+		DSLExpression   result;
+		result = NegateFactor();
+		if (StartOf(1)) {
+			switch (la.kind) {
+			case 4: {
+				Get();
+				break;
+			}
+			case 5: {
+				Get();
+				break;
+			}
+			case 6: {
+				Get();
+				break;
+			}
+			case 7: {
+				Get();
+				break;
+			}
+			case 8: {
+				Get();
+				break;
+			}
+			case 9: {
+				Get();
+				break;
+			}
+			}
+			Token op = t; 
+			DSLExpression  right = NegateFactor();
+			result = new Binary(op.val, result, right); 
+		}
+		return result;
+	}
+
+	DSLExpression   NegateFactor() {
+		DSLExpression   result;
+		boolean negated = false; 
+		if (la.kind == 10) {
+			Get();
+			negated = true; 
+		}
+		result = Factor();
+		result = negated ? new Negate(result) : result;
+		return result;
+	}
+
+	DSLExpression  Factor() {
+		DSLExpression  result;
+		result = null; 
+		if (la.kind == 1) {
+			result = MemberExpression(result);
+		} else if (la.kind == 2) {
+			Get();
+			result = new IntLiteral(t.val); 
+		} else if (la.kind == 11) {
+			Get();
+			result = Expression();
+			Expect(12);
+		} else SynErr(16);
+		return result;
+	}
+
+	DSLExpression  MemberExpression(DSLExpression receiver) {
+		DSLExpression  result;
+		result = null; 
+		Expect(1);
+		Variable variable = new Variable(receiver, t.val); 
+		result = variable; 
+		if (la.kind == 11) {
+			Get();
+			List<DSLExpression> parameters = new ArrayList<>();
+			DSLExpression parameter; 
+			if (StartOf(2)) {
+				parameter = Expression();
+				parameters.add(parameter); 
+				while (la.kind == 13) {
+					Get();
+					parameter = Expression();
+					parameters.add(parameter); 
+				}
+			}
+			Expect(12);
+			result = new Call(variable.getReceiver(), variable.getName(), parameters); 
+		}
+		if (la.kind == 14) {
+			Get();
+			result = MemberExpression(result);
+		}
+		return result;
+	}
+
+
+
+    private DSLExpression parseImpl() {
+        la = new Token();
+        la.val = "";
+        Get();
+        DSLExpression result = 		Expression();
+		Expect(0);
+
+        return result;
+    }
+
+    private static final boolean[][] set = {
+		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_T,_T,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_x,_x, _x}
+
+    };
+
+    public static DSLExpression parse(InputStream input) {
+        Parser parser = new Parser(input);
+        DSLExpression result = parser.parseImpl();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder();
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new InvalidExpressionException(msg.toString());
+        }
+        return result;
+    }
+
+    public static DSLExpression parse(String s) {
+        return parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8)));
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "numericLiteral expected"; break;
+			case 3: s = "\"||\" expected"; break;
+			case 4: s = "\"<\" expected"; break;
+			case 5: s = "\"<=\" expected"; break;
+			case 6: s = "\">\" expected"; break;
+			case 7: s = "\">=\" expected"; break;
+			case 8: s = "\"==\" expected"; break;
+			case 9: s = "\"!=\" expected"; break;
+			case 10: s = "\"!\" expected"; break;
+			case 11: s = "\"(\" expected"; break;
+			case 12: s = "\")\" expected"; break;
+			case 13: s = "\",\" expected"; break;
+			case 14: s = "\".\" expected"; break;
+			case 15: s = "??? expected"; break;
+			case 16: s = "invalid Factor"; break;
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,495 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+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, 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.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+-->declarations
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+-->initialization
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+-->casing
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+-->casing2
+            NextCh();
+        }
+    }
+
+-->comments
+
+    void CheckLiteral() {
+        String val = t.val;
+-->casing3
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' || 
+-->scan1
+        ) NextCh();
+-->scan2
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+-->scan3
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/Scanner.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.dsl.processor.expression;
+
+import java.io.*;
+import java.util.*;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+	static final int maxT = 15;
+	static final int noSym = 15;
+
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+		for (int i = 36; i <= 36; ++i) start.set(i, 1);
+		for (int i = 65; i <= 90; ++i) start.set(i, 1);
+		for (int i = 95; i <= 95; ++i) start.set(i, 1);
+		for (int i = 97; i <= 122; ++i) start.set(i, 1);
+		for (int i = 49; i <= 57; ++i) start.set(i, 6);
+		start.set(48, 2);
+		start.set(124, 7);
+		start.set(60, 18);
+		start.set(62, 19);
+		start.set(61, 11);
+		start.set(33, 20);
+		start.set(40, 14);
+		start.set(41, 15);
+		start.set(44, 16);
+		start.set(46, 17);
+		start.set(Buffer.EOF, -1);
+
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+			tval[tlen++] = (char)ch;
+
+            NextCh();
+        }
+    }
+
+
+
+    void CheckLiteral() {
+        String val = t.val;
+
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' ||
+			false
+        ) NextCh();
+
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+				case 1:
+					recEnd = pos; recKind = 1;
+					if (ch == '$' || ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch == '_' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					else {t.kind = 1; break loop;}
+				case 2:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '7') {AddCh(); state = 5; break;}
+					else if (ch == 'x') {AddCh(); state = 3; break;}
+					else if (ch == 'b') {AddCh(); state = 4; break;}
+					else {t.kind = 2; break loop;}
+				case 3:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); state = 3; break;}
+					else {t.kind = 2; break loop;}
+				case 4:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '1') {AddCh(); state = 4; break;}
+					else {t.kind = 2; break loop;}
+				case 5:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '7') {AddCh(); state = 5; break;}
+					else {t.kind = 2; break loop;}
+				case 6:
+					recEnd = pos; recKind = 2;
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 6; break;}
+					else {t.kind = 2; break loop;}
+				case 7:
+					if (ch == '|') {AddCh(); state = 8; break;}
+					else {state = 0; break;}
+				case 8:
+					{t.kind = 3; break loop;}
+				case 9:
+					{t.kind = 5; break loop;}
+				case 10:
+					{t.kind = 7; break loop;}
+				case 11:
+					if (ch == '=') {AddCh(); state = 12; break;}
+					else {state = 0; break;}
+				case 12:
+					{t.kind = 8; break loop;}
+				case 13:
+					{t.kind = 9; break loop;}
+				case 14:
+					{t.kind = 11; break loop;}
+				case 15:
+					{t.kind = 12; break loop;}
+				case 16:
+					{t.kind = 13; break loop;}
+				case 17:
+					{t.kind = 14; break loop;}
+				case 18:
+					recEnd = pos; recKind = 4;
+					if (ch == '=') {AddCh(); state = 9; break;}
+					else {t.kind = 4; break loop;}
+				case 19:
+					recEnd = pos; recKind = 6;
+					if (ch == '=') {AddCh(); state = 10; break;}
+					else {t.kind = 6; break loop;}
+				case 20:
+					recEnd = pos; recKind = 10;
+					if (ch == '=') {AddCh(); state = 13; break;}
+					else {t.kind = 10; break loop;}
+
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/CodeTypeElementFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class CodeTypeElementFactory<M> {
+
+    public abstract CodeTypeElement create(ProcessorContext context, M m);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/DSLExpressionGenerator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Call;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionVisitor;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.IntLiteral;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class DSLExpressionGenerator implements DSLExpressionVisitor {
+
+    private final Map<Variable, CodeTree> bindings;
+    private final CodeTree root;
+    private final Deque<CodeTree> stack = new ArrayDeque<>();
+
+    public DSLExpressionGenerator(CodeTree root, Map<Variable, CodeTree> bindings) {
+        this.bindings = bindings;
+        this.root = root;
+    }
+
+    public void visitBinary(Binary binary) {
+        CodeTree right = stack.pop();
+        CodeTree left = stack.pop();
+        stack.push(combine(left, string(" " + binary.getOperator() + " "), right));
+    }
+
+    public void visitCall(Call call) {
+        ExecutableElement method = call.getResolvedMethod();
+        CodeTree[] parameters = new CodeTree[method.getParameters().size()];
+        for (int i = 0; i < parameters.length; i++) {
+            parameters[parameters.length - i - 1] = pop();
+        }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        if (call.getResolvedMethod().getKind() == ElementKind.CONSTRUCTOR) {
+            builder.startNew(call.getResolvedType());
+        } else if (call.getReceiver() == null) {
+            if (isStatic(method)) {
+                builder.startStaticCall(method);
+            } else {
+                if (root != null) {
+                    builder.tree(root).string(".");
+                }
+                builder.startCall(method.getSimpleName().toString());
+            }
+        } else {
+            if (isStatic(method)) {
+                throw new AssertionError("Static calls must not have receivers.");
+            }
+            builder.startCall(pop(), method.getSimpleName().toString());
+        }
+        for (CodeTree parameter : parameters) {
+            builder.tree(parameter);
+        }
+        builder.end();
+
+        push(builder.build());
+    }
+
+    public void visitIntLiteral(IntLiteral binary) {
+        push(string(binary.getLiteral()));
+    }
+
+    public void visitNegate(Negate negate) {
+        push(combine(string("!"), combine(string("("), pop(), string(")"))));
+    }
+
+    public void visitVariable(Variable variable) {
+        VariableElement resolvedVariable = variable.getResolvedVariable();
+        CodeTree tree;
+        if (variable.getResolvedType().getKind() == TypeKind.NULL) {
+            tree = CodeTreeBuilder.singleString("null");
+        } else if (variable.getReceiver() == null) {
+
+            if (isStatic(resolvedVariable)) {
+                tree = staticReference(resolvedVariable);
+            } else {
+                tree = bindings.get(variable);
+                boolean bound = true;
+                if (tree == null) {
+                    tree = string(resolvedVariable.getSimpleName().toString());
+                    bound = false;
+                }
+                if (root != null && !bound) {
+                    tree = combine(root, string("."), tree);
+                }
+            }
+        } else {
+            if (isStatic(resolvedVariable)) {
+                throw new AssertionError("Static variables cannot have receivers.");
+            }
+            tree = combine(pop(), string("."), string(resolvedVariable.getSimpleName().toString()));
+        }
+        push(tree);
+    }
+
+    private static boolean isStatic(Element element) {
+        return element.getModifiers().contains(Modifier.STATIC);
+    }
+
+    private static CodeTree combine(CodeTree tree1, CodeTree tree2) {
+        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).end().build();
+    }
+
+    private static CodeTree combine(CodeTree tree1, CodeTree tree2, CodeTree tree3) {
+        return new CodeTreeBuilder(null).startGroup().tree(tree1).tree(tree2).tree(tree3).end().build();
+    }
+
+    private static CodeTree string(String s) {
+        return CodeTreeBuilder.singleString(s);
+    }
+
+    private static CodeTree staticReference(VariableElement var) {
+        return CodeTreeBuilder.createBuilder().staticReference(var.getEnclosingElement().asType(), var.getSimpleName().toString()).build();
+    }
+
+    private void push(CodeTree tree) {
+        stack.push(tree);
+    }
+
+    private CodeTree pop() {
+        return stack.pop();
+    }
+
+    public static CodeTree write(DSLExpression expression, CodeTree root, Map<Variable, CodeTree> bindings) {
+        DSLExpressionGenerator writer = new DSLExpressionGenerator(root, bindings);
+        expression.accept(writer);
+        return combine(string("("), writer.pop(), string(")"));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/GeneratorUtils.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.DSLOptions.TypeBoxingOptimization;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class GeneratorUtils {
+
+    public static CodeTree createTransferToInterpreterAndInvalidate() {
+        ProcessorContext context = ProcessorContext.getInstance();
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startStatement().startStaticCall(context.getType(CompilerDirectives.class), "transferToInterpreterAndInvalidate").end().end();
+        return builder.build();
+    }
+
+    public static CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz) {
+        TypeElement superClass = fromTypeMirror(clazz.getSuperclass());
+        ExecutableElement constructor = findConstructor(superClass);
+        return createConstructorUsingFields(modifiers, clazz, constructor);
+    }
+
+    public static CodeExecutableElement createConstructorUsingFields(Set<Modifier> modifiers, CodeTypeElement clazz, ExecutableElement constructor) {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers, null, clazz.getSimpleName().toString());
+        CodeTreeBuilder builder = method.createBuilder();
+        if (constructor != null && constructor.getParameters().size() > 0) {
+            builder.startStatement();
+            builder.startSuperCall();
+            for (VariableElement parameter : constructor.getParameters()) {
+                method.addParameter(new CodeVariableElement(parameter.asType(), parameter.getSimpleName().toString()));
+                builder.string(parameter.getSimpleName().toString());
+            }
+            builder.end(); // super
+            builder.end(); // statement
+        }
+
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(STATIC)) {
+                continue;
+            }
+            String fieldName = field.getSimpleName().toString();
+            method.addParameter(new CodeVariableElement(field.asType(), fieldName));
+            builder.startStatement();
+            builder.string("this.");
+            builder.string(fieldName);
+            builder.string(" = ");
+            builder.string(fieldName);
+            builder.end(); // statement
+        }
+
+        return method;
+    }
+
+    public static boolean isTypeBoxingOptimized(TypeBoxingOptimization boxing, TypeMirror type) {
+        switch (boxing) {
+            case NONE:
+                return false;
+            case ALWAYS:
+                return !ElementUtils.isObject(type) && !ElementUtils.isVoid(type);
+            case PRIMITIVE:
+                return ElementUtils.isPrimitive(type);
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    private static ExecutableElement findConstructor(TypeElement clazz) {
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(clazz.getEnclosedElements());
+        if (constructors.isEmpty()) {
+            return null;
+        } else {
+            return constructors.get(0);
+        }
+    }
+
+    public static CodeExecutableElement createSuperConstructor(ProcessorContext context, TypeElement type, ExecutableElement element) {
+        if (element.getModifiers().contains(Modifier.PRIVATE)) {
+            return null;
+        }
+        CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), element);
+        executable.setReturnType(null);
+        executable.setSimpleName(CodeNames.of(type.getSimpleName().toString()));
+        CodeTreeBuilder b = executable.createBuilder();
+        b.startStatement();
+        b.startSuperCall();
+        for (VariableElement v : element.getParameters()) {
+            b.string(v.getSimpleName().toString());
+        }
+        b.end();
+        b.end();
+
+        return executable;
+    }
+
+    public static CodeTypeElement createClass(Template sourceModel, TemplateMethod sourceMethod, Set<Modifier> modifiers, String simpleName, TypeMirror superType) {
+        TypeElement templateType = sourceModel.getTemplateType();
+
+        ProcessorContext context = ProcessorContext.getInstance();
+
+        PackageElement pack = context.getEnvironment().getElementUtils().getPackageOf(templateType);
+        CodeTypeElement clazz = new CodeTypeElement(modifiers, ElementKind.CLASS, pack, simpleName);
+        TypeMirror resolvedSuperType = superType;
+        if (resolvedSuperType == null) {
+            resolvedSuperType = context.getType(Object.class);
+        }
+        clazz.setSuperClass(resolvedSuperType);
+
+        CodeAnnotationMirror generatedByAnnotation = new CodeAnnotationMirror((DeclaredType) context.getType(GeneratedBy.class));
+        generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("value"), new CodeAnnotationValue(templateType.asType()));
+        if (sourceMethod != null && sourceMethod.getMethod() != null) {
+            generatedByAnnotation.setElementValue(generatedByAnnotation.findExecutableElement("methodName"), new CodeAnnotationValue(sourceMethod.createReferenceName()));
+        }
+
+        clazz.addAnnotationMirror(generatedByAnnotation);
+        return clazz;
+    }
+
+    public static List<ExecutableElement> findUserConstructors(TypeMirror nodeType) {
+        List<ExecutableElement> constructors = new ArrayList<>();
+        for (ExecutableElement constructor : ElementFilter.constructorsIn(ElementUtils.fromTypeMirror(nodeType).getEnclosedElements())) {
+            if (constructor.getModifiers().contains(PRIVATE)) {
+                continue;
+            }
+            if (isCopyConstructor(constructor)) {
+                continue;
+            }
+            constructors.add(constructor);
+        }
+
+        if (constructors.isEmpty()) {
+            constructors.add(new CodeExecutableElement(null, ElementUtils.getSimpleName(nodeType)));
+        }
+
+        return constructors;
+    }
+
+    public static boolean isCopyConstructor(ExecutableElement element) {
+        if (element.getParameters().size() != 1) {
+            return false;
+        }
+        VariableElement var = element.getParameters().get(0);
+        TypeElement enclosingType = ElementUtils.findNearestEnclosingType(var);
+        if (ElementUtils.typeEquals(var.asType(), enclosingType.asType())) {
+            return true;
+        }
+        List<TypeElement> types = ElementUtils.getDirectSuperTypes(enclosingType);
+        for (TypeElement type : types) {
+            if (!(type instanceof CodeTypeElement)) {
+                // no copy constructors which are not generated types
+                return false;
+            }
+
+            if (ElementUtils.typeEquals(var.asType(), type.asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ImplicitCastNodeFactory {
+
+    private final ProcessorContext context;
+    private final TypeMirror forType;
+    private final TypeSystemData typeSystem;
+    private final DSLOptions options;
+    private final List<TypeMirror> sourceTypes;
+
+    public ImplicitCastNodeFactory(ProcessorContext context, TypeSystemData typeSystem, TypeMirror forType) {
+        this.context = context;
+        this.forType = forType;
+        this.typeSystem = typeSystem;
+        this.options = typeSystem.getOptions();
+        this.sourceTypes = typeSystem.lookupSourceTypes(forType);
+    }
+
+    public static String typeName(TypeMirror type) {
+        return "Implicit" + getTypeId(type) + "Cast";
+    }
+
+    public static TypeMirror type(TypeSystemData typeSystem, TypeMirror type) {
+        String typeSystemName = TypeSystemCodeGenerator.typeName(typeSystem);
+        return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()) + "." + typeSystemName, typeName(type));
+    }
+
+    public static CodeTree create(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
+        return CodeTreeBuilder.createBuilder().startStaticCall(type(typeSystem, type), "create").tree(value).end().build();
+    }
+
+    public static CodeTree cast(String nodeName, CodeTree value) {
+        return CodeTreeBuilder.createBuilder().startCall(nodeName, "cast").tree(value).end().build();
+    }
+
+    public static CodeTree check(String nodeName, CodeTree value) {
+        return CodeTreeBuilder.createBuilder().startCall(nodeName, "check").tree(value).end().build();
+    }
+
+    private static String seenFieldName(TypeMirror type) {
+        return "seen" + getTypeId(type);
+    }
+
+    public CodeTypeElement create() {
+        String typeName = typeName(forType);
+        TypeMirror baseType = context.getType(Object.class);
+        CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL, STATIC), typeName, baseType);
+
+        for (TypeMirror sourceType : sourceTypes) {
+            CodeVariableElement hasSeen = new CodeVariableElement(modifiers(PUBLIC), context.getType(boolean.class), seenFieldName(sourceType));
+            hasSeen.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
+            clazz.add(hasSeen);
+        }
+
+        clazz.add(createConstructor(clazz));
+        if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), forType)) {
+            clazz.add(createIsMonomorphic());
+        }
+        clazz.add(createCast(false));
+        clazz.add(createCast(true));
+        clazz.add(createCheck());
+        clazz.add(createMerge(clazz));
+        clazz.add(createCreate(clazz));
+
+        return clazz;
+    }
+
+    private Element createIsMonomorphic() {
+        String methodName = "isMonomorphic";
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName);
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startReturn();
+        String operator = "";
+        for (TypeMirror sourceType : sourceTypes) {
+            builder.string(operator);
+            builder.string(seenFieldName(sourceType));
+            operator = " ^ ";
+        }
+        builder.end();
+        return method;
+    }
+
+    private static Element createConstructor(CodeTypeElement clazz) {
+        return new CodeExecutableElement(modifiers(PRIVATE), null, clazz.getSimpleName().toString());
+    }
+
+    private Element createCreate(CodeTypeElement clazz) {
+        String methodName = "create";
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), clazz.asType(), methodName);
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
+        CodeTreeBuilder builder = method.createBuilder();
+
+        builder.declaration(clazz.asType(), "newCast", builder.create().startNew(clazz.asType()).end());
+
+        for (TypeMirror sourceType : sourceTypes) {
+            String seenField = seenFieldName(sourceType);
+            builder.startStatement();
+            builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
+            builder.end();
+        }
+        builder.startReturn().string("newCast").end();
+        return method;
+    }
+
+    private Element createMerge(CodeTypeElement clazz) {
+        String methodName = "merge";
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), methodName);
+        method.addParameter(new CodeVariableElement(clazz.asType(), "otherCast"));
+        CodeTreeBuilder builder = method.createBuilder();
+
+        for (TypeMirror sourceType : sourceTypes) {
+            String seenField = seenFieldName(sourceType);
+            builder.startStatement();
+            builder.string("this.").string(seenField).string(" |= ").string("otherCast.").string(seenField);
+            builder.end();
+        }
+        return method;
+    }
+
+    private Element createCheck() {
+        String methodName = "check";
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName);
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
+        CodeTreeBuilder builder = method.createBuilder();
+
+        boolean elseIf = false;
+        for (TypeMirror sourceType : sourceTypes) {
+            elseIf = builder.startIf(elseIf);
+            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
+            builder.end();
+            builder.startBlock().returnTrue().end();
+        }
+        builder.returnFalse();
+        return method;
+    }
+
+    private Element createCast(boolean expect) {
+        String methodName = expect ? "expect" : "cast";
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType, methodName);
+        method.addParameter(new CodeVariableElement(context.getType(Object.class), "value"));
+        if (expect) {
+            method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
+        }
+
+        CodeTreeBuilder builder = method.createBuilder();
+
+        boolean elseIf = false;
+        for (TypeMirror sourceType : sourceTypes) {
+            elseIf = builder.startIf(elseIf);
+            builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(typeSystem, sourceType, "value"));
+            builder.end();
+            builder.startBlock();
+            builder.startReturn();
+            CodeTree castTree = TypeSystemCodeGenerator.cast(typeSystem, sourceType, "value");
+            ImplicitCastData cast = typeSystem.lookupCast(sourceType, forType);
+            if (cast != null) {
+                builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(typeSystem, cast, castTree));
+            } else {
+                builder.tree(castTree);
+            }
+            builder.end();
+            builder.end();
+        }
+        if (expect) {
+            builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string("value").end().end();
+        } else {
+            builder.startStatement().startStaticCall(context.getType(CompilerDirectives.class), "transferToInterpreter").end().end();
+            builder.startThrow().startNew(context.getType(AssertionError.class)).end().end();
+        }
+        return method;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class NodeCodeGenerator extends CodeTypeElementFactory<NodeData> {
+
+    @Override
+    public CodeTypeElement create(ProcessorContext context, NodeData node) {
+        List<CodeTypeElement> enclosedTypes = new ArrayList<>();
+        for (NodeData childNode : node.getEnclosingNodes()) {
+            CodeTypeElement type = create(context, childNode);
+            if (type != null) {
+                enclosedTypes.add(type);
+            }
+        }
+        List<CodeTypeElement> generatedNodes = generateNodes(context, node);
+
+        if (!generatedNodes.isEmpty() || !enclosedTypes.isEmpty()) {
+            CodeTypeElement type;
+            if (generatedNodes.isEmpty()) {
+                type = createContainer(node);
+            } else {
+                type = wrapGeneratedNodes(context, node, generatedNodes);
+            }
+
+            for (CodeTypeElement enclosedFactory : enclosedTypes) {
+                type.add(makeInnerClass(enclosedFactory));
+            }
+
+            if (node.getDeclaringNode() == null && enclosedTypes.size() > 0) {
+                ExecutableElement getFactories = createGetFactories(context, node);
+                if (getFactories != null) {
+                    type.add(getFactories);
+                }
+            }
+
+            return type;
+        } else {
+            return null;
+        }
+    }
+
+    private static CodeTypeElement makeInnerClass(CodeTypeElement type) {
+        Set<Modifier> modifiers = type.getModifiers();
+        modifiers.add(Modifier.STATIC);
+        return type;
+    }
+
+    private static CodeTypeElement wrapGeneratedNodes(ProcessorContext context, NodeData node, List<CodeTypeElement> generatedNodes) {
+        if (node.isGenerateFactory()) {
+            // wrap all types into a generated factory
+            CodeTypeElement factoryElement = new NodeFactoryFactory(context, node, generatedNodes.get(0)).create();
+            for (CodeTypeElement generatedNode : generatedNodes) {
+                factoryElement.add(makeInnerClass(generatedNode));
+            }
+            return factoryElement;
+        } else {
+            // wrap all types into the first node
+            CodeTypeElement first = generatedNodes.get(0);
+            CodeTypeElement second = first;
+            if (generatedNodes.size() > 1) {
+                second = generatedNodes.get(1);
+                for (CodeTypeElement generatedNode : generatedNodes) {
+                    if (first != generatedNode) {
+                        first.add(makeInnerClass(generatedNode));
+                    }
+                }
+            }
+            new NodeFactoryFactory(context, node, second).createFactoryMethods(first);
+            ElementUtils.setVisibility(first.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
+
+            return first;
+        }
+    }
+
+    private static CodeTypeElement createContainer(NodeData node) {
+        CodeTypeElement container;
+        Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
+        String containerName = NodeFactoryFactory.factoryClassName(node);
+        container = GeneratorUtils.createClass(node, null, modifiers(), containerName, null);
+        if (visibility != null) {
+            container.getModifiers().add(visibility);
+        }
+        container.getModifiers().add(Modifier.FINAL);
+
+        return container;
+    }
+
+    private static String getAccessorClassName(NodeData node) {
+        return node.isGenerateFactory() ? NodeFactoryFactory.factoryClassName(node) : NodeGenFactory.nodeTypeName(node);
+    }
+
+    private static List<CodeTypeElement> generateNodes(ProcessorContext context, NodeData node) {
+        if (!node.needsFactory()) {
+            return Collections.emptyList();
+        }
+        return Arrays.asList(new NodeGenFactory(context, node).create());
+    }
+
+    private static ExecutableElement createGetFactories(ProcessorContext context, NodeData node) {
+        List<NodeData> factoryList = node.getNodesWithFactories();
+        if (node.needsFactory() && node.isGenerateFactory()) {
+            factoryList.add(node);
+        }
+
+        if (factoryList.isEmpty()) {
+            return null;
+        }
+
+        List<TypeMirror> nodeTypesList = new ArrayList<>();
+        TypeMirror prev = null;
+        boolean allSame = true;
+        for (NodeData child : factoryList) {
+            nodeTypesList.add(child.getNodeType());
+            if (prev != null && !ElementUtils.typeEquals(child.getNodeType(), prev)) {
+                allSame = false;
+            }
+            prev = child.getNodeType();
+        }
+        TypeMirror commonNodeSuperType = ElementUtils.getCommonSuperType(context, nodeTypesList);
+
+        Types types = context.getEnvironment().getTypeUtils();
+        TypeMirror factoryType = context.getType(NodeFactory.class);
+        TypeMirror baseType;
+        if (allSame) {
+            baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), commonNodeSuperType);
+        } else {
+            baseType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(factoryType), types.getWildcardType(commonNodeSuperType, null));
+        }
+        TypeMirror listType = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getType(List.class)), baseType);
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories");
+
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startReturn();
+
+        if (factoryList.size() > 1) {
+            builder.startStaticCall(context.getType(Arrays.class), "asList");
+        } else {
+            builder.startStaticCall(context.getType(Collections.class), "singletonList");
+        }
+
+        for (NodeData child : factoryList) {
+            builder.startGroup();
+            NodeData childNode = child;
+            List<NodeData> factories = new ArrayList<>();
+            while (childNode.getDeclaringNode() != null) {
+                factories.add(childNode);
+                childNode = childNode.getDeclaringNode();
+            }
+            Collections.reverse(factories);
+            for (NodeData nodeData : factories) {
+
+                builder.string(getAccessorClassName(nodeData)).string(".");
+            }
+            builder.string("getInstance()");
+            builder.end();
+        }
+        builder.end();
+        builder.end();
+
+        return method;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeFactoryFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class NodeFactoryFactory {
+
+    static final String EMPTY_CLASS_ARRAY = "EMPTY_CLASS_ARRAY";
+
+    private final ProcessorContext context;
+    private final NodeData node;
+    private final CodeTypeElement createdFactoryElement;
+
+    public NodeFactoryFactory(ProcessorContext context, NodeData node, CodeTypeElement createdClass) {
+        this.context = context;
+        this.node = node;
+        this.createdFactoryElement = createdClass;
+    }
+
+    public static String factoryClassName(NodeData node) {
+        return node.getNodeId() + "Factory";
+    }
+
+    public CodeTypeElement create() {
+        Modifier visibility = ElementUtils.getVisibility(node.getTemplateType().getModifiers());
+        TypeMirror nodeFactory = ElementUtils.getDeclaredType(ElementUtils.fromTypeMirror(context.getTruffleTypes().getNodeFactoryBase()), node.getNodeType());
+
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(), factoryClassName(node), null);
+        if (visibility != null) {
+            clazz.getModifiers().add(visibility);
+        }
+        clazz.getModifiers().add(Modifier.FINAL);
+
+        if (createdFactoryElement != null) {
+            clazz.setSuperClass(nodeFactory);
+            clazz.add(createNodeFactoryConstructor());
+            clazz.add(createCreateNodeMethod());
+            clazz.add(createGetInstanceMethod(visibility));
+            clazz.add(createInstanceConstant(clazz.asType()));
+            createFactoryMethods(clazz);
+        }
+
+        return clazz;
+    }
+
+    private Element createNodeFactoryConstructor() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), null, factoryClassName(node));
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startStatement();
+        builder.startCall("super");
+
+        // node type
+        builder.typeLiteral(node.getNodeType());
+
+        // execution signature
+        builder.startGroup();
+        if (node.getChildExecutions().isEmpty()) {
+            builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+        } else {
+            builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+            for (NodeExecutionData execution : node.getChildExecutions()) {
+                builder.typeLiteral(execution.getNodeType());
+            }
+            builder.end();
+        }
+        builder.end();
+
+        // node signatures
+        builder.startGroup();
+        builder.startNewArray(new ArrayCodeTypeMirror(new ArrayCodeTypeMirror(context.getType(Class.class))), null);
+        List<ExecutableElement> constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
+        for (ExecutableElement constructor : constructors) {
+            builder.startGroup();
+            if (constructor.getParameters().isEmpty()) {
+                builder.staticReference(context.getTruffleTypes().getDslMetadata(), EMPTY_CLASS_ARRAY);
+            } else {
+                builder.startNewArray(new ArrayCodeTypeMirror(context.getType(Class.class)), null);
+                for (VariableElement var : constructor.getParameters()) {
+                    builder.typeLiteral(var.asType());
+                }
+                builder.end();
+            }
+            builder.end();
+        }
+        builder.end();
+        builder.end();
+
+        builder.end().end().end();
+        return method;
+    }
+
+    private CodeExecutableElement createCreateNodeMethod() {
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), node.getNodeType(), "createNode");
+        CodeVariableElement arguments = new CodeVariableElement(context.getType(Object.class), "arguments");
+        method.setVarArgs(true);
+        method.addParameter(arguments);
+
+        CodeTreeBuilder builder = method.createBuilder();
+        List<ExecutableElement> signatures = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
+        boolean ifStarted = false;
+
+        for (ExecutableElement element : signatures) {
+            ifStarted = builder.startIf(ifStarted);
+            builder.string("arguments.length == " + element.getParameters().size());
+
+            int index = 0;
+            for (VariableElement param : element.getParameters()) {
+                if (ElementUtils.isObject(param.asType())) {
+                    continue;
+                }
+                builder.string(" && ");
+                if (!param.asType().getKind().isPrimitive()) {
+                    builder.string("(arguments[" + index + "] == null || ");
+                }
+                builder.string("arguments[" + index + "] instanceof ");
+                builder.type(ElementUtils.boxType(context, param.asType()));
+                if (!param.asType().getKind().isPrimitive()) {
+                    builder.string(")");
+                }
+                index++;
+            }
+            builder.end();
+            builder.startBlock();
+
+            builder.startReturn().startCall("create");
+            index = 0;
+            for (VariableElement param : element.getParameters()) {
+                builder.startGroup();
+                if (!ElementUtils.isObject(param.asType())) {
+                    builder.string("(").type(param.asType()).string(") ");
+                }
+                builder.string("arguments[").string(String.valueOf(index)).string("]");
+                builder.end();
+                index++;
+            }
+            builder.end().end();
+
+            builder.end(); // block
+        }
+
+        builder.startElseBlock();
+        builder.startThrow().startNew(context.getType(IllegalArgumentException.class));
+        builder.doubleQuote("Invalid create signature.");
+        builder.end().end();
+        builder.end(); // else block
+        return method;
+    }
+
+    private ExecutableElement createGetInstanceMethod(Modifier visibility) {
+        TypeElement nodeFactoryType = ElementUtils.fromTypeMirror(context.getType(NodeFactory.class));
+        TypeMirror returnType = ElementUtils.getDeclaredType(nodeFactoryType, node.getNodeType());
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(), returnType, "getInstance");
+        if (visibility != null) {
+            method.getModifiers().add(visibility);
+        }
+        method.getModifiers().add(Modifier.STATIC);
+
+        String varName = instanceVarName(node);
+
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startIf();
+        builder.string(varName).string(" == null");
+        builder.end().startBlock();
+
+        builder.startStatement();
+        builder.string(varName);
+        builder.string(" = ");
+        builder.startNew(factoryClassName(node)).end();
+        builder.end();
+
+        builder.end();
+        builder.startReturn().string(varName).end();
+        return method;
+    }
+
+    private static String instanceVarName(NodeData node) {
+        if (node.getDeclaringNode() != null) {
+            return ElementUtils.firstLetterLowerCase(factoryClassName(node)) + "Instance";
+        } else {
+            return "instance";
+        }
+    }
+
+    private CodeVariableElement createInstanceConstant(TypeMirror factoryType) {
+        String varName = instanceVarName(node);
+        CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName);
+        var.getModifiers().add(Modifier.PRIVATE);
+        var.getModifiers().add(Modifier.STATIC);
+        return var;
+    }
+
+    public void createFactoryMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> constructors = GeneratorUtils.findUserConstructors(createdFactoryElement.asType());
+        for (ExecutableElement constructor : constructors) {
+            clazz.add(createCreateMethod(constructor));
+            if (constructor instanceof CodeExecutableElement) {
+                ElementUtils.setVisibility(constructor.getModifiers(), Modifier.PRIVATE);
+            }
+        }
+    }
+
+    private CodeExecutableElement createCreateMethod(ExecutableElement constructor) {
+        CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), constructor);
+        method.setSimpleName(CodeNames.of("create"));
+        method.getModifiers().clear();
+        method.getModifiers().add(Modifier.PUBLIC);
+        method.getModifiers().add(Modifier.STATIC);
+        method.setReturnType(node.getNodeType());
+
+        CodeTreeBuilder body = method.createBuilder();
+        body.startReturn();
+        if (node.getSpecializations().isEmpty()) {
+            body.nullLiteral();
+        } else {
+            body.startNew(NodeGenFactory.nodeType(node));
+            for (VariableElement var : method.getParameters()) {
+                body.string(var.getSimpleName().toString());
+            }
+            body.end();
+
+        }
+        body.end();
+        return method;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeGenFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3044 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.dsl.internal.DSLOptions.ImplicitCastOptimization;
+import com.oracle.truffle.api.dsl.internal.DSLOptions.TypeBoxingOptimization;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.parser.*;
+import com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard;
+
+public class NodeGenFactory {
+
+    private static final String FRAME_VALUE = TemplateMethod.FRAME_NAME;
+    private static final String NAME_SUFFIX = "_";
+    private static final String NODE_SUFFIX = "NodeGen";
+
+    private final ProcessorContext context;
+    private final NodeData node;
+    private final TypeSystemData typeSystem;
+    private final TypeMirror genericType;
+    private final DSLOptions options;
+    private final boolean singleSpecializable;
+    private final int varArgsThreshold;
+    private final Set<TypeMirror> expectedTypes = new HashSet<>();
+    private final Set<NodeExecutionData> usedExecuteChildMethods = new HashSet<>();
+    private boolean nextUsed;
+    private boolean singleSpecializableUnsupportedUsed;
+
+    private List<ExecutableTypeData> usedTypes;
+    private List<SpecializationData> reachableSpecializations;
+
+    public NodeGenFactory(ProcessorContext context, NodeData node) {
+        this.context = context;
+        this.node = node;
+        this.typeSystem = node.getTypeSystem();
+        this.genericType = context.getType(Object.class);
+        this.options = typeSystem.getOptions();
+        this.varArgsThreshold = calculateVarArgsThreshold();
+        this.reachableSpecializations = calculateReachableSpecializations();
+        this.singleSpecializable = isSingleSpecializableImpl();
+        this.usedTypes = filterBaseExecutableTypes(node.getExecutableTypes(), reachableSpecializations);
+    }
+
+    private int calculateVarArgsThreshold() {
+        TypeMirror specialization = context.getType(SpecializationNode.class);
+        TypeElement specializationType = fromTypeMirror(specialization);
+
+        int maxParameters = 0;
+        for (ExecutableElement element : ElementFilter.methodsIn(specializationType.getEnclosedElements())) {
+            if (element.getSimpleName().contentEquals("acceptAndExecute")) {
+                maxParameters = Math.max(maxParameters, element.getParameters().size());
+            }
+        }
+        return maxParameters;
+    }
+
+    public static String nodeTypeName(NodeData node) {
+        return resolveNodeId(node) + NODE_SUFFIX;
+    }
+
+    private static String assumptionName(AssumptionExpression assumption) {
+        return assumption.getId() + NAME_SUFFIX;
+    }
+
+    private static String resolveNodeId(NodeData node) {
+        String nodeid = node.getNodeId();
+        if (nodeid.endsWith("Node") && !nodeid.equals("Node")) {
+            nodeid = nodeid.substring(0, nodeid.length() - 4);
+        }
+        return nodeid;
+    }
+
+    public static TypeMirror nodeType(NodeData node) {
+        return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()), nodeTypeName(node));
+    }
+
+    private static String specializationTypeName(SpecializationData specialization) {
+        String id;
+        if (specialization == null) {
+            id = "Base";
+        } else {
+            id = specialization.getId();
+        }
+        return id + "Node_";
+    }
+
+    private TypeMirror specializationType(SpecializationData specialization) {
+        return new GeneratedTypeMirror(ElementUtils.getPackageName(node.getTemplateType()) + "." + nodeTypeName(node), specializationTypeName(specialization));
+    }
+
+    private static String polymorphicTypeProfileFieldName(NodeExecutionData execution) {
+        return execution.getName() + "Type" + NAME_SUFFIX;
+    }
+
+    private static String nodeFieldName(NodeExecutionData execution) {
+        return execution.getName() + NAME_SUFFIX;
+    }
+
+    private static String specializationStartFieldName() {
+        return "specialization" + NAME_SUFFIX;
+    }
+
+    private static String excludedFieldName(SpecializationData specialization) {
+        return "exclude" + specialization.getId() + NAME_SUFFIX;
+    }
+
+    private static String executeChildMethodName(NodeExecutionData execution, TypeMirror type) {
+        return "execute" + ElementUtils.firstLetterUpperCase(execution.getName()) + (ElementUtils.isObject(type) ? "" : getTypeId(type)) + NAME_SUFFIX;
+    }
+
+    private CodeTree accessParent(String name) {
+        if (singleSpecializable) {
+            if (name == null) {
+                return CodeTreeBuilder.singleString("this");
+            } else {
+                return CodeTreeBuilder.singleString(name);
+            }
+        } else {
+            if (name == null) {
+                return CodeTreeBuilder.singleString("root");
+            } else {
+                return CodeTreeBuilder.createBuilder().string("root.").string(name).build();
+            }
+        }
+    }
+
+    public CodeTypeElement create() {
+        CodeTypeElement clazz = GeneratorUtils.createClass(node, null, modifiers(FINAL), nodeTypeName(node), node.getTemplateType().asType());
+        ElementUtils.setVisibility(clazz.getModifiers(), ElementUtils.getVisibility(node.getTemplateType().getModifiers()));
+
+        for (NodeChildData child : node.getChildren()) {
+            clazz.addOptional(createAccessChildMethod(child));
+        }
+
+        for (NodeFieldData field : node.getFields()) {
+            if (!field.isGenerated()) {
+                continue;
+            }
+
+            clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), field.getType(), field.getName()));
+            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
+                CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), field.getGetter());
+                method.getModifiers().remove(Modifier.ABSTRACT);
+                method.createBuilder().startReturn().string("this.").string(field.getName()).end();
+                clazz.add(method);
+            }
+        }
+
+        for (ExecutableElement superConstructor : GeneratorUtils.findUserConstructors(node.getTemplateType().asType())) {
+            clazz.add(createNodeConstructor(clazz, superConstructor));
+        }
+
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.getChild() != null) {
+                clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), Child.class));
+            }
+        }
+
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!resolvePolymorphicExecutables(execution).isEmpty()) {
+                clazz.add(createNodeField(PRIVATE, getType(Class.class), polymorphicTypeProfileFieldName(execution), CompilationFinal.class));
+            }
+        }
+
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (mayBeExcluded(specialization)) {
+                clazz.add(createNodeField(PRIVATE, getType(boolean.class), excludedFieldName(specialization), CompilationFinal.class));
+            }
+        }
+
+        clazz.add(createGetCostMethod());
+
+        avoidFindbugsProblems(clazz);
+
+        if (singleSpecializable) {
+            SpecializationData specialization = reachableSpecializations.iterator().next();
+
+            for (ExecutableTypeData execType : usedTypes) {
+                if (execType.getMethod() == null) {
+                    boolean foundDelegate = false;
+                    for (ExecutableTypeData type : usedTypes) {
+                        if (type == execType) {
+                            continue;
+                        }
+                        if (findFastPathDelegate(specialization.getReturnType().getType(), type, usedTypes) == execType) {
+                            foundDelegate = true;
+                            break;
+                        }
+                    }
+                    // just exclude synthetic execute methods that were not delegated to
+                    if (!foundDelegate) {
+                        continue;
+                    }
+                }
+
+                clazz.add(createExecutableTypeOverride(usedTypes, execType));
+            }
+
+            if (singleSpecializableUnsupportedUsed) {
+                addUnsupportedMethod(clazz);
+            }
+        } else {
+
+            for (ExecutableTypeData execType : usedTypes) {
+                if (execType.getMethod() == null) {
+                    continue;
+                }
+                clazz.add(createExecutableTypeOverride(usedTypes, execType));
+            }
+
+            clazz.getImplements().add(getType(SpecializedNode.class));
+            clazz.add(createMethodGetSpecializationNode());
+            clazz.add(createDeepCopyMethod());
+            SpecializationData specializationStart = createSpecializations(clazz);
+            clazz.add(createNodeField(PRIVATE, specializationType(null), specializationStartFieldName(), Child.class));
+
+            for (ExecutableElement constructor : ElementFilter.constructorsIn(clazz.getEnclosedElements())) {
+                CodeTreeBuilder builder = ((CodeExecutableElement) constructor).appendBuilder();
+                builder.startStatement();
+                builder.string("this.").string(specializationStartFieldName());
+                builder.string(" = ").tree(createCallCreateMethod(specializationStart, "this", null));
+                builder.end();
+            }
+        }
+
+        for (TypeMirror type : ElementUtils.uniqueSortedTypes(expectedTypes, false)) {
+            if (!typeSystem.hasType(type)) {
+                clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type));
+            }
+        }
+
+        return clazz;
+    }
+
+    private void avoidFindbugsProblems(CodeTypeElement clazz) {
+        TypeElement type = context.getEnvironment().getElementUtils().getTypeElement("edu.umd.cs.findbugs.annotations.SuppressFBWarnings");
+        if (type == null) {
+            return;
+        }
+        boolean foundComparison = false;
+        outer: for (SpecializationData specialization : node.getSpecializations()) {
+            for (GuardExpression guard : specialization.getGuards()) {
+                if (guard.getExpression().containsComparisons()) {
+                    foundComparison = true;
+                    break outer;
+                }
+            }
+        }
+
+        if (foundComparison) {
+            CodeAnnotationMirror annotation = new CodeAnnotationMirror((DeclaredType) type.asType());
+            annotation.setElementValue(annotation.findExecutableElement("value"), new CodeAnnotationValue("SA_LOCAL_SELF_COMPARISON"));
+            clazz.addAnnotationMirror(annotation);
+        }
+    }
+
+    private void addUnsupportedMethod(CodeTypeElement clazz) {
+        CodeVariableElement seenUnsupportedField = new CodeVariableElement(modifiers(PRIVATE), getType(boolean.class), "seenUnsupported0");
+        seenUnsupportedField.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
+        clazz.add(seenUnsupportedField);
+        LocalContext locals = LocalContext.load(this);
+        CodeExecutableElement method = locals.createMethod(modifiers(PRIVATE), getType(UnsupportedSpecializationException.class), "unsupported", varArgsThreshold);
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startIf().string("!").string(seenUnsupportedField.getName()).end().startBlock();
+        builder.startStatement().startStaticCall(getType(CompilerDirectives.class), "transferToInterpreterAndInvalidate").end().end();
+        builder.startStatement().string(seenUnsupportedField.getName()).string(" = true").end();
+        builder.end();
+
+        builder.startReturn();
+        builder.startNew(getType(UnsupportedSpecializationException.class));
+        builder.string("this");
+        builder.tree(createGetSuppliedChildren());
+        locals.addReferencesTo(builder);
+        builder.end();
+        builder.end();
+        clazz.add(method);
+    }
+
+    private CodeExecutableElement createNodeConstructor(CodeTypeElement clazz, ExecutableElement superConstructor) {
+        CodeExecutableElement constructor = GeneratorUtils.createConstructorUsingFields(modifiers(), clazz, superConstructor);
+        ElementUtils.setVisibility(constructor.getModifiers(), ElementUtils.getVisibility(superConstructor.getModifiers()));
+
+        List<CodeVariableElement> childParameters = new ArrayList<>();
+        for (NodeChildData child : node.getChildren()) {
+            childParameters.add(new CodeVariableElement(child.getOriginalType(), child.getName()));
+        }
+        constructor.getParameters().addAll(superConstructor.getParameters().size(), childParameters);
+
+        CodeTreeBuilder builder = constructor.appendBuilder();
+        List<String> childValues = new ArrayList<>(node.getChildren().size());
+        for (NodeChildData child : node.getChildren()) {
+            String name = child.getName();
+            if (child.getCardinality().isMany()) {
+                CreateCastData createCast = node.findCast(child.getName());
+                if (createCast != null) {
+                    CodeTree nameTree = CodeTreeBuilder.singleString(name);
+                    CodeTreeBuilder callBuilder = builder.create();
+                    callBuilder.string(name).string(" != null ? ");
+                    callBuilder.tree(callMethod(null, createCast.getMethod(), nameTree));
+                    callBuilder.string(" : null");
+                    name += "_";
+                    builder.declaration(child.getNodeType(), name, callBuilder.build());
+                }
+            }
+            childValues.add(name);
+        }
+
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.getChild() == null) {
+                continue;
+            }
+            CreateCastData createCast = node.findCast(execution.getChild().getName());
+
+            builder.startStatement();
+            builder.string("this.").string(nodeFieldName(execution)).string(" = ");
+
+            String name = childValues.get(node.getChildren().indexOf(execution.getChild()));
+            CodeTreeBuilder accessorBuilder = builder.create();
+            accessorBuilder.string(name);
+
+            if (execution.isIndexed()) {
+                accessorBuilder.string("[").string(String.valueOf(execution.getChildIndex())).string("]");
+            }
+
+            CodeTree accessor = accessorBuilder.build();
+
+            if (createCast != null && execution.getChild().getCardinality().isOne()) {
+                accessor = callMethod(null, createCast.getMethod(), accessor);
+            }
+
+            if (execution.isIndexed()) {
+                CodeTreeBuilder nullCheck = builder.create();
+                nullCheck.string(name).string(" != null && ").string(String.valueOf(execution.getChildIndex())).string(" < ").string(name).string(".length").string(" ? ");
+                nullCheck.tree(accessor);
+                nullCheck.string(" : null");
+                accessor = nullCheck.build();
+            }
+
+            builder.tree(accessor);
+
+            builder.end();
+        }
+
+        return constructor;
+    }
+
+    private static boolean mayBeExcluded(SpecializationData specialization) {
+        return !specialization.getExceptions().isEmpty() || !specialization.getExcludedBy().isEmpty();
+    }
+
+    private SpecializationData createSpecializations(CodeTypeElement clazz) {
+        CodeTypeElement baseSpecialization = clazz.add(createBaseSpecialization());
+        TypeMirror baseSpecializationType = baseSpecialization.asType();
+
+        Map<SpecializationData, CodeTypeElement> generated = new LinkedHashMap<>();
+
+        List<SpecializationData> generateSpecializations = new ArrayList<>();
+        generateSpecializations.add(node.getUninitializedSpecialization());
+        if (needsPolymorphic()) {
+            generateSpecializations.add(node.getPolymorphicSpecialization());
+        }
+        generateSpecializations.addAll(reachableSpecializations);
+
+        for (SpecializationData specialization : generateSpecializations) {
+            generated.put(specialization, clazz.add(createSpecialization(specialization, baseSpecializationType)));
+        }
+
+        baseSpecialization.addOptional(createCreateNext(generated));
+        baseSpecialization.addOptional(createCreateFallback(generated));
+        baseSpecialization.addOptional(createCreatePolymorphic(generated));
+        baseSpecialization.addOptional(createGetNext(baseSpecialization));
+
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            Collection<TypeMirror> specializedTypes = node.findSpecializedTypes(execution);
+            specializedTypes.add(genericType);
+            for (TypeMirror specializedType : specializedTypes) {
+                if (isExecuteChildShared(execution, specializedType)) {
+                    baseSpecialization.addOptional(createExecuteChildMethod(execution, specializedType));
+                }
+            }
+        }
+
+        return node.getUninitializedSpecialization();
+    }
+
+    private boolean needsPolymorphic() {
+        int signatureSize = node.getSignatureSize();
+        boolean allEvaluated = true;
+        for (ExecutableTypeData type : usedTypes) {
+            if (type.getEvaluatedCount() != signatureSize) {
+                allEvaluated = false;
+            }
+        }
+        if (allEvaluated) {
+            return false;
+        }
+
+        if (reachableSpecializations.size() != 1) {
+            return true;
+        }
+
+        SpecializationData specialization = reachableSpecializations.get(0);
+        for (Parameter parameter : specialization.getSignatureParameters()) {
+            TypeMirror type = parameter.getType();
+            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
+                return true;
+            }
+        }
+        if (specialization.hasMultipleInstances()) {
+            return true;
+        }
+        return false;
+
+    }
+
+    // create specialization
+
+    private CodeTypeElement createBaseSpecialization() {
+        CodeTypeElement clazz = createClass(node, null, modifiers(PRIVATE, ABSTRACT, STATIC), specializationTypeName(null), typeSystem.getContext().getType(SpecializationNode.class));
+
+        clazz.addOptional(createSpecializationConstructor(clazz, null, null));
+        clazz.add(new CodeVariableElement(modifiers(PROTECTED, FINAL), nodeType(node), "root"));
+
+        clazz.addOptional(createUnsupported());
+        clazz.add(createGetSuppliedChildrenMethod());
+        clazz.add(createAcceptAndExecute());
+
+        for (ExecutableTypeData type : usedTypes) {
+            clazz.add(createFastPathExecuteMethod(null, type, usedTypes));
+        }
+
+        return clazz;
+    }
+
+    private Element createAcceptAndExecute() {
+        ExecutableTypeData executableElement = createSpecializationNodeSignature(node.getSignatureSize());
+        LocalContext currentLocals = LocalContext.load(this, executableElement, varArgsThreshold);
+        CodeExecutableElement executable = createExecuteMethod(null, executableElement, currentLocals, false, varArgsThreshold);
+
+        executable.getModifiers().add(FINAL);
+        CodeTreeBuilder builder = executable.createBuilder();
+
+        CodeTree receiver = CodeTreeBuilder.singleString("this");
+
+        builder.tree(createCallDelegateExecute(builder, receiver, currentLocals, executableElement, node.getGenericExecutableType(null)));
+
+        return executable;
+    }
+
+    private ExecutableTypeData createSpecializationNodeSignature(int argumentCount) {
+        TypeMirror[] parameters = new TypeMirror[argumentCount];
+        Arrays.fill(parameters, genericType);
+        return new ExecutableTypeData(node, genericType, "acceptAndExecute", context.getType(Frame.class), Arrays.asList(parameters));
+    }
+
+    private boolean shouldImplementExecutableType(SpecializationData specialization, ExecutableTypeData executableType) {
+        // always implement the root execute method. they are declared abstract in the base node.
+        if (executableType.getDelegatedTo() == null) {
+            return true;
+        }
+
+        // specializations with more parameters are just ignored
+        if (executableType.getEvaluatedCount() > node.getExecutionCount()) {
+            return false;
+        }
+
+        if (!isSubtypeBoxed(context, specialization.getReturnType().getType(), executableType.getReturnType())) {
+            return false;
+        }
+
+        // the evaluated signature might be compatible to the specialization
+        boolean specializationCompatible = true;
+        List<TypeMirror> signatureParameters = executableType.getSignatureParameters();
+        for (int i = 0; i < signatureParameters.size(); i++) {
+            TypeMirror evaluatedType = signatureParameters.get(i);
+            TypeMirror specializedType = specialization.findParameterOrDie(node.getChildExecutions().get(i)).getType();
+
+            if (!isSubtypeBoxed(context, evaluatedType, specializedType) && !isSubtypeBoxed(context, specializedType, evaluatedType)) {
+                specializationCompatible = false;
+                break;
+            }
+        }
+        if (!specializationCompatible) {
+            return false;
+        }
+
+        // possibly trigger void optimization for a specialization if it is enabled
+        if (isVoid(executableType.getReturnType())) {
+            if (isTypeBoxingOptimized(options.voidBoxingOptimization(), specialization.getReturnType().getType())) {
+                return true;
+            }
+        }
+
+        // trigger type boxing elimination for unevaluated arguments
+        for (int i = executableType.getEvaluatedCount(); i < node.getExecutionCount(); i++) {
+            NodeExecutionData execution = node.getChildExecutions().get(i);
+            TypeMirror specializedType = specialization.findParameterOrDie(execution).getType();
+            if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), specializedType)) {
+                // it does not make sense to do type boxing elimination for children with
+                // no type specialized execute method
+                if (execution.getChild() != null) {
+                    ExecutableTypeData executedType = execution.getChild().findExecutableType(specializedType);
+                    if (executedType != null) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        // trigger type boxing elimination for return types
+        if (typeEquals(executableType.getReturnType(), specialization.getReturnType().getType())) {
+            if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), executableType.getReturnType())) {
+                return true;
+            }
+        }
+
+        // trigger generation for evaluated assignable type matches other than generic
+        for (int i = 0; i < signatureParameters.size(); i++) {
+            TypeMirror evaluatedType = signatureParameters.get(i);
+            NodeExecutionData execution = node.getChildExecutions().get(i);
+            TypeMirror specializedType = specialization.findParameterOrDie(execution).getType();
+
+            if (isSubtypeBoxed(context, evaluatedType, specializedType) && !isObject(specializedType)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private List<ExecutableTypeData> filterBaseExecutableTypes(List<ExecutableTypeData> executableTypes, List<SpecializationData> specializations) {
+        Set<TypeMirror> returnTypes = new HashSet<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            returnTypes.add(specialization.getReturnType().getType());
+        }
+
+        List<ExecutableTypeData> prefilteredTypes = new ArrayList<>();
+        for (ExecutableTypeData type : executableTypes) {
+            if (type.getDelegatedTo() == null || shouldAlwaysImplementExecutableType(type)) {
+                prefilteredTypes.add(type);
+            } else {
+                boolean foundSubtype = false;
+                for (TypeMirror returnType : returnTypes) {
+                    if (isSubtypeBoxed(context, returnType, type.getReturnType())) {
+                        foundSubtype = true;
+                    }
+                }
+                if (foundSubtype) {
+                    prefilteredTypes.add(type);
+                }
+            }
+        }
+
+        Set<ExecutableTypeData> types = new HashSet<>();
+        type: for (ExecutableTypeData type : prefilteredTypes) {
+            for (SpecializationData specialization : specializations) {
+                if (shouldImplementExecutableType(specialization, type) || shouldAlwaysImplementExecutableType(type)) {
+                    types.add(type);
+                    continue type;
+                }
+            }
+        }
+        Set<ExecutableTypeData> delegatesToAdd = new HashSet<>();
+        do {
+            delegatesToAdd.clear();
+            for (ExecutableTypeData type : types) {
+                ExecutableTypeData delegate = type.getDelegatedTo();
+                if (delegate != null && !types.contains(delegate)) {
+                    delegatesToAdd.add(delegate);
+                }
+            }
+            types.addAll(delegatesToAdd);
+        } while (!delegatesToAdd.isEmpty());
+        List<ExecutableTypeData> newUsedTypes = new ArrayList<>(types);
+        Collections.sort(newUsedTypes);
+        return newUsedTypes;
+    }
+
+    private boolean shouldAlwaysImplementExecutableType(ExecutableTypeData type) {
+        return type.isAbstract() || !(type.hasUnexpectedValue(context) && type.getMethod() != null);
+    }
+
+    private CodeTypeElement createSpecialization(SpecializationData specialization, TypeMirror baseType) {
+        CodeTypeElement clazz = createClass(node, specialization, modifiers(PRIVATE, STATIC, FINAL), specializationTypeName(specialization), baseType);
+
+        CodeExecutableElement constructor = clazz.addOptional(createSpecializationConstructor(clazz, specialization, null));
+
+        for (Parameter p : specialization.getSignatureParameters()) {
+            TypeMirror targetType = p.getType();
+            if (typeSystem.hasImplicitSourceTypes(targetType)) {
+                NodeExecutionData execution = p.getSpecification().getExecution();
+                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
+                if (implicitProfile != null) {
+                    implicitProfile.getModifiers().add(PRIVATE);
+                    implicitProfile.getModifiers().add(FINAL);
+                    clazz.add(implicitProfile);
+                }
+            }
+        }
+
+        if (specialization.isFallback()) {
+            clazz.add(createFallbackGuardMethod());
+        }
+
+        clazz.addOptional(createSpecializationCreateMethod(specialization, constructor));
+        clazz.addOptional(createMergeMethod(specialization));
+        clazz.addOptional(createIsSameMethod(specialization));
+        clazz.addOptional(createIsIdenticalMethod(specialization));
+
+        // get types that should get implemented
+        List<ExecutableTypeData> types = new ArrayList<>();
+        for (ExecutableTypeData type : node.getExecutableTypes()) {
+            if (shouldImplementExecutableType(specialization, type)) {
+                types.add(type);
+            }
+        }
+        for (ExecutableTypeData type : types) {
+            clazz.add(createFastPathExecuteMethod(specialization, type, types));
+        }
+
+        return clazz;
+    }
+
+    public static List<Parameter> getDynamicParameters(TemplateMethod method) {
+        List<Parameter> parameters = new ArrayList<>();
+        for (Parameter param : method.getReturnTypeAndParameters()) {
+            if (param.getSpecification().isLocal()) {
+                // ignore parameters passed by locals
+                continue;
+            } else if (param.getVariableElement() != null && param.getVariableElement().getAnnotation(Cached.class) != null) {
+                // ignore cached parameters
+                continue;
+            }
+            parameters.add(param);
+        }
+        return parameters;
+    }
+
+    private Element createDeepCopyMethod() {
+        if (singleSpecializable) {
+            return null;
+        }
+        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), getType(Node.class), "deepCopy");
+        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        CodeTreeBuilder builder = executable.createBuilder();
+        builder.startReturn().startStaticCall(getType(SpecializationNode.class), "updateRoot").string("super.deepCopy()").end().end();
+        return executable;
+    }
+
+    private Element createGetCostMethod() {
+        TypeMirror returnType = getType(NodeCost.class);
+        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getCost");
+        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        CodeTreeBuilder builder = executable.createBuilder();
+        if (singleSpecializable) {
+            builder.startReturn().staticReference(getType(NodeCost.class), "MONOMORPHIC").end().end();
+        } else {
+            builder.startReturn().startCall(specializationStartFieldName(), "getNodeCost").end().end();
+        }
+        return executable;
+
+    }
+
+    private Element createIsIdenticalMethod(SpecializationData specialization) {
+        boolean cacheBoundGuard = specialization.hasMultipleInstances();
+        if (!cacheBoundGuard) {
+            return null;
+        }
+
+        LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold);
+        currentLocals.loadFastPathState(specialization);
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isIdentical");
+        method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other"));
+        currentLocals.addParametersTo(method, varArgsThreshold, FRAME_VALUE);
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        final CodeTreeBuilder builder = method.createBuilder();
+
+        SpecializationGroup group = SpecializationGroup.create(specialization);
+        SpecializationBody executionFactory = new SpecializationBody(true, false) {
+            @Override
+            public CodeTree createBody(SpecializationData s, LocalContext values) {
+                return builder.create().returnTrue().build();
+            }
+        };
+
+        builder.tree(createGuardAndCast(group, genericType, currentLocals, executionFactory));
+        builder.returnFalse();
+        return method;
+    }
+
+    private CodeExecutableElement createIsSameMethod(SpecializationData specialization) {
+        if (!specialization.isSpecialized() || !options.implicitCastOptimization().isDuplicateTail()) {
+            return null;
+        }
+
+        List<CodeVariableElement> profiles = new ArrayList<>();
+        for (Parameter parameter : specialization.getSignatureParameters()) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
+                continue;
+            }
+            CodeVariableElement var = createImplicitProfileParameter(execution, parameter.getType());
+            if (var != null) {
+                profiles.add(var);
+            }
+        }
+
+        if (profiles.isEmpty()) {
+            return null;
+        }
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isSame");
+        method.addParameter(new CodeVariableElement(getType(SpecializationNode.class), "other"));
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        CodeTreeBuilder builder = method.createBuilder();
+
+        builder.startReturn();
+        builder.string("super.isSame(other)");
+
+        for (CodeVariableElement profile : profiles) {
+            builder.string(" && ");
+            builder.string("this.").string(profile.getName()).string(" == ").string("(").cast(specializationType(specialization)).string("other).").string(profile.getName());
+        }
+
+        builder.end();
+        return method;
+    }
+
+    private Element createMergeMethod(SpecializationData specialization) {
+        if (specialization.getExcludedBy().isEmpty() && !specialization.isPolymorphic()) {
+            return null;
+        }
+        TypeMirror specializationNodeType = getType(SpecializationNode.class);
+        LocalContext currentLocals = LocalContext.load(this, createSpecializationNodeSignature(node.getSignatureSize()), varArgsThreshold);
+
+        CodeExecutableElement executable = new CodeExecutableElement(modifiers(PUBLIC), specializationNodeType, "merge");
+        executable.addParameter(new CodeVariableElement(specializationNodeType, "newNode"));
+        currentLocals.addParametersTo(executable, varArgsThreshold, FRAME_VALUE);
+        executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        CodeTreeBuilder builder = executable.createBuilder();
+
+        if (specialization.isPolymorphic()) {
+            builder.startReturn();
+            builder.startCall("polymorphicMerge");
+            builder.string("newNode");
+            builder.startCall("super", "merge");
+            builder.string("newNode");
+            currentLocals.addReferencesTo(builder, FRAME_VALUE);
+            builder.end();
+            builder.end();
+            builder.end();
+
+        } else {
+            boolean elseIf = false;
+            for (SpecializationData containedSpecialization : specialization.getExcludedBy()) {
+                elseIf = builder.startIf(elseIf);
+                builder.string("newNode.getClass() == ").typeLiteral(specializationType(containedSpecialization));
+                builder.end();
+                builder.startBlock();
+                builder.statement("removeSame(\"Contained by " + containedSpecialization.createReferenceName() + "\")");
+                builder.end();
+            }
+            builder.startReturn();
+            builder.startCall("super", "merge");
+            builder.string("newNode");
+            currentLocals.addReferencesTo(builder, FRAME_VALUE);
+            builder.end();
+            builder.end();
+        }
+
+        return executable;
+    }
+
+    private Element createCreateFallback(Map<SpecializationData, CodeTypeElement> generatedSpecializationClasses) {
+        SpecializationData fallback = node.getGenericSpecialization();
+        if (fallback == null) {
+            return null;
+        }
+        CodeTypeElement generatedType = generatedSpecializationClasses.get(fallback);
+        if (generatedType == null) {
+            return null;
+        }
+
+        TypeMirror returnType = getType(SpecializationNode.class);
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, "createFallback");
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        method.createBuilder().startReturn().tree(createCallCreateMethod(fallback, null, null)).end();
+        return method;
+    }
+
+    private Element createCreatePolymorphic(Map<SpecializationData, CodeTypeElement> generatedSpecializationClasses) {
+        SpecializationData polymorphic = node.getPolymorphicSpecialization();
+        CodeTypeElement generatedPolymorphic = generatedSpecializationClasses.get(polymorphic);
+        if (generatedPolymorphic == null) {
+            return null;
+        }
+        TypeMirror returnType = getType(SpecializationNode.class);
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), returnType, "createPolymorphic");
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        method.createBuilder().startReturn().tree(createCallCreateMethod(polymorphic, null, null)).end();
+        return method;
+    }
+
+    private CodeExecutableElement createCreateNext(final Map<SpecializationData, CodeTypeElement> specializationClasses) {
+        final LocalContext locals = LocalContext.load(this);
+
+        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), getType(SpecializationNode.class), "createNext", varArgsThreshold, FRAME_VALUE);
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+
+        CodeTreeBuilder builder = method.createBuilder();
+        SpecializationGroup group = createSpecializationGroups();
+        CodeTree execution = createGuardAndCast(group, genericType, locals, new SpecializationBody(false, false) {
+            @Override
+            public CodeTree createBody(SpecializationData specialization, LocalContext values) {
+                CodeTypeElement generatedType = specializationClasses.get(specialization);
+                if (generatedType == null) {
+                    throw new AssertionError("No generated type for " + specialization);
+                }
+                return createSlowPathExecute(specialization, values);
+            }
+        });
+
+        builder.tree(execution);
+
+        if (hasFallthrough(group, genericType, locals, false, null)) {
+            builder.returnNull();
+        }
+        return method;
+    }
+
+    private CodeExecutableElement createFallbackGuardMethod() {
+        boolean frameUsed = node.isFrameUsedByAnyGuard();
+        LocalContext locals = LocalContext.load(this);
+
+        if (!frameUsed) {
+            locals.removeValue(FRAME_VALUE);
+        }
+
+        CodeExecutableElement boundaryMethod = locals.createMethod(modifiers(PRIVATE), getType(boolean.class), "guardFallback", varArgsThreshold, FRAME_VALUE);
+        if (!frameUsed) {
+            boundaryMethod.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(TruffleBoundary.class)));
+        }
+
+        CodeTreeBuilder builder = boundaryMethod.createBuilder();
+        builder.startReturn();
+        builder.startCall("createNext");
+        locals.addReferencesTo(builder, FRAME_VALUE);
+        builder.end();
+        builder.string(" == null");
+        builder.end();
+        return boundaryMethod;
+    }
+
+    private ExecutableElement createAccessChildMethod(NodeChildData child) {
+        if (child.getAccessElement() != null && child.getAccessElement().getModifiers().contains(Modifier.ABSTRACT)) {
+            ExecutableElement getter = (ExecutableElement) child.getAccessElement();
+            CodeExecutableElement method = CodeExecutableElement.clone(context.getEnvironment(), getter);
+            method.getModifiers().remove(Modifier.ABSTRACT);
+
+            List<NodeExecutionData> executions = new ArrayList<>();
+            for (NodeExecutionData execution : node.getChildExecutions()) {
+                if (execution.getChild() == child) {
+                    executions.add(execution);
+                }
+            }
+
+            CodeTreeBuilder builder = method.createBuilder();
+            if (child.getCardinality().isMany()) {
+                builder.startReturn().startNewArray((ArrayType) child.getOriginalType(), null);
+                for (NodeExecutionData execution : executions) {
+                    builder.string(nodeFieldName(execution));
+                }
+                builder.end().end();
+            } else {
+                for (NodeExecutionData execution : executions) {
+                    builder.startReturn().string("this.").string(nodeFieldName(execution)).end();
+                    break;
+                }
+            }
+            return method;
+        }
+        return null;
+    }
+
+    private Element createUnsupported() {
+        SpecializationData fallback = node.getGenericSpecialization();
+        if (fallback == null || optimizeFallback(fallback) || fallback.getMethod() == null) {
+            return null;
+        }
+        LocalContext locals = LocalContext.load(this);
+
+        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), genericType, "unsupported", varArgsThreshold, FRAME_VALUE);
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startReturn();
+        builder.tree(callTemplateMethod(accessParent(null), fallback, locals));
+        builder.end();
+
+        return method;
+    }
+
+    private boolean isSingleSpecializableImpl() {
+        if (reachableSpecializations.size() != 1) {
+            return false;
+        }
+
+        SpecializationData specialization = reachableSpecializations.get(0);
+
+        for (Parameter parameter : specialization.getSignatureParameters()) {
+            TypeMirror type = parameter.getType();
+            if (type != null && typeSystem.hasImplicitSourceTypes(type)) {
+                return false;
+            }
+        }
+
+        if (!specialization.getAssumptionExpressions().isEmpty()) {
+            return false;
+        }
+
+        if (specialization.getCaches().size() > 0) {
+            // TODO chumer: caches do not yet support single specialization.
+            // it could be worthwhile to explore if this is possible
+            return false;
+        }
+        return true;
+    }
+
+    private List<SpecializationData> calculateReachableSpecializations() {
+        List<SpecializationData> specializations = new ArrayList<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.isReachable() && //
+                            (specialization.isSpecialized() //
+                            || (specialization.isFallback() && optimizeFallback(specialization)))) {
+                specializations.add(specialization);
+            }
+        }
+        return specializations;
+    }
+
+    private boolean optimizeFallback(SpecializationData specialization) {
+        switch (options.optimizeFallback()) {
+            case NEVER:
+                return false;
+            case DECLARED:
+                return specialization.getMethod() != null;
+            case ALWAYS:
+                return true;
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    private CodeExecutableElement createExecutableTypeOverride(List<ExecutableTypeData> usedExecutables, ExecutableTypeData execType) {
+        LocalContext locals = LocalContext.load(this, execType, Integer.MAX_VALUE);
+        CodeExecutableElement method = createExecuteMethod(null, execType, locals, true, Integer.MAX_VALUE);
+
+        CodeTreeBuilder builder = method.createBuilder();
+        if (singleSpecializable) {
+            SpecializationData specialization = reachableSpecializations.iterator().next();
+            builder.tree(createFastPath(builder, specialization, execType, usedExecutables, locals));
+        } else {
+            // create acceptAndExecute
+            ExecutableTypeData delegate = execType;
+            CodeTree receiver = CodeTreeBuilder.singleString(specializationStartFieldName());
+            builder.tree(createCallDelegateExecute(builder, receiver, locals, execType, delegate));
+        }
+        return method;
+    }
+
+    private Element createMethodGetSpecializationNode() {
+        TypeMirror returntype = getType(SpecializationNode.class);
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returntype, "getSpecializationNode");
+        method.createBuilder().startReturn().string(specializationStartFieldName()).end();
+        return method;
+    }
+
+    private TypeMirror getType(Class<?> clazz) {
+        return context.getType(clazz);
+    }
+
+    private CodeVariableElement createNodeField(Modifier visibility, TypeMirror type, String name, Class<?> annotationType) {
+        CodeVariableElement childField = new CodeVariableElement(modifiers(), type, name);
+        childField.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(annotationType)));
+        setVisibility(childField.getModifiers(), visibility);
+        return childField;
+    }
+
+    private static List<ExecutableTypeData> resolveSpecializedExecutables(NodeExecutionData execution, Collection<TypeMirror> types, TypeBoxingOptimization optimization) {
+        if (optimization == TypeBoxingOptimization.NONE) {
+            return Collections.emptyList();
+        } else if (types.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<ExecutableTypeData> executables = new ArrayList<>();
+        for (TypeMirror type : types) {
+            if (!isTypeBoxingOptimized(optimization, type)) {
+                continue;
+            }
+            if (execution.getChild() == null) {
+                continue;
+            }
+            ExecutableTypeData foundType = execution.getChild().getNodeData().findExecutableType(type, execution.getChild().getExecuteWith().size());
+            if (foundType != null) {
+                executables.add(foundType);
+            }
+        }
+        return executables;
+    }
+
+    private static CodeTree callMethod(CodeTree receiver, ExecutableElement method, CodeTree... boundValues) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (method.getModifiers().contains(STATIC)) {
+            builder.startStaticCall(method.getEnclosingElement().asType(), method.getSimpleName().toString());
+        } else {
+            builder.startCall(receiver, method.getSimpleName().toString());
+        }
+        int index = -1;
+        for (VariableElement parameter : method.getParameters()) {
+            index++;
+            if (index < boundValues.length) {
+                CodeTree tree = boundValues[index];
+                if (tree != null) {
+                    builder.tree(tree);
+                    continue;
+                }
+            }
+
+            builder.defaultValue(parameter.asType());
+        }
+        builder.end();
+        return builder.build();
+    }
+
+    private CodeTree[] bindExecuteMethodParameters(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) {
+        List<NodeExecutionData> executeWith = execution != null ? execution.getChild().getExecuteWith() : null;
+
+        List<CodeTree> values = new ArrayList<>();
+        if (method.getFrameParameter() != null) {
+            LocalVariable frameLocal = currentValues.get(FRAME_VALUE);
+            if (frameLocal == null) {
+                values.add(CodeTreeBuilder.singleString("null"));
+            } else {
+                values.add(createTypeSafeReference(frameLocal, method.getFrameParameter()));
+            }
+        }
+
+        int evaluatedIndex = 0;
+        for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) {
+            NodeExecutionData parameterExecution;
+            if (executeWith != null && executionIndex < executeWith.size()) {
+                parameterExecution = executeWith.get(executionIndex);
+            } else {
+                parameterExecution = node.getChildExecutions().get(executionIndex);
+            }
+            if (parameterExecution.isShortCircuit()) {
+                if (evaluatedIndex < method.getEvaluatedCount()) {
+                    TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex);
+                    LocalVariable shortCircuit = currentValues.getShortCircuit(parameterExecution);
+                    if (shortCircuit != null) {
+                        values.add(createTypeSafeReference(shortCircuit, targetType));
+                    } else {
+                        values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build());
+                    }
+                    evaluatedIndex++;
+                }
+            }
+            if (evaluatedIndex < method.getEvaluatedCount()) {
+                TypeMirror targetType = method.getEvaluatedParameters().get(evaluatedIndex);
+                LocalVariable value = currentValues.getValue(parameterExecution);
+                if (value != null) {
+                    values.add(createTypeSafeReference(value, targetType));
+                } else {
+                    values.add(CodeTreeBuilder.createBuilder().defaultValue(targetType).build());
+                }
+                evaluatedIndex++;
+            }
+        }
+        return values.toArray(new CodeTree[values.size()]);
+    }
+
+    private CodeTree callExecuteMethod(NodeExecutionData execution, ExecutableTypeData method, LocalContext currentValues) {
+        CodeTree receiver = execution != null ? accessParent(nodeFieldName(execution)) : null;
+        return callMethod(receiver, method.getMethod(), bindExecuteMethodParameters(execution, method, currentValues));
+    }
+
+    private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, LocalContext currentValues) {
+        CodeTree[] bindings = new CodeTree[method.getParameters().size()];
+
+        int signatureIndex = 0;
+        for (int i = 0; i < bindings.length; i++) {
+            Parameter parameter = method.getParameters().get(i);
+
+            LocalVariable var = currentValues.get(parameter, signatureIndex);
+            if (var == null) {
+                var = currentValues.get(parameter.getLocalName());
+            }
+
+            if (var != null) {
+                bindings[i] = createTypeSafeReference(var, parameter.getType());
+            }
+
+            if (parameter.getSpecification().isSignature()) {
+                signatureIndex++;
+            }
+        }
+        return callMethod(receiver, method.getMethod(), bindings);
+    }
+
+    private CodeTree createTypeSafeReference(LocalVariable var, TypeMirror targetType) {
+        CodeTree valueReference = var.createReference();
+        TypeMirror sourceType = var.getTypeMirror();
+        if (targetType == null || sourceType == null) {
+            return valueReference;
+        }
+        if (needsCastTo(sourceType, targetType)) {
+            valueReference = TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference);
+        }
+        return valueReference;
+    }
+
+    private SpecializationGroup createSpecializationGroups() {
+        return SpecializationGroup.create(reachableSpecializations);
+    }
+
+    private CodeTree createSlowPathExecute(SpecializationData specialization, LocalContext currentValues) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (specialization.isFallback()) {
+            return builder.returnNull().build();
+        }
+
+        if (node.isFrameUsedByAnyGuard()) {
+            builder.tree(createTransferToInterpreterAndInvalidate());
+        }
+
+        // caches unbound to guards are invoked after all guards
+        for (CacheExpression cache : specialization.getCaches()) {
+            if (!specialization.isCacheBoundByGuard(cache)) {
+                initializeCache(builder, specialization, cache, currentValues);
+            }
+        }
+        boolean hasAssumptions = !specialization.getAssumptionExpressions().isEmpty();
+        if (hasAssumptions) {
+
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                CodeTree assumptions = DSLExpressionGenerator.write(assumption.getExpression(), accessParent(null),
+                                castBoundTypes(bindExpressionValues(assumption.getExpression(), specialization, currentValues)));
+                String name = assumptionName(assumption);
+                // needs specialization index for assumption to make unique
+                String varName = name + specialization.getIndex();
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                builder.declaration(type, varName, assumptions);
+                currentValues.set(name, new LocalVariable(type, varName, null, null));
+            }
+
+            builder.startIf();
+            String sep = "";
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
+                if (assumptionVar == null) {
+                    throw new AssertionError("assumption var not resolved");
+                }
+                builder.string(sep);
+                builder.startCall("isValid").tree(assumptionVar.createReference()).end();
+                sep = " && ";
+            }
+            builder.end();
+            builder.startBlock();
+        }
+
+        for (SpecializationData otherSpeciailzation : node.getSpecializations()) {
+            if (otherSpeciailzation == specialization) {
+                continue;
+            }
+            if (otherSpeciailzation.getExcludedBy().contains(specialization)) {
+                builder.startStatement();
+                builder.tree(accessParent(excludedFieldName(otherSpeciailzation)));
+                builder.string(" = true");
+                builder.end();
+            }
+        }
+
+        CodeTree create = createCallCreateMethod(specialization, null, currentValues);
+
+        if (specialization.hasMultipleInstances()) {
+            builder.declaration(getType(SpecializationNode.class), "s", create);
+            DSLExpression limitExpression = specialization.getLimitExpression();
+            CodeTree limitExpressionTree;
+            if (limitExpression == null) {
+                limitExpressionTree = CodeTreeBuilder.singleString("3");
+            } else {
+                limitExpressionTree = DSLExpressionGenerator.write(limitExpression, accessParent(null), //
+                                castBoundTypes(bindExpressionValues(limitExpression, specialization, currentValues)));
+            }
+
+            builder.startIf().string("countSame(s) < ").tree(limitExpressionTree).end().startBlock();
+            builder.statement("return s");
+            builder.end();
+        } else {
+            builder.startReturn().tree(create).end();
+        }
+
+        if (hasAssumptions) {
+            builder.end();
+        }
+
+        if (mayBeExcluded(specialization)) {
+            CodeTreeBuilder checkHasSeenBuilder = builder.create();
+            checkHasSeenBuilder.startIf().string("!").tree(accessParent(excludedFieldName(specialization))).end().startBlock();
+            checkHasSeenBuilder.tree(builder.build());
+            checkHasSeenBuilder.end();
+            return checkHasSeenBuilder.build();
+        }
+        return builder.build();
+    }
+
+    private boolean hasFallthrough(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, boolean fastPath, List<GuardExpression> ignoreGuards) {
+        for (TypeGuard guard : group.getTypeGuards()) {
+            if (currentValues.getValue(guard.getSignatureIndex()) == null) {
+                // not evaluated
+                return true;
+            }
+            LocalVariable value = currentValues.getValue(guard.getSignatureIndex());
+            if (needsCastTo(value.getTypeMirror(), guard.getType())) {
+                return true;
+            }
+        }
+
+        List<GuardExpression> guards = new ArrayList<>(group.getGuards());
+        List<GuardExpression> elseConnectable = group.findElseConnectableGuards();
+        guards.removeAll(elseConnectable);
+        if (ignoreGuards != null) {
+            guards.removeAll(ignoreGuards);
+        }
+        SpecializationData specialization = group.getSpecialization();
+        if (specialization != null && fastPath) {
+            for (ListIterator<GuardExpression> iterator = guards.listIterator(); iterator.hasNext();) {
+                GuardExpression guard = iterator.next();
+                if (!specialization.isDynamicParameterBound(guard.getExpression())) {
+                    iterator.remove();
+                }
+            }
+        }
+
+        if (!guards.isEmpty()) {
+            return true;
+        }
+
+        if (!fastPath && specialization != null && !specialization.getAssumptionExpressions().isEmpty()) {
+            return true;
+        }
+
+        if (!fastPath && specialization != null && mayBeExcluded(specialization)) {
+            return true;
+        }
+
+        if (!elseConnectable.isEmpty()) {
+            SpecializationGroup previous = group.getPrevious();
+            if (previous != null && hasFallthrough(previous, forType, currentValues, fastPath, previous.getGuards())) {
+                return true;
+            }
+        }
+
+        List<SpecializationGroup> groupChildren = group.getChildren();
+        if (!groupChildren.isEmpty()) {
+            return hasFallthrough(groupChildren.get(groupChildren.size() - 1), forType, currentValues, fastPath, ignoreGuards);
+        }
+
+        return false;
+    }
+
+    private Element createGetNext(CodeTypeElement type) {
+        if (!nextUsed) {
+            return null;
+        }
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), type.asType(), "getNext");
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startReturn().cast(type.asType(), CodeTreeBuilder.singleString("this.next")).end();
+        return method;
+    }
+
+    private Element createGetSuppliedChildrenMethod() {
+        ArrayType nodeArray = context.getEnvironment().getTypeUtils().getArrayType(getType(Node.class));
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, FINAL), nodeArray, "getSuppliedChildren");
+        method.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+
+        CodeTreeBuilder builder = method.createBuilder();
+        builder.startReturn().tree(createGetSuppliedChildren()).end();
+
+        return method;
+    }
+
+    private CodeTree createGetSuppliedChildren() {
+        ArrayType nodeArray = context.getEnvironment().getTypeUtils().getArrayType(getType(Node.class));
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startNewArray(nodeArray, null);
+        for (int i = 0; i < node.getChildExecutions().size(); i++) {
+            NodeExecutionData execution = node.getChildExecutions().get(i);
+            if (execution.isShortCircuit()) {
+                builder.nullLiteral();
+            }
+            if (execution.getChild() == null) {
+                builder.nullLiteral();
+            } else {
+                builder.tree(accessParent(nodeFieldName(execution)));
+            }
+        }
+        builder.end();
+        return builder.build();
+    }
+
+    // create specialization
+
+    private CodeTree createCallCreateMethod(SpecializationData specialization, String rootName, LocalContext currentValues) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        TypeMirror specializationType = specializationType(specialization);
+        if (useLazyClassLoading()) {
+            builder.startStaticCall(specializationType(specialization), "create");
+        } else {
+            builder.startNew(specializationType);
+        }
+        if (rootName != null) {
+            builder.string(rootName);
+        } else {
+            builder.string("root");
+        }
+        if (currentValues != null) {
+            for (Parameter p : specialization.getSignatureParameters()) {
+                CodeVariableElement var = createImplicitProfileParameter(p.getSpecification().getExecution(), p.getType());
+                if (var != null) {
+                    LocalVariable variable = currentValues.get(p.getLocalName());
+                    if (variable == null) {
+                        throw new AssertionError("Could not bind cached value " + p.getLocalName() + ": " + currentValues);
+                    }
+                    builder.tree(variable.original().createReference());
+                }
+            }
+            for (CacheExpression cache : specialization.getCaches()) {
+                LocalVariable variable = currentValues.get(cache.getParameter().getLocalName());
+                if (variable == null) {
+                    throw new AssertionError("Could not bind cached value " + cache.getParameter().getLocalName() + ": " + currentValues);
+                }
+                builder.tree(variable.createReference());
+            }
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable variable = currentValues.get(assumptionName(assumption));
+                if (variable == null) {
+                    throw new AssertionError("Could not bind assumption value " + assumption.getId() + ": " + currentValues);
+                }
+                builder.tree(variable.createReference());
+            }
+        }
+        builder.end();
+
+        return builder.build();
+    }
+
+    private Element createSpecializationCreateMethod(SpecializationData specialization, CodeExecutableElement constructor) {
+        if (!useLazyClassLoading()) {
+            return null;
+        }
+
+        CodeExecutableElement executable = CodeExecutableElement.clone(context.getEnvironment(), constructor);
+        executable.setReturnType(specializationType(null));
+        executable.setSimpleName(CodeNames.of("create"));
+        executable.getModifiers().add(STATIC);
+
+        CodeTreeBuilder builder = executable.createBuilder();
+        builder.startReturn().startNew(specializationType(specialization));
+        for (VariableElement parameter : executable.getParameters()) {
+            builder.string(parameter.getSimpleName().toString());
+        }
+        builder.end().end();
+        return executable;
+    }
+
+    private boolean useLazyClassLoading() {
+        return options.useLazyClassLoading() && !singleSpecializable;
+    }
+
+    private static String implicitClassFieldName(NodeExecutionData execution) {
+        return execution.getName() + "ImplicitType";
+    }
+
+    private static String implicitNodeFieldName(NodeExecutionData execution) {
+        return execution.getName() + "Cast";
+    }
+
+    private CodeExecutableElement createSpecializationConstructor(CodeTypeElement clazz, SpecializationData specialization, String constantIndex) {
+        CodeExecutableElement constructor = new CodeExecutableElement(modifiers(), null, clazz.getSimpleName().toString());
+
+        constructor.addParameter(new CodeVariableElement(nodeType(node), "root"));
+        CodeTreeBuilder builder = constructor.createBuilder();
+
+        if (specialization == null) {
+            if (constantIndex == null) {
+                builder.statement("super(index)");
+                constructor.addParameter(new CodeVariableElement(getType(int.class), "index"));
+            } else {
+                builder.startStatement().startSuperCall().string(constantIndex).end().end();
+            }
+            builder.statement("this.root = root");
+        } else {
+            int index = resolveSpecializationIndex(specialization);
+            builder.startStatement().startSuperCall().string("root").string(String.valueOf(index)).end().end();
+
+            for (Parameter p : specialization.getSignatureParameters()) {
+                NodeExecutionData execution = p.getSpecification().getExecution();
+
+                CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, p.getType());
+                if (implicitProfile != null) {
+                    LocalVariable var = LocalVariable.fromParameter(p).makeGeneric(context);
+
+                    String implicitFieldName = implicitProfile.getName();
+                    if (options.implicitCastOptimization().isDuplicateTail()) {
+                        constructor.addParameter(var.createParameter());
+                        CodeTree implicitType = TypeSystemCodeGenerator.implicitType(typeSystem, p.getType(), var.createReference());
+                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(implicitType).end();
+                    } else if (options.implicitCastOptimization().isMergeCasts()) {
+                        // use node that supports polymorphism
+                        constructor.addParameter(var.createParameter());
+                        builder.startStatement().string("this.").string(implicitFieldName).string(" = ").tree(ImplicitCastNodeFactory.create(typeSystem, p.getType(), var.createReference())).end();
+                    } else {
+                        throw new AssertionError();
+                    }
+                }
+            }
+            for (CacheExpression cache : specialization.getCaches()) {
+                String name = cache.getParameter().getLocalName();
+                TypeMirror type = cache.getParameter().getType();
+
+                if (ElementUtils.isAssignable(type, new ArrayCodeTypeMirror(getType(Node.class)))) {
+                    CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
+                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Children.class)));
+                } else if (ElementUtils.isAssignable(type, getType(Node.class))) {
+                    CodeVariableElement var = clazz.add(new CodeVariableElement(modifiers(PRIVATE), type, name));
+                    var.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(Child.class)));
+                } else {
+                    clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
+                }
+                constructor.addParameter(new CodeVariableElement(type, name));
+                builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
+            }
+
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                String name = assumptionName(assumption);
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                CodeVariableElement field = clazz.add(new CodeVariableElement(modifiers(PRIVATE, FINAL), type, name));
+                field.addAnnotationMirror(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class)));
+                constructor.addParameter(new CodeVariableElement(type, name));
+                builder.startStatement().string("this.").string(name).string(" = ").string(name).end();
+            }
+        }
+
+        if (constructor.getParameters().isEmpty()) {
+            // do not generate default constructor
+            return null;
+        }
+        return constructor;
+    }
+
+    // TODO this logic can be inlined to the parser as soon as the old NodeGen layout is gone
+    private static int resolveSpecializationIndex(SpecializationData specialization) {
+        if (specialization.isFallback()) {
+            return Integer.MAX_VALUE - 1;
+        } else if (specialization.isUninitialized()) {
+            return Integer.MAX_VALUE;
+        } else if (specialization.isPolymorphic()) {
+            return 0;
+        } else {
+            return specialization.getIndex();
+        }
+    }
+
+    private CodeTree createThrowUnsupported(LocalContext currentValues) {
+        singleSpecializableUnsupportedUsed = true;
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startThrow().startCall("unsupported");
+        currentValues.addReferencesTo(builder);
+        builder.end().end();
+        return builder.build();
+    }
+
+    private CodeTree createCallNext(CodeTreeBuilder parent, ExecutableTypeData currentType, ExecutableTypeData callType, LocalContext currentValues) {
+        if (singleSpecializable) {
+            return createThrowUnsupported(currentValues);
+        }
+        CodeTreeBuilder callBuilder = parent.create();
+        callBuilder.tree(createCallDelegateExecute(callBuilder, CodeTreeBuilder.singleString("getNext()"), currentValues, currentType, callType));
+        nextUsed = true;
+        return callBuilder.build();
+    }
+
+    private CodeTree createCallRemove(String reason, ExecutableTypeData forType, LocalContext currentValues) {
+        if (singleSpecializable) {
+            return createThrowUnsupported(currentValues);
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startCall("remove");
+        builder.doubleQuote(reason);
+        currentValues.addReferencesTo(builder, FRAME_VALUE);
+        builder.end();
+        CodeTree call = builder.build();
+
+        builder = builder.create();
+        builder.startReturn();
+        builder.tree(expectOrCast(genericType, forType, call));
+        builder.end();
+        return builder.build();
+    }
+
+    private CodeTree createCallDelegate(String methodName, String reason, ExecutableTypeData forType, LocalContext currentValues) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startCall(methodName);
+        if (reason != null) {
+            builder.doubleQuote(reason);
+        }
+        currentValues.addReferencesTo(builder, FRAME_VALUE);
+        builder.end();
+
+        CodeTree expectOrCast = expectOrCast(genericType, forType, builder.build());
+        return expectOrCast;
+    }
+
+    private CodeTree expectOrCast(TypeMirror sourceType, ExecutableTypeData targetType, CodeTree content) {
+        if (needsUnexpectedResultException(targetType)) {
+            return expect(sourceType, targetType.getReturnType(), content);
+        } else {
+            return cast(sourceType, targetType.getReturnType(), content);
+        }
+    }
+
+    private CodeTree cast(TypeMirror sourceType, TypeMirror targetType, CodeTree content) {
+        if (ElementUtils.needsCastTo(sourceType, targetType) && !isVoid(sourceType)) {
+            return TypeSystemCodeGenerator.cast(typeSystem, targetType, content);
+        } else {
+            return content;
+        }
+    }
+
+    private CodeTree expect(TypeMirror sourceType, TypeMirror forType, CodeTree tree) {
+        if (sourceType == null || ElementUtils.needsCastTo(sourceType, forType)) {
+            expectedTypes.add(forType);
+            return TypeSystemCodeGenerator.expect(typeSystem, forType, tree);
+        }
+        return tree;
+    }
+
+    private Set<ExecutableTypeData> findSpecializedExecutableTypes(NodeExecutionData execution, TypeMirror type) {
+        if (execution.getChild() == null) {
+            return Collections.emptySet();
+        }
+        ExecutableTypeData executableType = resolveExecutableType(execution.getChild(), type);
+        Set<ExecutableTypeData> executedTypes = new HashSet<>();
+        executedTypes.add(executableType);
+        if (typeSystem.hasImplicitSourceTypes(type)) {
+            executedTypes.addAll(resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(type), options.implicitTypeBoxingOptimization()));
+        }
+        return executedTypes;
+    }
+
+    private ExecutableTypeData resolveExecutableType(NodeChildData child, TypeMirror type) {
+        int executeWithCount = child.getExecuteWith().size();
+        ExecutableTypeData executableType = child.getNodeData().findExecutableType(type, executeWithCount);
+        if (executableType == null) {
+            executableType = child.getNodeData().findAnyGenericExecutableType(context, executeWithCount);
+        }
+        return executableType;
+    }
+
+    private boolean hasChildUnexpectedResult(NodeExecutionData execution, TypeMirror type) {
+        for (ExecutableTypeData executableType : findSpecializedExecutableTypes(execution, type)) {
+            if (executableType != null && (executableType.hasUnexpectedValue(context) || needsCastTo(executableType.getReturnType(), type))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Element createFastPathExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, List<ExecutableTypeData> allTypes) {
+        LocalContext currentLocals = LocalContext.load(this, executedType, Integer.MAX_VALUE);
+        CodeExecutableElement executable = createExecuteMethod(specialization, executedType, currentLocals, false, Integer.MAX_VALUE);
+        CodeTreeBuilder builder = executable.createBuilder();
+        if (specialization == null) {
+            if (executedType.getDelegatedTo() == null) {
+                executable.getModifiers().add(ABSTRACT);
+            }
+        } else {
+            executable.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(Override.class)));
+        }
+        builder.tree(createFastPath(builder, specialization, executedType, allTypes, currentLocals));
+
+        return executable;
+    }
+
+    private static final String VARARGS_NAME = "args";
+
+    private CodeExecutableElement createExecuteMethod(SpecializationData specialization, ExecutableTypeData executedType, LocalContext currentLocals, boolean originalOverride, int varArgs) {
+        TypeMirror returnType = executedType.getReturnType();
+
+        if (specialization != null) {
+            currentLocals.loadFastPathState(specialization);
+        }
+
+        String methodName;
+        if (originalOverride && executedType.getMethod() != null) {
+            methodName = executedType.getMethod().getSimpleName().toString();
+        } else {
+            methodName = executedType.getUniqueName();
+        }
+
+        CodeExecutableElement executable;
+        if (originalOverride && executedType.getMethod() != null) {
+            executable = CodeExecutableElement.clone(context.getEnvironment(), executedType.getMethod());
+            executable.getAnnotationMirrors().clear();
+            executable.getModifiers().remove(ABSTRACT);
+            for (VariableElement var : executable.getParameters()) {
+                ((CodeVariableElement) var).getAnnotationMirrors().clear();
+            }
+            if (executedType.getFrameParameter() != null) {
+                ((CodeVariableElement) executable.getParameters().get(0)).setName(FRAME_VALUE);
+            }
+
+            if (executable.isVarArgs()) {
+                ((CodeVariableElement) executable.getParameters().get(executable.getParameters().size() - 1)).setName(VARARGS_NAME);
+            }
+
+            renameOriginalParameters(executedType, executable, currentLocals);
+        } else {
+            executable = currentLocals.createMethod(modifiers(PUBLIC), returnType, methodName, varArgs, FRAME_VALUE);
+        }
+        executable.getThrownTypes().clear();
+
+        if (needsUnexpectedResultException(executedType)) {
+            executable.getThrownTypes().add(context.getDeclaredType(UnexpectedResultException.class));
+        }
+
+        return executable;
+    }
+
+    private void renameOriginalParameters(ExecutableTypeData executedType, CodeExecutableElement executable, LocalContext currentLocals) {
+        // rename varargs parameter
+        int evaluatedIndex = 0;
+        for (int executionIndex = 0; executionIndex < node.getExecutionCount(); executionIndex++) {
+            NodeExecutionData execution = node.getChildExecutions().get(executionIndex);
+            if (execution.isShortCircuit()) {
+                if (evaluatedIndex < executedType.getEvaluatedCount()) {
+                    TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex);
+                    LocalVariable shortCircuit = currentLocals.getShortCircuit(execution);
+                    if (shortCircuit != null) {
+                        currentLocals.setShortCircuitValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, shortCircuit));
+                    }
+                    evaluatedIndex++;
+                }
+            }
+            if (evaluatedIndex < executedType.getEvaluatedCount()) {
+                TypeMirror evaluatedType = executedType.getEvaluatedParameters().get(evaluatedIndex);
+                LocalVariable value = currentLocals.getValue(execution);
+                if (value != null) {
+                    currentLocals.setValue(execution, renameExecutableTypeParameter(executable, executedType, evaluatedIndex, evaluatedType, value));
+                }
+                evaluatedIndex++;
+            }
+        }
+    }
+
+    private static LocalVariable renameExecutableTypeParameter(CodeExecutableElement method, ExecutableTypeData executedType, int evaluatedIndex, TypeMirror targetType, LocalVariable var) {
+        int parameterIndex = executedType.getParameterIndex(evaluatedIndex);
+        int varArgsIndex = executedType.getVarArgsIndex(parameterIndex);
+        LocalVariable returnVar = var;
+        if (varArgsIndex >= 0) {
+            returnVar = returnVar.accessWith(CodeTreeBuilder.singleString(VARARGS_NAME + "[" + varArgsIndex + "]"));
+        } else {
+            ((CodeVariableElement) method.getParameters().get(parameterIndex)).setName(returnVar.getName());
+        }
+        if (!isObject(targetType)) {
+            returnVar = returnVar.newType(targetType);
+        }
+        return returnVar;
+    }
+
+    private boolean needsUnexpectedResultException(ExecutableTypeData executedType) {
+        if (!executedType.hasUnexpectedValue(context)) {
+            return false;
+        }
+
+        SpecializationData polymorphicSpecialization = node.getPolymorphicSpecialization();
+        if (polymorphicSpecialization != null && isSubtypeBoxed(context, polymorphicSpecialization.getReturnType().getType(), executedType.getReturnType())) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    private CodeTree createFastPath(CodeTreeBuilder parent, SpecializationData specialization, final ExecutableTypeData executableType, List<ExecutableTypeData> allTypes, LocalContext currentLocals) {
+        final CodeTreeBuilder builder = parent.create();
+        TypeMirror returnType = executableType.getReturnType();
+
+        ExecutableTypeData delegate = null;
+        if (specialization == null) {
+            delegate = executableType.getDelegatedTo();
+        }
+
+        if (delegate == null) {
+            delegate = findFastPathDelegate((specialization != null ? specialization.getReturnType().getType() : genericType), executableType, allTypes);
+        }
+
+        int delegateSignatureCount = delegate != null ? delegate.getSignatureParameters().size() : 0;
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (specialization == null && delegate != null && execution.getIndex() >= delegateSignatureCount) {
+                // we just evaluate children for the next delegate
+                continue;
+            } else if (specialization != null && delegate != null) {
+                // skip if already delegated
+                break;
+            }
+
+            LocalVariable var = currentLocals.getValue(execution);
+            if (var == null) {
+                TypeMirror targetType;
+                if (specialization == null) {
+                    targetType = node.getGenericType(execution);
+                } else {
+                    targetType = specialization.findParameterOrDie(execution).getType();
+                }
+                LocalVariable shortCircuit = resolveShortCircuit(specialization, execution, currentLocals);
+                var = currentLocals.createValue(execution, targetType).nextName();
+                builder.tree(createAssignExecuteChild(builder, execution, executableType, var, shortCircuit, currentLocals));
+                currentLocals.setValue(execution, var);
+            }
+        }
+
+        LocalContext originalValues = currentLocals.copy();
+        if (delegate != null) {
+            builder.tree(createCallDelegateExecute(builder, null, currentLocals, executableType, delegate));
+        } else if (specialization == null) {
+            // nothing to do. abstract anyway
+        } else if (specialization.isPolymorphic()) {
+            builder.tree(createCallNext(builder, executableType, node.getGenericExecutableType(executableType), currentLocals));
+        } else if (specialization.isUninitialized()) {
+            builder.startReturn().tree(createCallDelegate("uninitialized", null, executableType, currentLocals)).end();
+        } else {
+            SpecializationGroup group = SpecializationGroup.create(specialization);
+            SpecializationBody executionFactory = new SpecializationBody(true, true) {
+                @Override
+                public CodeTree createBody(SpecializationData s, LocalContext values) {
+                    return createFastPathExecute(builder, executableType, s, values);
+                }
+            };
+            builder.tree(createGuardAndCast(group, returnType, currentLocals, executionFactory));
+            if (hasFallthrough(group, returnType, originalValues, true, null) || group.getSpecialization().isFallback()) {
+                builder.tree(createCallNext(builder, executableType, node.getGenericExecutableType(executableType), originalValues));
+            }
+        }
+        return builder.build();
+    }
+
+    private CodeTree createCallDelegateExecute(final CodeTreeBuilder parent, CodeTree receiver, LocalContext currentLocals, ExecutableTypeData source, ExecutableTypeData delegate) {
+        CodeTreeBuilder callBuilder = parent.create();
+
+        if (singleSpecializable && delegate.getMethod() != null) {
+            callBuilder.startCall(receiver, delegate.getMethod().getSimpleName().toString());
+        } else {
+            callBuilder.startCall(receiver, delegate.getUniqueName());
+        }
+        callBuilder.trees(bindExecuteMethodParameters(null, delegate, currentLocals));
+        callBuilder.end();
+        CodeTree call = expectOrCast(delegate.getReturnType(), source, callBuilder.build());
+
+        CodeTreeBuilder returnBuilder = parent.create();
+        if (isVoid(source.getReturnType())) {
+            returnBuilder.statement(call);
+            returnBuilder.returnStatement();
+        } else if (isVoid(delegate.getReturnType())) {
+            returnBuilder.statement(call);
+            returnBuilder.returnDefault();
+        } else {
+            returnBuilder.startReturn().tree(call).end();
+        }
+
+        CodeTreeBuilder builder = parent.create();
+
+        if (!needsUnexpectedResultException(source) && needsUnexpectedResultException(delegate)) {
+            builder.startTryBlock();
+            builder.tree(returnBuilder.build());
+            builder.end().startCatchBlock(context.getType(UnexpectedResultException.class), "ex");
+            if (!isVoid(source.getReturnType())) {
+                builder.startReturn().tree(cast(context.getType(Object.class), source.getReturnType(), CodeTreeBuilder.singleString("ex.getResult()"))).end();
+            }
+            builder.end();
+        } else {
+            builder.tree(returnBuilder.build());
+        }
+        return builder.build();
+    }
+
+    private ExecutableTypeData findFastPathDelegate(TypeMirror targetType, ExecutableTypeData executableType, List<ExecutableTypeData> allTypes) {
+        if (typeEquals(executableType.getReturnType(), targetType)) {
+            // type matches look for even better delegates
+            for (ExecutableTypeData type : allTypes) {
+                if (typeEquals(type.getReturnType(), targetType) && executableType.sameParameters(type)) {
+                    if (type != executableType) {
+                        return type;
+                    }
+                }
+            }
+            return null;
+        } else {
+            for (ExecutableTypeData type : allTypes) {
+                if (typeEquals(type.getReturnType(), targetType) && executableType.sameParameters(type)) {
+                    return type;
+                }
+            }
+            int executableIndex = allTypes.indexOf(executableType);
+            int compareIndex = 0;
+            for (ExecutableTypeData type : allTypes) {
+                if (executableIndex != compareIndex && executableType.sameParameters(type)) {
+                    int result = ExecutableTypeData.compareType(context, type.getReturnType(), executableType.getReturnType());
+                    if (result < 0) {
+                        return type;
+                    } else if (result == 0 && executableIndex < compareIndex) {
+                        return type;
+                    }
+                }
+                compareIndex++;
+            }
+            return null;
+        }
+    }
+
+    private LocalVariable resolveShortCircuit(SpecializationData specialization, NodeExecutionData execution, LocalContext currentLocals) {
+        LocalVariable shortCircuit = null;
+        if (execution.isShortCircuit()) {
+            shortCircuit = currentLocals.getShortCircuit(execution);
+
+            if (shortCircuit == null) {
+                SpecializationData resolvedSpecialization = specialization;
+                if (specialization == null) {
+                    resolvedSpecialization = node.getGenericSpecialization();
+                }
+                ShortCircuitData shortCircuitData = resolvedSpecialization.getShortCircuits().get(calculateShortCircuitIndex(execution));
+                CodeTree access = callTemplateMethod(accessParent(null), shortCircuitData, currentLocals);
+                shortCircuit = currentLocals.createShortCircuitValue(execution).accessWith(access);
+            } else {
+                CodeTree access = shortCircuit.createReference();
+                shortCircuit = shortCircuit.nextName().accessWith(access);
+            }
+        }
+        return shortCircuit;
+    }
+
+    private int calculateShortCircuitIndex(NodeExecutionData execution) {
+        int shortCircuitIndex = 0;
+        for (NodeExecutionData otherExectuion : node.getChildExecutions()) {
+            if (otherExectuion.isShortCircuit()) {
+                if (otherExectuion == execution) {
+                    break;
+                }
+                shortCircuitIndex++;
+            }
+        }
+        return shortCircuitIndex;
+    }
+
+    private CodeTree createFastPathExecute(CodeTreeBuilder parent, final ExecutableTypeData forType, SpecializationData specialization, LocalContext currentValues) {
+        CodeTreeBuilder builder = parent.create();
+        int ifCount = 0;
+        if (specialization.isFallback()) {
+            builder.startIf().startCall("guardFallback");
+            if (node.isFrameUsedByAnyGuard()) {
+                if (currentValues.get(FRAME_VALUE) != null) {
+                    builder.string(FRAME_VALUE);
+                } else {
+                    builder.nullLiteral();
+                }
+            }
+            currentValues.addReferencesTo(builder);
+
+            builder.end();
+            builder.end();
+            builder.startBlock();
+            ifCount++;
+        }
+        CodeTreeBuilder execute = builder.create();
+
+        if (!specialization.getAssumptionExpressions().isEmpty()) {
+            builder.startTryBlock();
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                LocalVariable assumptionVar = currentValues.get(assumptionName(assumption));
+                if (assumptionVar == null) {
+                    throw new AssertionError("Could not resolve assumption var " + currentValues);
+                }
+                builder.startStatement().startCall("check").tree(assumptionVar.createReference()).end().end();
+            }
+            builder.end().startCatchBlock(getType(InvalidAssumptionException.class), "ae");
+            builder.startReturn();
+            List<String> assumptionIds = new ArrayList<>();
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                assumptionIds.add(assumption.getId());
+            }
+            builder.tree(createCallDelegate("removeThis", String.format("Assumption %s invalidated", assumptionIds), forType, currentValues));
+            builder.end();
+            builder.end();
+        }
+
+        if (specialization.getMethod() == null) {
+            execute.startReturn();
+            execute.startCall("unsupported");
+            currentValues.addReferencesTo(execute, FRAME_VALUE);
+            execute.end();
+            execute.end();
+        } else {
+            boolean doReturn = !isVoid(specialization.getMethod().getReturnType());
+            if (doReturn) {
+                execute.startReturn();
+            } else {
+                execute.startStatement();
+            }
+            execute.tree(callTemplateMethod(accessParent(null), specialization, currentValues));
+            execute.end();
+            if (!doReturn) {
+                if (isVoid(forType.getReturnType())) {
+                    execute.returnStatement();
+                } else {
+                    execute.startReturn();
+                    execute.defaultValue(forType.getReturnType());
+                    execute.end();
+                }
+            }
+        }
+        builder.tree(createFastPathTryCatchRewriteException(specialization, forType, currentValues, execute.build()));
+        builder.end(ifCount);
+        return builder.build();
+    }
+
+    private CodeTree createGuardAndCast(SpecializationGroup group, TypeMirror forType, LocalContext currentValues, SpecializationBody execution) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        Set<TypeGuard> castGuards;
+        if (execution.needsCastedValues()) {
+            castGuards = null; // cast all
+        } else {
+            castGuards = new HashSet<>();
+            for (TypeGuard castGuard : group.getTypeGuards()) {
+                if (isTypeGuardUsedInAnyGuardOrCacheBelow(group, currentValues, castGuard, execution.isFastPath())) {
+                    castGuards.add(castGuard);
+                }
+            }
+        }
+
+        SpecializationData specialization = group.getSpecialization();
+        CodeTree[] checkAndCast = createTypeCheckAndLocals(specialization, group.getTypeGuards(), castGuards, currentValues, execution);
+
+        CodeTree check = checkAndCast[0];
+        CodeTree cast = checkAndCast[1];
+
+        List<GuardExpression> elseGuardExpressions = group.findElseConnectableGuards();
+        List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards());
+        guardExpressions.removeAll(elseGuardExpressions);
+        CodeTree[] methodGuardAndAssertions = createMethodGuardCheck(guardExpressions, specialization, currentValues, execution.isFastPath());
+        CodeTree methodGuards = methodGuardAndAssertions[0];
+        CodeTree guardAssertions = methodGuardAndAssertions[1];
+
+        int ifCount = 0;
+        if (!check.isEmpty()) {
+            builder.startIf();
+            builder.tree(check).end();
+            builder.startBlock();
+            ifCount++;
+        }
+        if (!cast.isEmpty()) {
+            builder.tree(cast);
+        }
+        boolean elseIf = !elseGuardExpressions.isEmpty();
+        if (!methodGuards.isEmpty()) {
+            builder.startIf(elseIf);
+            builder.tree(methodGuards).end();
+            builder.startBlock();
+            ifCount++;
+        } else if (elseIf) {
+            builder.startElseBlock();
+            ifCount++;
+        }
+        if (!guardAssertions.isEmpty()) {
+            builder.tree(guardAssertions);
+        }
+
+        boolean reachable = isReachableGroup(group, ifCount);
+        if (reachable) {
+            for (SpecializationGroup child : group.getChildren()) {
+                builder.tree(createGuardAndCast(child, forType, currentValues.copy(), execution));
+            }
+            if (specialization != null) {
+                builder.tree(execution.createBody(specialization, currentValues));
+            }
+        }
+        builder.end(ifCount);
+
+        return builder.build();
+    }
+
+    private static boolean isReachableGroup(SpecializationGroup group, int ifCount) {
+        if (ifCount != 0) {
+            return true;
+        }
+        SpecializationGroup previous = group.getPreviousGroup();
+        if (previous == null || previous.findElseConnectableGuards().isEmpty()) {
+            return true;
+        }
+
+        /*
+         * Hacky else case. In this case the specialization is not reachable due to previous else
+         * branch. This is only true if the minimum state is not checked.
+         */
+        if (previous.getGuards().size() == 1 && previous.getTypeGuards().isEmpty() &&
+                        (previous.getParent() == null || previous.getMaxSpecializationIndex() != previous.getParent().getMaxSpecializationIndex())) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean isTypeGuardUsedInAnyGuardOrCacheBelow(SpecializationGroup group, LocalContext currentValues, TypeGuard typeGuard, boolean fastPath) {
+        String localName = currentValues.getValue(typeGuard.getSignatureIndex()).getName();
+
+        SpecializationData specialization = group.getSpecialization();
+        for (GuardExpression guard : group.getGuards()) {
+            if (isVariableBoundIn(specialization, guard.getExpression(), localName, currentValues)) {
+                return true;
+            }
+        }
+        if (!fastPath && specialization != null) {
+            for (CacheExpression cache : specialization.getCaches()) {
+                if (isVariableBoundIn(specialization, cache.getExpression(), localName, currentValues)) {
+                    return true;
+                }
+            }
+        }
+
+        for (SpecializationGroup child : group.getChildren()) {
+            if (isTypeGuardUsedInAnyGuardOrCacheBelow(child, currentValues, typeGuard, fastPath)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean isVariableBoundIn(SpecializationData specialization, DSLExpression expression, String localName, LocalContext currentValues) throws AssertionError {
+        Map<Variable, LocalVariable> boundValues = bindExpressionValues(expression, specialization, currentValues);
+        for (Variable var : expression.findBoundVariables()) {
+            LocalVariable target = boundValues.get(var);
+            if (target != null && localName.equals(target.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private CodeExecutableElement createExecuteChildMethod(NodeExecutionData execution, TypeMirror targetType) {
+        if (!usedExecuteChildMethods.contains(execution)) {
+            return null;
+        }
+
+        LocalContext locals = LocalContext.load(this, createSpecializationNodeSignature(0), Integer.MAX_VALUE);
+
+        CodeExecutableElement method = locals.createMethod(modifiers(PROTECTED, FINAL), targetType, executeChildMethodName(execution, targetType), Integer.MAX_VALUE, FRAME_VALUE);
+        if (hasChildUnexpectedResult(execution, targetType)) {
+            method.getThrownTypes().add(getType(UnexpectedResultException.class));
+        }
+
+        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetType);
+        if (implicitProfile != null) {
+            method.addParameter(implicitProfile);
+        }
+
+        for (int i = 0; i < execution.getChild().getExecuteWith().size(); i++) {
+            NodeExecutionData executeWith = node.getChildExecutions().get(i);
+            LocalVariable var = locals.createValue(executeWith, genericType);
+            method.addParameter(var.createParameter());
+            locals.setValue(executeWith, var);
+        }
+
+        CodeTreeBuilder builder = method.createBuilder();
+        CodeTree executeChild = createExecuteChild(execution, locals.createValue(execution, targetType), locals, true);
+        if (executeChild.isSingleLine()) {
+            builder.statement(executeChild);
+        } else {
+            builder.tree(executeChild);
+        }
+        return method;
+    }
+
+    private CodeVariableElement createImplicitProfileParameter(NodeExecutionData execution, TypeMirror targetType) {
+        if (typeSystem.hasImplicitSourceTypes(targetType)) {
+            if (typeEquals(node.getGenericType(execution), targetType)) {
+                return null;
+            }
+
+            switch (options.implicitCastOptimization()) {
+                case NONE:
+                    return null;
+                case DUPLICATE_TAIL:
+                    return new CodeVariableElement(getType(Class.class), implicitClassFieldName(execution));
+                case MERGE_CASTS:
+                    return new CodeVariableElement(ImplicitCastNodeFactory.type(typeSystem, targetType), implicitNodeFieldName(execution));
+            }
+        }
+        return null;
+    }
+
+    private boolean isExecuteChildShared(NodeExecutionData execution, TypeMirror targetType) {
+        if (isVoid(targetType)) {
+            return false;
+        } else if (isObject(targetType)) {
+            return resolvePolymorphicExecutables(execution).size() >= 1;
+        } else {
+            if (!isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), targetType)) {
+                return false;
+            }
+            if (!typeSystem.hasImplicitSourceTypes(targetType)) {
+                return false;
+            }
+
+            int uses = 0;
+            for (SpecializationData specialization : node.getSpecializations()) {
+                List<Parameter> parameters = specialization.findByExecutionData(execution);
+                for (Parameter parameter : parameters) {
+                    if (targetType.equals(parameter.getType())) {
+                        uses++;
+                    }
+                }
+            }
+            if (uses > 1) {
+                return resolveSpecializedExecutables(execution, typeSystem.lookupSourceTypes(targetType), options.implicitTypeBoxingOptimization()).size() > 1;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    private CodeTree createAssignExecuteChild(CodeTreeBuilder parent, NodeExecutionData execution, ExecutableTypeData type, LocalVariable targetValue, LocalVariable shortCircuit,
+                    LocalContext currentValues) {
+        CodeTreeBuilder builder = parent.create();
+        boolean hasUnexpected = hasChildUnexpectedResult(execution, targetValue.getTypeMirror());
+
+        CodeTree executeChild;
+        if (isExecuteChildShared(execution, targetValue.getTypeMirror())) {
+            executeChild = createCallSharedExecuteChild(execution, targetValue, currentValues);
+        } else {
+            executeChild = createExecuteChild(execution, targetValue, currentValues, false);
+        }
+
+        builder.tree(createTryExecuteChild(targetValue, executeChild, shortCircuit == null, hasUnexpected));
+
+        if (shortCircuit != null) {
+            currentValues.setShortCircuitValue(execution, shortCircuit.accessWith(null));
+        }
+
+        builder.end();
+        if (hasUnexpected) {
+            builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
+            LocalContext slowPathValues = currentValues.copy();
+            slowPathValues.setValue(execution, targetValue.makeGeneric(context).accessWith(CodeTreeBuilder.singleString("ex.getResult()")));
+
+            ExecutableTypeData delegateType = node.getGenericExecutableType(type);
+            boolean found = false;
+            for (NodeExecutionData otherExecution : node.getChildExecutions()) {
+                if (found) {
+                    LocalVariable childEvaluatedValue = slowPathValues.createValue(otherExecution, genericType);
+                    LocalVariable genericShortCircuit = resolveShortCircuit(null, otherExecution, slowPathValues);
+                    builder.tree(createAssignExecuteChild(builder, otherExecution, delegateType, childEvaluatedValue, genericShortCircuit, slowPathValues));
+                    slowPathValues.setValue(otherExecution, childEvaluatedValue);
+                } else {
+                    // skip forward already evaluated
+                    found = execution == otherExecution;
+                }
+            }
+            builder.tree(createCallNext(builder, type, delegateType, slowPathValues));
+            builder.end();
+        }
+
+        return createShortCircuit(targetValue, shortCircuit, builder.build());
+    }
+
+    private static CodeTree createShortCircuit(LocalVariable targetValue, LocalVariable shortCircuitValue, CodeTree tryExecute) {
+        if (shortCircuitValue == null) {
+            return tryExecute;
+        }
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        builder.tree(shortCircuitValue.createDeclaration(shortCircuitValue.createReference()));
+        builder.tree(targetValue.createDeclaration(builder.create().defaultValue(targetValue.getTypeMirror()).build()));
+
+        builder.startIf().string(shortCircuitValue.getName()).end().startBlock();
+        builder.tree(tryExecute);
+        builder.end();
+
+        return builder.build();
+    }
+
+    private static CodeTree createTryExecuteChild(LocalVariable value, CodeTree executeChild, boolean needDeclaration, boolean hasTry) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        boolean hasDeclaration = false;
+        if ((hasTry || !executeChild.isSingleLine()) && needDeclaration) {
+            builder.tree(value.createDeclaration(null));
+            hasDeclaration = true;
+        }
+
+        if (hasTry) {
+            builder.startTryBlock();
+        } else {
+            builder.startGroup();
+        }
+
+        if (executeChild.isSingleLine()) {
+            builder.startStatement();
+            if (hasDeclaration || !needDeclaration) {
+                builder.tree(executeChild);
+            } else {
+                builder.type(value.getTypeMirror()).string(" ").tree(executeChild);
+            }
+            builder.end();
+        } else {
+            builder.tree(executeChild);
+        }
+
+        builder.end();
+
+        return builder.build();
+    }
+
+    private CodeTree createCallSharedExecuteChild(NodeExecutionData execution, LocalVariable targetValue, LocalContext currentValues) {
+        if (!isExecuteChildShared(execution, targetValue.getTypeMirror())) {
+            throw new AssertionError("Execute child not shared with method but called.");
+        }
+        usedExecuteChildMethods.add(execution);
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.tree(targetValue.createReference()).string(" = ");
+        builder.startCall(executeChildMethodName(execution, targetValue.getTypeMirror()));
+        if (currentValues.get(FRAME_VALUE) == null) {
+            builder.nullLiteral();
+        } else {
+            builder.string(FRAME_VALUE);
+        }
+
+        CodeVariableElement implicitProfile = createImplicitProfileParameter(execution, targetValue.getTypeMirror());
+        if (implicitProfile != null) {
+            builder.string(implicitProfile.getName());
+        }
+        for (int i = 0; i < execution.getChild().getExecuteWith().size(); i++) {
+            builder.tree(currentValues.getValue(i).createReference());
+        }
+        builder.end();
+        return builder.build();
+    }
+
+    private CodeTree createExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) {
+        final CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        CodeTree assignment = createAssignmentStart(target, shared);
+
+        final Set<ExecutableTypeData> executableTypes = findSpecializedExecutableTypes(execution, target.getTypeMirror());
+        if (executableTypes.isEmpty()) {
+            throw new AssertionError(); // cannot execute child
+        } else if (executableTypes.size() == 1 && !typeSystem.hasImplicitSourceTypes(target.getTypeMirror())) {
+            ExecutableTypeData executableType = executableTypes.iterator().next();
+            if (isObject(target.getTypeMirror()) && executableType.getEvaluatedCount() == 0) {
+                return createPolymorphicExecuteChild(execution, target, currentValues, shared);
+            } else {
+                builder.tree(assignment);
+                builder.tree(createSingleExecute(execution, target, currentValues, executableType));
+            }
+        } else {
+            if (options.implicitCastOptimization().isNone()) {
+                throw new AssertionError("findSpecializedExecutableTypes is always 1 if implicit cast opt is disabled");
+            } else if (options.implicitCastOptimization().isDuplicateTail()) {
+                builder.tree(createExecuteChildDuplicateTail(builder, execution, assignment, target, currentValues));
+            } else if (options.implicitCastOptimization().isMergeCasts()) {
+                // TODO
+                throw new UnsupportedOperationException();
+            } else {
+                throw new AssertionError();
+            }
+        }
+        return builder.build();
+    }
+
+    private CodeTree createSingleExecute(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, ExecutableTypeData executableType) {
+        CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
+        return expect(executableType.getReturnType(), target.getTypeMirror(), execute);
+    }
+
+    private CodeTree createPolymorphicExecuteChild(NodeExecutionData execution, LocalVariable target, LocalContext currentValues, boolean shared) throws AssertionError {
+        ExecutableTypeData genericExecutableType = execution.getChild().getNodeData().findAnyGenericExecutableType(context, execution.getChild().getExecuteWith().size());
+        if (genericExecutableType == null) {
+            throw new AssertionError("At least one generic executable method must be available.");
+        }
+
+        List<ExecutableTypeData> specializedExecutables = resolvePolymorphicExecutables(execution);
+        Collections.sort(specializedExecutables, new Comparator<ExecutableTypeData>() {
+            public int compare(ExecutableTypeData o1, ExecutableTypeData o2) {
+                return compareType(o1.getReturnType(), o2.getReturnType());
+            }
+        });
+
+        CodeTree assignment = createAssignmentStart(target, shared);
+        CodeTree executeGeneric = createSingleExecute(execution, target, currentValues, genericExecutableType);
+
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (specializedExecutables.isEmpty()) {
+            builder.tree(assignment);
+            builder.tree(executeGeneric);
+        } else {
+            final CodeTreeBuilder polyChainBuilder = builder.create();
+            final String profileField = polymorphicTypeProfileFieldName(execution);
+            final String valueFieldName = "_value";
+            final String typeFieldName = "_type";
+
+            builder.declaration(getType(Class.class), profileField, accessParent(profileField));
+
+            boolean encounteredUnexpectedResult = false;
+            boolean hasSpecializedTypes = false;
+            for (ExecutableTypeData executableType : specializedExecutables) {
+                hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
+                polyChainBuilder.string(profileField);
+                polyChainBuilder.string(" == ").typeLiteral(executableType.getReturnType());
+                polyChainBuilder.end();
+                polyChainBuilder.startBlock();
+                polyChainBuilder.startStatement();
+                polyChainBuilder.tree(assignment);
+                polyChainBuilder.tree(createSingleExecute(execution, target, currentValues, executableType)).end();
+                polyChainBuilder.end();
+                encounteredUnexpectedResult |= executableType.hasUnexpectedValue(context);
+            }
+
+            // else if null -> specialize
+            polyChainBuilder.startElseIf().string(profileField).string(" == null").end();
+            polyChainBuilder.startBlock();
+            polyChainBuilder.tree(createTransferToInterpreterAndInvalidate());
+            polyChainBuilder.declaration(context.getType(Class.class), typeFieldName, polyChainBuilder.create().typeLiteral(genericType).build());
+            polyChainBuilder.startTryBlock();
+            polyChainBuilder.declaration(genericExecutableType.getReturnType(), valueFieldName, executeGeneric);
+
+            hasSpecializedTypes = false;
+            for (ExecutableTypeData executableType : specializedExecutables) {
+                hasSpecializedTypes = polyChainBuilder.startIf(hasSpecializedTypes);
+                polyChainBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, executableType.getReturnType(), CodeTreeBuilder.singleString(valueFieldName)));
+                polyChainBuilder.end();
+                polyChainBuilder.startBlock();
+                polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(executableType.getReturnType()).end();
+                polyChainBuilder.end();
+            }
+            polyChainBuilder.startElseBlock();
+            polyChainBuilder.startStatement().string(typeFieldName).string(" = ").typeLiteral(genericType).end();
+            polyChainBuilder.end();
+            polyChainBuilder.startReturn().string(valueFieldName).end();
+
+            polyChainBuilder.end().startFinallyBlock();
+            polyChainBuilder.startStatement().tree(accessParent(profileField)).string(" = ").string(typeFieldName).end();
+            polyChainBuilder.end();
+            polyChainBuilder.end();
+
+            // else -> execute generic
+            polyChainBuilder.startElseBlock();
+            polyChainBuilder.startStatement().tree(assignment).tree(executeGeneric).end();
+            polyChainBuilder.end();
+
+            CodeTree executePolymorphic = polyChainBuilder.build();
+            if (encounteredUnexpectedResult) {
+                builder.startTryBlock();
+                builder.tree(executePolymorphic);
+                builder.end();
+                builder.startCatchBlock(getType(UnexpectedResultException.class), "ex");
+                builder.startStatement().tree(accessParent(profileField)).string(" = ").typeLiteral(genericType).end();
+                builder.startReturn().string("ex.getResult()").end();
+                builder.end();
+            } else {
+                builder.tree(executePolymorphic);
+            }
+        }
+        return builder.build();
+    }
+
+    private List<ExecutableTypeData> resolvePolymorphicExecutables(NodeExecutionData execution) {
+        if (singleSpecializable) {
+            return Collections.emptyList();
+        }
+        Set<TypeMirror> specializedTypes = new HashSet<>();
+        for (TypeMirror type : node.findSpecializedTypes(execution)) {
+            specializedTypes.addAll(typeSystem.lookupSourceTypes(type));
+        }
+        return resolveSpecializedExecutables(execution, specializedTypes, options.polymorphicTypeBoxingElimination());
+    }
+
+    private static CodeTree createAssignmentStart(LocalVariable target, boolean shared) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (shared) {
+            builder.string("return ");
+        } else {
+            builder.string(target.getName()).string(" = ");
+        }
+        return builder.build();
+    }
+
+    private CodeTree createExecuteChildDuplicateTail(CodeTreeBuilder parent, NodeExecutionData execution, CodeTree assignment, LocalVariable target, LocalContext currentValues) {
+        CodeTreeBuilder builder = parent.create();
+        List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror());
+        String implicitClassFieldName = implicitClassFieldName(execution);
+        List<ExecutableTypeData> executableTypes = resolveSpecializedExecutables(execution, sourceTypes, options.implicitTypeBoxingOptimization());
+
+        boolean elseIf = false;
+        for (ExecutableTypeData executableType : executableTypes) {
+            elseIf = builder.startIf(elseIf);
+            builder.string(implicitClassFieldName).string(" == ").typeLiteral(executableType.getReturnType());
+            builder.end();
+            builder.startBlock();
+            builder.startStatement().tree(assignment);
+
+            CodeTree execute = callExecuteMethod(execution, executableType, currentValues);
+            ImplicitCastData cast = typeSystem.lookupCast(executableType.getReturnType(), target.getTypeMirror());
+            if (cast != null) {
+                execute = callMethod(null, cast.getMethod(), execute);
+            }
+            builder.tree(execute);
+            builder.end();
+            builder.end();
+        }
+
+        if (!executableTypes.isEmpty()) {
+            builder.startElseBlock();
+        }
+
+        LocalVariable genericValue = target.makeGeneric(context).nextName();
+        builder.tree(createAssignExecuteChild(builder, execution, node.getGenericExecutableType(null), genericValue, null, currentValues));
+        if (executableTypes.size() == sourceTypes.size()) {
+            builder.startThrow().startNew(getType(UnexpectedResultException.class)).tree(genericValue.createReference()).end().end();
+        } else {
+            builder.startStatement().tree(assignment);
+            builder.tree(TypeSystemCodeGenerator.implicitExpect(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitClassFieldName));
+            builder.end();
+        }
+
+        if (!executableTypes.isEmpty()) {
+            builder.end();
+        }
+        return builder.build();
+    }
+
+    private CodeTree createFastPathTryCatchRewriteException(SpecializationData specialization, ExecutableTypeData forType, LocalContext currentValues, CodeTree execution) {
+        if (specialization.getExceptions().isEmpty()) {
+            return execution;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startTryBlock();
+        builder.tree(execution);
+        TypeMirror[] exceptionTypes = new TypeMirror[specialization.getExceptions().size()];
+        for (int i = 0; i < exceptionTypes.length; i++) {
+            exceptionTypes[i] = specialization.getExceptions().get(i).getJavaClass();
+        }
+        builder.end().startCatchBlock(exceptionTypes, "ex");
+        builder.startStatement().tree(accessParent(excludedFieldName(specialization))).string(" = true").end();
+        builder.tree(createCallRemove("threw rewrite exception", forType, currentValues));
+        builder.end();
+        return builder.build();
+    }
+
+    private CodeTree[] createMethodGuardCheck(List<GuardExpression> guardExpressions, SpecializationData specialization, LocalContext currentValues, boolean fastPath) {
+        CodeTreeBuilder expressionBuilder = CodeTreeBuilder.createBuilder();
+        CodeTreeBuilder assertionBuilder = CodeTreeBuilder.createBuilder();
+        String and = "";
+        for (GuardExpression guard : guardExpressions) {
+            DSLExpression expression = guard.getExpression();
+
+            Map<Variable, CodeTree> resolvedBindings = castBoundTypes(bindExpressionValues(expression, specialization, currentValues));
+            CodeTree expressionCode = DSLExpressionGenerator.write(expression, accessParent(null), resolvedBindings);
+
+            if (!specialization.isDynamicParameterBound(expression) && fastPath) {
+                /*
+                 * Guards where no dynamic parameters are bound can just be executed on the fast
+                 * path.
+                 */
+                assertionBuilder.startAssert().tree(expressionCode).end();
+            } else {
+                expressionBuilder.string(and);
+                expressionBuilder.tree(expressionCode);
+                and = " && ";
+            }
+        }
+        return new CodeTree[]{expressionBuilder.build(), assertionBuilder.build()};
+    }
+
+    private static Map<Variable, CodeTree> castBoundTypes(Map<Variable, LocalVariable> bindings) {
+        Map<Variable, CodeTree> resolvedBindings = new HashMap<>();
+        for (Variable variable : bindings.keySet()) {
+            LocalVariable localVariable = bindings.get(variable);
+            CodeTree resolved = localVariable.createReference();
+            TypeMirror sourceType = localVariable.getTypeMirror();
+            TypeMirror targetType = variable.getResolvedTargetType();
+            if (targetType == null) {
+                targetType = variable.getResolvedType();
+            }
+            if (!ElementUtils.isAssignable(sourceType, targetType)) {
+                resolved = CodeTreeBuilder.createBuilder().cast(targetType, resolved).build();
+            }
+            resolvedBindings.put(variable, resolved);
+        }
+        return resolvedBindings;
+    }
+
+    private static Map<Variable, LocalVariable> bindExpressionValues(DSLExpression expression, SpecializationData specialization, LocalContext currentValues) throws AssertionError {
+        Map<Variable, LocalVariable> bindings = new HashMap<>();
+
+        Set<Variable> boundVariables = expression.findBoundVariables();
+        if (specialization == null && !boundVariables.isEmpty()) {
+            throw new AssertionError("Cannot bind guard variable in non-specialization group. yet.");
+        }
+
+        // resolve bindings for local context
+        for (Variable variable : boundVariables) {
+            Parameter resolvedParameter = specialization.findByVariable(variable.getResolvedVariable());
+            if (resolvedParameter != null) {
+                LocalVariable localVariable;
+                if (resolvedParameter.getSpecification().isSignature()) {
+                    NodeExecutionData execution = resolvedParameter.getSpecification().getExecution();
+                    localVariable = currentValues.getValue(execution);
+                } else {
+                    localVariable = currentValues.get(resolvedParameter.getLocalName());
+                }
+                if (localVariable != null) {
+                    bindings.put(variable, localVariable);
+                }
+            }
+        }
+        return bindings;
+    }
+
+    private CodeTree[] createTypeCheckAndLocals(SpecializationData specialization, List<TypeGuard> typeGuards, Set<TypeGuard> castGuards, LocalContext currentValues,
+                    SpecializationBody specializationExecution) {
+        CodeTreeBuilder checksBuilder = CodeTreeBuilder.createBuilder();
+        CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder();
+        for (TypeGuard typeGuard : typeGuards) {
+            int signatureIndex = typeGuard.getSignatureIndex();
+            LocalVariable value = currentValues.getValue(signatureIndex);
+            TypeMirror targetType = typeGuard.getType();
+            if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) {
+                continue;
+            }
+            NodeExecutionData execution = node.getChildExecutions().get(signatureIndex);
+            if (!checksBuilder.isEmpty()) {
+                checksBuilder.string(" && ");
+            }
+
+            CodeTreeBuilder checkBuilder = checksBuilder.create();
+            CodeTreeBuilder castBuilder = checksBuilder.create();
+
+            LocalVariable shortCircuit = currentValues.getShortCircuit(execution);
+            if (shortCircuit != null) {
+                checkBuilder.string("(");
+                CodeTreeBuilder referenceBuilder = checkBuilder.create();
+                if (!ElementUtils.isPrimitive(shortCircuit.getTypeMirror())) {
+                    referenceBuilder.string("(boolean) ");
+                }
+                referenceBuilder.tree(shortCircuit.createReference());
+                checkBuilder.string("!").tree(referenceBuilder.build());
+                checkBuilder.string(" || ");
+                castBuilder.tree(referenceBuilder.build()).string(" ? ");
+            }
+
+            List<ImplicitCastData> sourceTypes = typeSystem.lookupByTargetType(targetType);
+            CodeTree valueReference = value.createReference();
+            if (sourceTypes.isEmpty()) {
+                checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, value.createReference()));
+                castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference));
+            } else {
+                ImplicitCastOptimization opt = options.implicitCastOptimization();
+                if (specializationExecution.isFastPath() && !opt.isNone()) {
+                    if (opt.isDuplicateTail()) {
+                        String typeHintField = implicitClassFieldName(execution);
+                        checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, typeHintField));
+                        castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, typeHintField));
+                    } else if (opt.isMergeCasts()) {
+                        checkBuilder.tree(ImplicitCastNodeFactory.check(implicitNodeFieldName(execution), valueReference));
+                        castBuilder.tree(ImplicitCastNodeFactory.cast(implicitNodeFieldName(execution), valueReference));
+                    } else {
+                        throw new AssertionError("implicit cast opt");
+                    }
+                } else {
+                    checkBuilder.tree(TypeSystemCodeGenerator.implicitCheck(typeSystem, targetType, valueReference, null));
+                    castBuilder.tree(TypeSystemCodeGenerator.implicitCast(typeSystem, targetType, valueReference, null));
+                }
+            }
+
+            if (shortCircuit != null) {
+                checkBuilder.string(")");
+                castBuilder.string(" : ").defaultValue(targetType);
+            }
+
+            if (castGuards == null || castGuards.contains(typeGuard)) {
+                LocalVariable castVariable = currentValues.getValue(execution).nextName().newType(typeGuard.getType()).accessWith(null);
+                currentValues.setValue(execution, castVariable);
+                localsBuilder.tree(castVariable.createDeclaration(castBuilder.build()));
+            }
+
+            checksBuilder.tree(checkBuilder.build());
+        }
+
+        if (specialization != null && !specializationExecution.isFastPath()) {
+            for (CacheExpression cache : specialization.getCaches()) {
+                if (specialization.isCacheBoundByGuard(cache)) {
+                    initializeCache(localsBuilder, specialization, cache, currentValues);
+                }
+            }
+        }
+
+        return new CodeTree[]{checksBuilder.build(), localsBuilder.build()};
+    }
+
+    private void initializeCache(CodeTreeBuilder builder, SpecializationData specialization, CacheExpression cache, LocalContext currentValues) {
+        CodeTree initializer = DSLExpressionGenerator.write(cache.getExpression(), accessParent(null), castBoundTypes(bindExpressionValues(cache.getExpression(), specialization, currentValues)));
+        String name = cache.getParameter().getLocalName();
+        // multiple specializations might use the same name
+        String varName = name + specialization.getIndex();
+        TypeMirror type = cache.getParameter().getType();
+        builder.declaration(type, varName, initializer);
+        currentValues.set(name, new LocalVariable(type, varName, null, null));
+    }
+
+    public static final class LocalContext {
+
+        private final NodeGenFactory factory;
+        private final Map<String, LocalVariable> values = new HashMap<>();
+
+        private LocalContext(NodeGenFactory factory) {
+            this.factory = factory;
+        }
+
+        public void loadFastPathState(SpecializationData specialization) {
+            for (CacheExpression cache : specialization.getCaches()) {
+                Parameter cacheParameter = cache.getParameter();
+                String name = cacheParameter.getVariableElement().getSimpleName().toString();
+                set(cacheParameter.getLocalName(), new LocalVariable(cacheParameter.getType(), name, CodeTreeBuilder.singleString("this." + name), null));
+            }
+
+            for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
+                String name = assumptionName(assumption);
+                TypeMirror type = assumption.getExpression().getResolvedType();
+                set(name, new LocalVariable(type, name, CodeTreeBuilder.singleString("this." + name), null));
+            }
+        }
+
+        public CodeExecutableElement createMethod(Set<Modifier> modifiers, TypeMirror returnType, String name, int varArgsThreshold, String... optionalArguments) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers, returnType, name);
+            addParametersTo(method, varArgsThreshold, optionalArguments);
+            return method;
+        }
+
+        public static LocalContext load(NodeGenFactory factory, ExecutableTypeData type, int varargsThreshold) {
+            LocalContext context = new LocalContext(factory);
+            context.loadEvaluatedValues(type, varargsThreshold);
+            return context;
+        }
+
+        private void loadEvaluatedValues(ExecutableTypeData executedType, int varargsThreshold) {
+            TypeMirror frame = executedType.getFrameParameter();
+            if (frame == null) {
+                removeValue(FRAME_VALUE);
+            } else {
+                set(FRAME_VALUE, new LocalVariable(frame, FRAME_VALUE, null, null));
+            }
+            for (NodeFieldData field : factory.node.getFields()) {
+                String fieldName = fieldValueName(field);
+                values.put(fieldName, new LocalVariable(field.getType(), fieldName, factory.accessParent(field.getName()), null));
+            }
+            boolean varargs = needsVarargs(false, varargsThreshold);
+            List<TypeMirror> evaluatedParameter = executedType.getEvaluatedParameters();
+            int evaluatedIndex = 0;
+            for (int executionIndex = 0; executionIndex < factory.node.getExecutionCount(); executionIndex++) {
+                NodeExecutionData execution = factory.node.getChildExecutions().get(executionIndex);
+                if (execution.isShortCircuit()) {
+                    if (evaluatedIndex < executedType.getEvaluatedCount()) {
+                        TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex);
+                        LocalVariable shortCircuit = createShortCircuitValue(execution).newType(evaluatedType);
+                        if (varargs) {
+                            shortCircuit = shortCircuit.accessWith(createReadVarargs(evaluatedIndex));
+                        }
+                        values.put(shortCircuit.getName(), shortCircuit.makeOriginal());
+                        evaluatedIndex++;
+                    }
+                }
+                if (evaluatedIndex < executedType.getEvaluatedCount()) {
+                    TypeMirror evaluatedType = evaluatedParameter.get(evaluatedIndex);
+                    LocalVariable value = createValue(execution, evaluatedType);
+                    if (varargs) {
+                        value = value.accessWith(createReadVarargs(evaluatedIndex));
+                    }
+                    values.put(value.getName(), value.makeOriginal());
+                    evaluatedIndex++;
+                }
+            }
+        }
+
+        public static LocalContext load(NodeGenFactory factory) {
+            return load(factory, factory.createSpecializationNodeSignature(factory.node.getSignatureSize()), factory.varArgsThreshold);
+        }
+
+        public LocalContext copy() {
+            LocalContext copy = new LocalContext(factory);
+            copy.values.putAll(values);
+            return copy;
+        }
+
+        private static String fieldValueName(NodeFieldData field) {
+            return field.getName() + "Value";
+        }
+
+        @SuppressWarnings("static-method")
+        public LocalVariable createValue(NodeExecutionData execution, TypeMirror type) {
+            return new LocalVariable(type, valueName(execution), null, null);
+        }
+
+        public LocalVariable createShortCircuitValue(NodeExecutionData execution) {
+            return new LocalVariable(factory.getType(boolean.class), shortCircuitName(execution), null, null);
+        }
+
+        private static String valueName(NodeExecutionData execution) {
+            return execution.getName() + "Value";
+        }
+
+        private static String shortCircuitName(NodeExecutionData execution) {
+            return "has" + ElementUtils.firstLetterUpperCase(valueName(execution));
+        }
+
+        public void set(String id, LocalVariable var) {
+            values.put(id, var);
+        }
+
+        public LocalVariable get(String id) {
+            return values.get(id);
+        }
+
+        public LocalVariable get(Parameter parameter, int signatureIndex) {
+            LocalVariable var = get(parameter.getLocalName());
+            if (var == null && parameter.getSpecification().isSignature()) {
+                // lookup by signature index for executeWith
+                List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
+                if (signatureIndex < childExecutions.size() && signatureIndex >= 0) {
+                    NodeExecutionData execution = childExecutions.get(signatureIndex);
+                    var = getValue(execution);
+                }
+            }
+            return var;
+        }
+
+        public LocalVariable getValue(NodeExecutionData execution) {
+            return get(valueName(execution));
+        }
+
+        public LocalVariable getValue(int signatureIndex) {
+            List<NodeExecutionData> childExecutions = factory.node.getChildExecutions();
+            if (signatureIndex < childExecutions.size()) {
+                return getValue(childExecutions.get(signatureIndex));
+            } else {
+                return null;
+            }
+        }
+
+        public void removeValue(String id) {
+            values.remove(id);
+        }
+
+        public void setValue(NodeExecutionData execution, LocalVariable var) {
+            values.put(valueName(execution), var);
+        }
+
+        public void setShortCircuitValue(NodeExecutionData execution, LocalVariable var) {
+            if (var == null) {
+                return;
+            }
+            values.put(shortCircuitName(execution), var);
+        }
+
+        private boolean needsVarargs(boolean requireLoaded, int varArgsThreshold) {
+            int size = 0;
+            for (NodeExecutionData execution : factory.node.getChildExecutions()) {
+                if (requireLoaded && getValue(execution) == null) {
+                    continue;
+                }
+                if (execution.isShortCircuit()) {
+                    size += 2;
+                } else {
+                    size++;
+                }
+            }
+            return size >= varArgsThreshold;
+        }
+
+        private static CodeTree createReadVarargs(int i) {
+            return CodeTreeBuilder.createBuilder().string("args_[").string(String.valueOf(i)).string("]").build();
+        }
+
+        public void addReferencesTo(CodeTreeBuilder builder, String... optionalNames) {
+            for (String var : optionalNames) {
+                LocalVariable local = values.get(var);
+                if (local == null) {
+                    builder.nullLiteral();
+                } else {
+                    builder.tree(local.createReference());
+                }
+            }
+
+            List<NodeExecutionData> executions = factory.node.getChildExecutions();
+            for (NodeExecutionData execution : executions) {
+                if (execution.isShortCircuit()) {
+                    LocalVariable shortCircuitVar = getShortCircuit(execution);
+                    if (shortCircuitVar != null) {
+                        builder.tree(shortCircuitVar.createReference());
+                    }
+                }
+                LocalVariable var = getValue(execution);
+                if (var != null) {
+                    builder.startGroup();
+                    if (executions.size() == 1 && ElementUtils.typeEquals(var.getTypeMirror(), factory.getType(Object[].class))) {
+                        // if the current type is Object[] do not use varargs for a single argument
+                        builder.string("(Object) ");
+                    }
+                    builder.tree(var.createReference());
+                    builder.end();
+                }
+            }
+        }
+
+        public void addParametersTo(CodeExecutableElement method, int varArgsThreshold, String... optionalNames) {
+            for (String var : optionalNames) {
+                LocalVariable local = values.get(var);
+                if (local != null) {
+                    method.addParameter(local.createParameter());
+                }
+            }
+            if (needsVarargs(true, varArgsThreshold)) {
+                method.addParameter(new CodeVariableElement(factory.getType(Object[].class), "args_"));
+                method.setVarArgs(true);
+            } else {
+                for (NodeExecutionData execution : factory.node.getChildExecutions()) {
+                    if (execution.isShortCircuit()) {
+                        LocalVariable shortCircuitVar = getShortCircuit(execution);
+                        if (shortCircuitVar != null) {
+                            method.addParameter(shortCircuitVar.createParameter());
+                        }
+                    }
+
+                    LocalVariable var = getValue(execution);
+                    if (var != null) {
+                        method.addParameter(var.createParameter());
+                    }
+                }
+            }
+        }
+
+        private LocalVariable getShortCircuit(NodeExecutionData execution) {
+            return values.get(shortCircuitName(execution));
+        }
+
+        @Override
+        public String toString() {
+            return "LocalContext [values=" + values + "]";
+        }
+
+    }
+
+    public static final class LocalVariable {
+
+        private final TypeMirror typeMirror;
+        private final CodeTree accessorTree;
+        private final String name;
+        private final LocalVariable previous;
+
+        public static LocalVariable fromParameter(Parameter parameter) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            String name = null;
+            if (execution == null) {
+                name = parameter.getLocalName();
+            } else {
+                name = createName(execution);
+            }
+            return new LocalVariable(parameter.getType(), name, null, null);
+        }
+
+        private LocalVariable(TypeMirror typeMirror, String name, CodeTree accessorTree, LocalVariable previous) {
+            Objects.requireNonNull(typeMirror);
+            this.typeMirror = typeMirror;
+            this.accessorTree = accessorTree;
+            this.name = name;
+            this.previous = previous;
+        }
+
+        public String getShortCircuitName() {
+            return "has" + ElementUtils.firstLetterUpperCase(getName());
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        private static String createNextName(String name) {
+            return name + "_";
+        }
+
+        private static String createName(NodeExecutionData execution) {
+            if (execution == null) {
+                return "<error>";
+            }
+            return execution.getName() + "Value";
+        }
+
+        public TypeMirror getTypeMirror() {
+            return typeMirror;
+        }
+
+        public CodeVariableElement createParameter() {
+            return new CodeVariableElement(getTypeMirror(), getName());
+        }
+
+        public CodeTree createDeclaration(CodeTree init) {
+            return CodeTreeBuilder.createBuilder().declaration(getTypeMirror(), getName(), init).build();
+        }
+
+        public CodeTree createReference() {
+            if (accessorTree != null) {
+                return accessorTree;
+            } else {
+                return CodeTreeBuilder.singleString(getName());
+            }
+        }
+
+        public LocalVariable newType(TypeMirror newType) {
+            return new LocalVariable(newType, name, accessorTree, this);
+        }
+
+        public LocalVariable accessWith(CodeTree tree) {
+            return new LocalVariable(typeMirror, name, tree, this);
+        }
+
+        public LocalVariable nextName() {
+            return new LocalVariable(typeMirror, createNextName(name), accessorTree, this);
+        }
+
+        public LocalVariable makeOriginal() {
+            return new LocalVariable(typeMirror, name, accessorTree, null);
+        }
+
+        public LocalVariable original() {
+            LocalVariable variable = this;
+            while (variable.previous != null) {
+                variable = variable.previous;
+            }
+            return variable;
+        }
+
+        public LocalVariable makeGeneric(ProcessorContext context) {
+            return newType(context.getType(Object.class));
+        }
+
+        @Override
+        public String toString() {
+            return "Local[type = " + getTypeMirror() + ", name = " + name + ", accessWith = " + accessorTree + "]";
+        }
+
+    }
+
+    private abstract class SpecializationBody {
+
+        private final boolean fastPath;
+        private final boolean needsCastedValues;
+
+        public SpecializationBody(boolean fastPath, boolean needsCastedValues) {
+            this.fastPath = fastPath;
+            this.needsCastedValues = needsCastedValues;
+        }
+
+        public final boolean isFastPath() {
+            return fastPath;
+        }
+
+        public final boolean needsCastedValues() {
+            return needsCastedValues;
+        }
+
+        public abstract CodeTree createBody(SpecializationData specialization, LocalContext currentValues);
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.generator;
+
+import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class TypeSystemCodeGenerator extends CodeTypeElementFactory<TypeSystemData> {
+
+    private static final String LOCAL_VALUE = "value";
+
+    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, String content) {
+        return cast(typeSystem, type, CodeTreeBuilder.singleString(content));
+    }
+
+    public static CodeTree implicitType(TypeSystemData typeSystem, TypeMirror type, CodeTree value) {
+        if (ElementUtils.isObject(type)) {
+            return value;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(typeSystem, type)).tree(value);
+        builder.end();
+        return builder.build();
+    }
+
+    public static CodeTree invokeImplicitCast(TypeSystemData typeSystem, ImplicitCastData cast, CodeTree expression) {
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression);
+        builder.end();
+        return builder.build();
+    }
+
+    public static CodeTree implicitCheck(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, isImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    public static CodeTree implicitExpect(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, expectImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    public static CodeTree implicitCast(TypeSystemData typeSystem, TypeMirror type, CodeTree value, String typeHint) {
+        return callImplictMethod(typeSystem, type, asImplicitTypeMethodName(typeSystem, type), value, typeHint);
+    }
+
+    private static CodeTree callImplictMethod(TypeSystemData typeSystem, TypeMirror type, String methodName, CodeTree value, String typeHint) {
+        if (ElementUtils.isObject(type)) {
+            return value;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        builder.startStaticCall(createTypeSystemGen(typeSystem), methodName).tree(value);
+        if (typeHint != null) {
+            builder.string(typeHint);
+        }
+        builder.end();
+        return builder.build();
+    }
+
+    public static CodeTree cast(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type)) {
+            return content;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        TypeCastData cast = typeSystem.getCast(type);
+        if (cast == null) {
+            builder.cast(ElementUtils.fillInGenericWildcards(type), content);
+        } else {
+            builder.startStaticCall(typeSystem.getTemplateType().asType(), cast.getMethodName()).tree(content).end();
+        }
+        return builder.build();
+    }
+
+    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type) || ElementUtils.isVoid(type)) {
+            return content;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+        if (typeSystem.hasType(type)) {
+            builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(typeSystem, type)).tree(content).end();
+        } else {
+            builder.startCall(expectTypeMethodName(typeSystem, type)).tree(content).end();
+        }
+
+        return builder.build();
+    }
+
+    public static CodeExecutableElement createExpectMethod(Modifier visibility, TypeSystemData typeSystem, TypeMirror sourceTypeOriginal, TypeMirror expectedTypeOriginal) {
+        TypeMirror expectedType = ElementUtils.fillInGenericWildcards(expectedTypeOriginal);
+        TypeMirror sourceType = ElementUtils.fillInGenericWildcards(sourceTypeOriginal);
+        if (ElementUtils.isObject(expectedType) || ElementUtils.isVoid(expectedType)) {
+            return null;
+        }
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(STATIC), expectedType, TypeSystemCodeGenerator.expectTypeMethodName(typeSystem, expectedType));
+        method.setVisibility(visibility);
+        method.addParameter(new CodeVariableElement(sourceType, LOCAL_VALUE));
+        method.addThrownType(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException());
+
+        CodeTreeBuilder body = method.createBuilder();
+        body.startIf().tree(check(typeSystem, expectedType, LOCAL_VALUE)).end().startBlock();
+        body.startReturn().tree(cast(typeSystem, expectedType, LOCAL_VALUE)).end();
+        body.end();
+        body.startThrow().startNew(typeSystem.getContext().getTruffleTypes().getUnexpectedValueException()).string(LOCAL_VALUE).end().end();
+        return method;
+    }
+
+    public static CodeTree expect(TypeSystemData typeSystem, TypeMirror sourceType, TypeMirror targetType, CodeTree content) {
+        if (sourceType != null && !ElementUtils.needsCastTo(sourceType, targetType)) {
+            return content;
+        } else {
+            return expect(typeSystem, targetType, content);
+        }
+    }
+
+    public static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) {
+        return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem));
+    }
+
+    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, String content) {
+        return check(typeSystem, type, CodeTreeBuilder.singleString(content));
+    }
+
+    public static CodeTree check(TypeSystemData typeSystem, TypeMirror type, CodeTree content) {
+        if (ElementUtils.isObject(type)) {
+            return content;
+        }
+        CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
+
+        TypeCheckData check = typeSystem.getCheck(type);
+        if (check == null) {
+            builder.instanceOf(content, ElementUtils.boxType(typeSystem.getContext(), type));
+        } else {
+            builder.startStaticCall(typeSystem.getTemplateType().asType(), check.getMethodName()).tree(content).end();
+        }
+        return builder.build();
+    }
+
+    public static String isTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "is" + getTypeId(typeSystem, type);
+    }
+
+    private static String getTypeId(TypeSystemData typeSystem, TypeMirror type) {
+        return ElementUtils.getTypeId(typeSystem.boxType(type));
+    }
+
+    static String isImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "isImplicit" + getTypeId(typeSystem, type);
+    }
+
+    public static String asTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "as" + getTypeId(typeSystem, type);
+    }
+
+    static String asImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "asImplicit" + getTypeId(typeSystem, type);
+    }
+
+    static String expectImplicitTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "expectImplicit" + getTypeId(typeSystem, type);
+    }
+
+    static String getImplicitClass(TypeSystemData typeSystem, TypeMirror type) {
+        return "getImplicit" + getTypeId(typeSystem, type) + "Class";
+    }
+
+    public static String expectTypeMethodName(TypeSystemData typeSystem, TypeMirror type) {
+        return "expect" + getTypeId(typeSystem, type);
+    }
+
+    static String typeName(TypeSystemData typeSystem) {
+        String name = getSimpleName(typeSystem.getTemplateType());
+        return name + "Gen";
+    }
+
+    static String singletonName(TypeSystemData type) {
+        return createConstantName(getSimpleName(type.getTemplateType().asType()));
+    }
+
+    @Override
+    public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) {
+        CodeTypeElement clazz = new TypeClassFactory(context, typeSystem).create();
+
+        if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) {
+            for (TypeMirror type : typeSystem.lookupTargetTypes()) {
+                clazz.add(new ImplicitCastNodeFactory(context, typeSystem, type).create());
+            }
+        }
+        return clazz;
+    }
+
+    private static class TypeClassFactory {
+
+        private final ProcessorContext context;
+        private final TypeSystemData typeSystem;
+
+        public TypeClassFactory(ProcessorContext context, TypeSystemData typeSystem) {
+            this.context = context;
+            this.typeSystem = typeSystem;
+        }
+
+        public CodeTypeElement create() {
+            String name = typeName(typeSystem);
+            CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType());
+
+            clazz.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), clazz));
+            CodeVariableElement singleton = createSingleton(clazz);
+            clazz.add(singleton);
+
+            for (TypeMirror type : typeSystem.getLegacyTypes()) {
+                if (ElementUtils.isVoid(type) || ElementUtils.isObject(type)) {
+                    continue;
+                }
+
+                clazz.addOptional(createIsTypeMethod(type));
+                clazz.addOptional(createAsTypeMethod(type));
+                clazz.addOptional(createExpectTypeMethod(type, context.getType(Object.class)));
+
+            }
+
+            List<TypeMirror> lookupTargetTypes = typeSystem.lookupTargetTypes();
+            for (TypeMirror type : lookupTargetTypes) {
+                clazz.add(createAsImplicitTypeMethod(type, false));
+                if (typeSystem.getOptions().implicitCastOptimization().isNone()) {
+                    clazz.add(createExpectImplicitTypeMethod(type, false));
+                }
+                clazz.add(createIsImplicitTypeMethod(type, false));
+
+                if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) {
+                    clazz.add(createAsImplicitTypeMethod(type, true));
+                    clazz.add(createExpectImplicitTypeMethod(type, true));
+                    clazz.add(createIsImplicitTypeMethod(type, true));
+                    clazz.add(createGetImplicitClass(type));
+                }
+            }
+            return clazz;
+        }
+
+        private CodeVariableElement createSingleton(CodeTypeElement clazz) {
+            CodeVariableElement field = new CodeVariableElement(modifiers(PUBLIC, STATIC, FINAL), clazz.asType(), singletonName(typeSystem));
+            field.createInitBuilder().startNew(clazz.asType()).end();
+
+            CodeAnnotationMirror annotationMirror = new CodeAnnotationMirror((DeclaredType) context.getType(Deprecated.class));
+            field.getAnnotationMirrors().add(annotationMirror);
+
+            return field;
+        }
+
+        private CodeExecutableElement createIsImplicitTypeMethod(TypeMirror type, boolean typed) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(typeSystem, type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+            if (typed) {
+                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
+            }
+            CodeTreeBuilder builder = method.createBuilder();
+
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            builder.startReturn();
+            String sep = "";
+            for (TypeMirror sourceType : sourceTypes) {
+                builder.string(sep);
+                if (typed) {
+                    builder.string("(typeHint == ").typeLiteral(sourceType).string(" && ");
+                }
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
+                if (typed) {
+                    builder.string(")");
+                }
+                if (sourceTypes.lastIndexOf(sourceType) != sourceTypes.size() - 1) {
+                    builder.newLine();
+                }
+                if (sep.equals("")) {
+                    builder.startIndention();
+                }
+                sep = " || ";
+            }
+            builder.end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createAsImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
+            String name = asImplicitTypeMethodName(typeSystem, type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+            if (useTypeHint) {
+                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
+            }
+
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeMirror sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                if (useTypeHint) {
+                    builder.string("typeHint == ").typeLiteral(sourceType);
+                } else {
+                    builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
+                }
+
+                builder.end().startBlock();
+
+                builder.startReturn();
+                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
+                if (cast != null) {
+                    builder.startCall(cast.getMethodName());
+                }
+                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
+                if (cast != null) {
+                    builder.end();
+                }
+                builder.end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.tree(createTransferToInterpreterAndInvalidate());
+            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createExpectImplicitTypeMethod(TypeMirror type, boolean useTypeHint) {
+            String name = expectImplicitTypeMethodName(typeSystem, type);
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, name);
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+            if (useTypeHint) {
+                method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
+            }
+            method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
+
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
+
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeMirror sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                if (useTypeHint) {
+                    builder.string("typeHint == ").typeLiteral(sourceType);
+                    builder.string(" && ");
+                }
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE));
+
+                builder.end().startBlock();
+
+                builder.startReturn();
+                ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
+                if (cast != null) {
+                    builder.startCall(cast.getMethodName());
+                }
+                builder.tree(cast(typeSystem, sourceType, LOCAL_VALUE)).end();
+                if (cast != null) {
+                    builder.end();
+                }
+                builder.end();
+                builder.end();
+            }
+
+            builder.startElseBlock();
+            builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string(LOCAL_VALUE).end().end();
+            builder.end();
+            return method;
+        }
+
+        private CodeExecutableElement createGetImplicitClass(TypeMirror type) {
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(typeSystem, type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+
+            List<TypeMirror> sourceTypes = typeSystem.lookupSourceTypes(type);
+            CodeTreeBuilder builder = method.createBuilder();
+            boolean elseIf = false;
+            for (TypeMirror sourceType : sourceTypes) {
+                elseIf = builder.startIf(elseIf);
+                builder.tree(check(typeSystem, sourceType, LOCAL_VALUE)).end();
+                builder.end().startBlock();
+                builder.startReturn().typeLiteral(sourceType).end();
+                builder.end();
+            }
+
+            builder.startElseIf().string(LOCAL_VALUE).string(" == ").nullLiteral().end();
+            builder.startBlock();
+            builder.startReturn().typeLiteral(context.getType(Object.class)).end();
+            builder.end();
+
+            builder.startElseBlock();
+            builder.tree(createTransferToInterpreterAndInvalidate());
+            builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
+            builder.end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createIsTypeMethod(TypeMirror type) {
+            if (typeSystem.getCheck(type) != null) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isTypeMethodName(typeSystem, type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+
+            CodeTreeBuilder body = method.createBuilder();
+            body.startReturn().tree(check(typeSystem, type, LOCAL_VALUE)).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createAsTypeMethod(TypeMirror type) {
+            if (typeSystem.getCast(type) != null) {
+                return null;
+            }
+
+            CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type, TypeSystemCodeGenerator.asTypeMethodName(typeSystem, type));
+            method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
+
+            CodeTreeBuilder body = method.createBuilder();
+            String assertMessage = typeName(typeSystem) + "." + asTypeMethodName(typeSystem, type) + ": " + ElementUtils.getSimpleName(type) + " expected";
+            body.startAssert().tree(check(typeSystem, type, LOCAL_VALUE)).string(" : ").doubleQuote(assertMessage).end();
+            body.startReturn().tree(cast(typeSystem, type, LOCAL_VALUE)).end();
+
+            return method;
+        }
+
+        private CodeExecutableElement createExpectTypeMethod(TypeMirror expectedType, TypeMirror sourceType) {
+            return createExpectMethod(Modifier.PUBLIC, typeSystem, sourceType, expectedType);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1256 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public class ElementUtils {
+
+    public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) {
+        if (element.isArray()) {
+            return processingEnv.getTypeUtils().getArrayType(getType(processingEnv, element.getComponentType()));
+        }
+        if (element.isPrimitive()) {
+            if (element == void.class) {
+                return processingEnv.getTypeUtils().getNoType(TypeKind.VOID);
+            }
+            TypeKind typeKind;
+            if (element == boolean.class) {
+                typeKind = TypeKind.BOOLEAN;
+            } else if (element == byte.class) {
+                typeKind = TypeKind.BYTE;
+            } else if (element == short.class) {
+                typeKind = TypeKind.SHORT;
+            } else if (element == char.class) {
+                typeKind = TypeKind.CHAR;
+            } else if (element == int.class) {
+                typeKind = TypeKind.INT;
+            } else if (element == long.class) {
+                typeKind = TypeKind.LONG;
+            } else if (element == float.class) {
+                typeKind = TypeKind.FLOAT;
+            } else if (element == double.class) {
+                typeKind = TypeKind.DOUBLE;
+            } else {
+                assert false;
+                return null;
+            }
+            return processingEnv.getTypeUtils().getPrimitiveType(typeKind);
+        } else {
+            TypeElement typeElement = processingEnv.getElementUtils().getTypeElement(element.getCanonicalName());
+            if (typeElement == null) {
+                return null;
+            }
+            return typeElement.asType();
+        }
+    }
+
+    public static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    public static boolean needsCastTo(TypeMirror sourceType, TypeMirror targetType) {
+        if (typeEquals(sourceType, targetType)) {
+            return false;
+        } else if (isObject(targetType)) {
+            return false;
+        } else if (isVoid(targetType)) {
+            return false;
+        } else if (isAssignable(sourceType, targetType)) {
+            return false;
+        }
+        return true;
+    }
+
+    public static String createReferenceName(ExecutableElement method) {
+        StringBuilder b = new StringBuilder();
+
+        b.append(method.getSimpleName().toString());
+        b.append("(");
+
+        String sep = "";
+        for (VariableElement parameter : method.getParameters()) {
+            b.append(sep);
+            b.append(ElementUtils.getSimpleName(parameter.asType()));
+            sep = ", ";
+        }
+
+        b.append(")");
+        return b.toString();
+    }
+
+    public static TypeMirror boxType(ProcessorContext context, TypeMirror primitiveType) {
+        if (primitiveType == null) {
+            return null;
+        }
+        TypeMirror boxedType = primitiveType;
+        if (boxedType.getKind().isPrimitive()) {
+            boxedType = context.getEnvironment().getTypeUtils().boxedClass((PrimitiveType) boxedType).asType();
+        }
+        return boxedType;
+    }
+
+    public static DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) {
+        return new DeclaredCodeTypeMirror(typeElem, Arrays.asList(typeArgs));
+    }
+
+    public static List<AnnotationMirror> collectAnnotations(ProcessorContext context, AnnotationMirror markerAnnotation, String elementName, Element element,
+                    Class<? extends Annotation> annotationClass) {
+        List<AnnotationMirror> result = new ArrayList<>();
+        if (markerAnnotation != null) {
+            result.addAll(ElementUtils.getAnnotationValueList(AnnotationMirror.class, markerAnnotation, elementName));
+        }
+        AnnotationMirror explicit = ElementUtils.findAnnotationMirror(context.getEnvironment(), element, annotationClass);
+        if (explicit != null) {
+            result.add(explicit);
+        }
+        return result;
+    }
+
+    public static TypeMirror getCommonSuperType(ProcessorContext context, Collection<TypeMirror> types) {
+        if (types.isEmpty()) {
+            return context.getType(Object.class);
+        }
+        Iterator<TypeMirror> typesIterator = types.iterator();
+        TypeMirror prev = typesIterator.next();
+        while (typesIterator.hasNext()) {
+            prev = getCommonSuperType(context, prev, typesIterator.next());
+        }
+        return prev;
+    }
+
+    private static TypeMirror getCommonSuperType(ProcessorContext context, TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return type1;
+        }
+        if (isVoid(type1)) {
+            return type2;
+        } else if (isVoid(type2)) {
+            return type1;
+        }
+        if (isObject(type1)) {
+            return type1;
+        } else if (isObject(type2)) {
+            return type2;
+        }
+
+        if (isPrimitive(type1) || isPrimitive(type2)) {
+            return context.getType(Object.class);
+        }
+
+        if (isSubtype(type1, type2)) {
+            return type2;
+        } else if (isSubtype(type2, type1)) {
+            return type1;
+        }
+
+        TypeElement element1 = fromTypeMirror(type1);
+        TypeElement element2 = fromTypeMirror(type2);
+
+        if (element1 == null || element2 == null) {
+            return context.getType(Object.class);
+        }
+
+        List<TypeElement> element1Types = getSuperTypes(element1);
+        List<TypeElement> element2Types = getSuperTypes(element2);
+
+        for (TypeElement superType1 : element1Types) {
+            for (TypeElement superType2 : element2Types) {
+                if (typeEquals(superType1.asType(), superType2.asType())) {
+                    return superType2.asType();
+                }
+            }
+        }
+
+        return context.getType(Object.class);
+    }
+
+    public static String getReadableSignature(ExecutableElement method) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(method.getSimpleName().toString());
+        builder.append("(");
+        String sep = "";
+        for (VariableElement var : method.getParameters()) {
+            builder.append(sep);
+            builder.append(getSimpleName(var.asType()));
+            sep = ", ";
+        }
+        builder.append(")");
+        return builder.toString();
+    }
+
+    public static boolean hasError(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case INT:
+            case SHORT:
+            case LONG:
+            case DECLARED:
+            case VOID:
+            case TYPEVAR:
+                return false;
+            case ARRAY:
+                return hasError(((ArrayType) mirror).getComponentType());
+            case ERROR:
+                return true;
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isSubtypeBoxed(ProcessorContext context, TypeMirror from, TypeMirror to) {
+        return isSubtype(boxType(context, from), boxType(context, to));
+    }
+
+    public static boolean isSubtype(TypeMirror type1, TypeMirror type2) {
+        if (type1 instanceof CodeTypeMirror || type2 instanceof CodeTypeMirror) {
+            throw new UnsupportedOperationException();
+        }
+        return ProcessorContext.getInstance().getEnvironment().getTypeUtils().isSubtype(type1, type2);
+    }
+
+    public static boolean isAssignable(TypeMirror from, TypeMirror to) {
+        if (typeEquals(from, to)) {
+            return true;
+        } else if (isVoid(to)) {
+            return true;
+        } else if (isObject(to)) {
+            return true;
+        }
+        ProcessorContext context = ProcessorContext.getInstance();
+        if (!(from instanceof CodeTypeMirror) && !(to instanceof CodeTypeMirror)) {
+            return context.getEnvironment().getTypeUtils().isAssignable(context.reloadType(from), context.reloadType(to));
+        } else {
+            return isAssignableImpl(from, to);
+        }
+    }
+
+    private static boolean isAssignableImpl(TypeMirror from, TypeMirror to) {
+        // JLS 5.1.1 identity conversion
+        if (ElementUtils.typeEquals(from, to)) {
+            return true;
+        }
+
+        if (isObject(to)) {
+            return true;
+        }
+
+        // JLS 5.1.2 widening primitives
+        if (ElementUtils.isPrimitive(from) && ElementUtils.isPrimitive(to)) {
+            TypeKind fromKind = from.getKind();
+            TypeKind toKind = to.getKind();
+            switch (fromKind) {
+                case BYTE:
+                    switch (toKind) {
+                        case SHORT:
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case SHORT:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case CHAR:
+                    switch (toKind) {
+                        case INT:
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case INT:
+                    switch (toKind) {
+                        case LONG:
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case LONG:
+                    switch (toKind) {
+                        case FLOAT:
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+                case FLOAT:
+                    switch (toKind) {
+                        case DOUBLE:
+                            return true;
+                    }
+                    break;
+
+            }
+            return false;
+        } else if (ElementUtils.isPrimitive(from) || ElementUtils.isPrimitive(to)) {
+            return false;
+        }
+
+        if (from instanceof ArrayType && to instanceof ArrayType) {
+            return isAssignable(((ArrayType) from).getComponentType(), ((ArrayType) to).getComponentType());
+        }
+
+        if (from instanceof ArrayType || to instanceof ArrayType) {
+            return false;
+        }
+
+        TypeElement fromType = ElementUtils.fromTypeMirror(from);
+        TypeElement toType = ElementUtils.fromTypeMirror(to);
+        if (fromType == null || toType == null) {
+            return false;
+        }
+        // JLS 5.1.6 narrowing reference conversion
+
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(fromType);
+        for (TypeElement superType : superTypes) {
+            if (ElementUtils.typeEquals(superType.asType(), to)) {
+                return true;
+            }
+        }
+
+        // TODO more spec
+        return false;
+    }
+
+    public static Set<Modifier> modifiers(Modifier... modifier) {
+        return new LinkedHashSet<>(Arrays.asList(modifier));
+    }
+
+    public static String getTypeId(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "Boolean";
+            case BYTE:
+                return "Byte";
+            case CHAR:
+                return "Char";
+            case DOUBLE:
+                return "Double";
+            case FLOAT:
+                return "Float";
+            case SHORT:
+                return "Short";
+            case INT:
+                return "Int";
+            case LONG:
+                return "Long";
+            case DECLARED:
+                return fixECJBinaryNameIssue(((DeclaredType) mirror).asElement().getSimpleName().toString());
+            case ARRAY:
+                return getTypeId(((ArrayType) mirror).getComponentType()) + "Array";
+            case VOID:
+                return "Void";
+            case NULL:
+                return "Null";
+            case WILDCARD:
+                StringBuilder b = new StringBuilder();
+                WildcardType type = (WildcardType) mirror;
+                if (type.getExtendsBound() != null) {
+                    b.append("Extends").append(getTypeId(type.getExtendsBound()));
+                } else if (type.getSuperBound() != null) {
+                    b.append("Super").append(getTypeId(type.getExtendsBound()));
+                }
+                return b.toString();
+            case TYPEVAR:
+                return "Any";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    public static String getSimpleName(TypeElement element) {
+        return getSimpleName(element.asType());
+    }
+
+    public static String getSimpleName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case FLOAT:
+                return "float";
+            case SHORT:
+                return "short";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getDeclaredName((DeclaredType) mirror, true);
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType()) + "[]";
+            case VOID:
+                return "void";
+            case NULL:
+                return "null";
+            case WILDCARD:
+                return getWildcardName((WildcardType) mirror);
+            case TYPEVAR:
+                return "?";
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind() + " mirror: " + mirror);
+        }
+    }
+
+    private static String getWildcardName(WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(getSimpleName(type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(getSimpleName(type.getExtendsBound()));
+        }
+        return b.toString();
+    }
+
+    public static String getDeclaredName(DeclaredType element, boolean includeTypeVariables) {
+        String simpleName = fixECJBinaryNameIssue(element.asElement().getSimpleName().toString());
+
+        if (!includeTypeVariables || element.getTypeArguments().size() == 0) {
+            return simpleName;
+        }
+
+        StringBuilder b = new StringBuilder(simpleName);
+        b.append("<");
+        if (element.getTypeArguments().size() > 0) {
+            for (int i = 0; i < element.getTypeArguments().size(); i++) {
+                b.append(getSimpleName(element.getTypeArguments().get(i)));
+                if (i < element.getTypeArguments().size() - 1) {
+                    b.append(", ");
+                }
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public static String fixECJBinaryNameIssue(String name) {
+        if (name.contains("$")) {
+            int lastIndex = name.lastIndexOf('$');
+            return name.substring(lastIndex + 1, name.length());
+        }
+        return name;
+    }
+
+    public static String getQualifiedName(TypeElement element) {
+        String qualifiedName = element.getQualifiedName().toString();
+        if (qualifiedName.contains("$")) {
+            /*
+             * If a class gets loaded in its binary form by the ECJ compiler it fails to produce the
+             * proper canonical class name. It leaves the $ in the qualified name of the class. So
+             * one instance of a TypeElement may be loaded in binary and one in source form. The
+             * current type comparison in #typeEquals compares by the qualified name so the
+             * qualified name must match. This is basically a hack to fix the returned qualified
+             * name of eclipse.
+             */
+            qualifiedName = qualifiedName.replace('$', '.');
+        }
+        return qualifiedName;
+    }
+
+    public static String getQualifiedName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+                return "boolean";
+            case BYTE:
+                return "byte";
+            case CHAR:
+                return "char";
+            case DOUBLE:
+                return "double";
+            case SHORT:
+                return "short";
+            case FLOAT:
+                return "float";
+            case INT:
+                return "int";
+            case LONG:
+                return "long";
+            case DECLARED:
+                return getQualifiedName(fromTypeMirror(mirror));
+            case ARRAY:
+                return getQualifiedName(((ArrayType) mirror).getComponentType());
+            case VOID:
+                return "void";
+            case NULL:
+                return "null";
+            case TYPEVAR:
+                return getSimpleName(mirror);
+            case ERROR:
+                throw new CompileErrorException("Type error " + mirror);
+            case EXECUTABLE:
+                return ((ExecutableType) mirror).toString();
+            case NONE:
+                return "$none";
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror + " mirror: " + mirror);
+        }
+    }
+
+    public static boolean isVoid(TypeMirror mirror) {
+        return mirror != null && mirror.getKind() == TypeKind.VOID;
+    }
+
+    public static boolean isPrimitive(TypeMirror mirror) {
+        return mirror != null && mirror.getKind().isPrimitive();
+    }
+
+    public static List<String> getQualifiedSuperTypeNames(TypeElement element) {
+        List<TypeElement> types = getSuperTypes(element);
+        List<String> qualifiedNames = new ArrayList<>();
+        for (TypeElement type : types) {
+            qualifiedNames.add(getQualifiedName(type));
+        }
+        return qualifiedNames;
+    }
+
+    public static List<TypeElement> getDeclaredTypes(TypeElement element) {
+        return ElementFilter.typesIn(element.getEnclosedElements());
+    }
+
+    public static boolean isEnclosedIn(Element enclosedIn, Element element) {
+        if (element == null) {
+            return false;
+        } else if (typeEquals(enclosedIn.asType(), element.asType())) {
+            return true;
+        } else {
+            return isEnclosedIn(enclosedIn, element.getEnclosingElement());
+        }
+    }
+
+    public static TypeElement findRootEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+
+        for (int i = elements.size() - 1; i >= 0; i--) {
+            if (elements.get(i).getKind().isClass()) {
+                return (TypeElement) elements.get(i);
+            }
+        }
+
+        return null;
+    }
+
+    public static List<Element> getElementHierarchy(Element e) {
+        List<Element> elements = new ArrayList<>();
+        elements.add(e);
+
+        Element enclosing = e.getEnclosingElement();
+        while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) {
+            elements.add(enclosing);
+            enclosing = enclosing.getEnclosingElement();
+        }
+        if (enclosing != null) {
+            elements.add(enclosing);
+        }
+        return elements;
+    }
+
+    public static TypeElement findNearestEnclosingType(Element element) {
+        List<Element> elements = getElementHierarchy(element);
+        for (Element e : elements) {
+            if (e.getKind().isClass() || e.getKind().isInterface()) {
+                return (TypeElement) e;
+            }
+        }
+        return null;
+    }
+
+    public static List<TypeElement> getDirectSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        TypeElement superElement = getSuperType(element);
+        if (superElement != null) {
+            types.add(superElement);
+            types.addAll(getDirectSuperTypes(superElement));
+        }
+
+        return types;
+    }
+
+    /**
+     * Gets the element representing the {@linkplain TypeElement#getSuperclass() super class} of a
+     * given type element.
+     */
+    public static TypeElement getSuperType(TypeElement element) {
+        if (element.getSuperclass() != null) {
+            return fromTypeMirror(element.getSuperclass());
+        }
+        return null;
+    }
+
+    public static List<TypeElement> getSuperTypes(TypeElement element) {
+        List<TypeElement> types = new ArrayList<>();
+        List<TypeElement> superTypes = null;
+        List<TypeElement> superInterfaces = null;
+        TypeElement superElement = getSuperType(element);
+        if (superElement != null) {
+            types.add(superElement);
+            superTypes = getSuperTypes(superElement);
+        }
+        for (TypeMirror interfaceMirror : element.getInterfaces()) {
+            TypeElement interfaceElement = fromTypeMirror(interfaceMirror);
+            if (interfaceElement != null) {
+                types.add(interfaceElement);
+                if (superInterfaces == null) {
+                    superInterfaces = getSuperTypes(interfaceElement);
+                } else {
+                    superInterfaces.addAll(getSuperTypes(interfaceElement));
+                }
+            }
+        }
+
+        if (superTypes != null) {
+            types.addAll(superTypes);
+        }
+
+        if (superInterfaces != null) {
+            types.addAll(superInterfaces);
+        }
+
+        return types;
+    }
+
+    public static String getPackageName(TypeElement element) {
+        return findPackageElement(element).getQualifiedName().toString();
+    }
+
+    public static String getEnclosedQualifiedName(DeclaredType mirror) {
+        Element e = ((TypeElement) mirror.asElement()).getEnclosingElement();
+        if (e.getKind() == ElementKind.PACKAGE) {
+            return ((PackageElement) e).getQualifiedName().toString();
+        } else if (e.getKind().isInterface() || e.getKind().isClass()) {
+            return getQualifiedName((TypeElement) e);
+        } else {
+            return null;
+        }
+    }
+
+    public static String getPackageName(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+            case NULL:
+            case TYPEVAR:
+                return null;
+            case DECLARED:
+                PackageElement pack = findPackageElement(fromTypeMirror(mirror));
+                if (pack == null) {
+                    throw new IllegalArgumentException("No package element found for declared type " + getSimpleName(mirror));
+                }
+                return pack.getQualifiedName().toString();
+            case ARRAY:
+                return getSimpleName(((ArrayType) mirror).getComponentType());
+            case EXECUTABLE:
+                return null;
+            default:
+                throw new RuntimeException("Unknown type specified " + mirror.getKind());
+        }
+    }
+
+    public static String createConstantName(String simpleName) {
+        // TODO use camel case to produce underscores.
+        return simpleName.toString().toUpperCase();
+    }
+
+    public static TypeElement fromTypeMirror(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case DECLARED:
+                return (TypeElement) ((DeclaredType) mirror).asElement();
+            case ARRAY:
+                return fromTypeMirror(((ArrayType) mirror).getComponentType());
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> getAnnotationValueList(Class<T> expectedListType, AnnotationMirror mirror, String name) {
+        List<? extends AnnotationValue> values = getAnnotationValue(List.class, mirror, name);
+        List<T> result = new ArrayList<>();
+
+        if (values != null) {
+            for (AnnotationValue value : values) {
+                T annotationValue = resolveAnnotationValue(expectedListType, value);
+                if (annotationValue != null) {
+                    result.add(annotationValue);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static <T> T getAnnotationValue(Class<T> expectedType, AnnotationMirror mirror, String name) {
+        return resolveAnnotationValue(expectedType, getAnnotationValue(mirror, name));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
+        if (value == null) {
+            return null;
+        }
+
+        Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null);
+        if (unboxedValue != null) {
+            if (expectedType == TypeMirror.class && unboxedValue instanceof String) {
+                return null;
+            }
+            if (!expectedType.isAssignableFrom(unboxedValue.getClass())) {
+                throw new ClassCastException(unboxedValue.getClass().getName() + " not assignable from " + expectedType.getName());
+            }
+        }
+        return (T) unboxedValue;
+    }
+
+    public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String name) {
+        ExecutableElement valueMethod = null;
+        for (ExecutableElement method : ElementFilter.methodsIn(mirror.getAnnotationType().asElement().getEnclosedElements())) {
+            if (method.getSimpleName().toString().equals(name)) {
+                valueMethod = method;
+                break;
+            }
+        }
+
+        if (valueMethod == null) {
+            return null;
+        }
+
+        AnnotationValue value = mirror.getElementValues().get(valueMethod);
+        if (value == null) {
+            value = valueMethod.getDefaultValue();
+        }
+
+        return value;
+    }
+
+    private static class AnnotationValueVisitorImpl extends AbstractAnnotationValueVisitor7<Object, Void> {
+
+        @Override
+        public Object visitBoolean(boolean b, Void p) {
+            return Boolean.valueOf(b);
+        }
+
+        @Override
+        public Object visitByte(byte b, Void p) {
+            return Byte.valueOf(b);
+        }
+
+        @Override
+        public Object visitChar(char c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitDouble(double d, Void p) {
+            return d;
+        }
+
+        @Override
+        public Object visitFloat(float f, Void p) {
+            return f;
+        }
+
+        @Override
+        public Object visitInt(int i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitLong(long i, Void p) {
+            return i;
+        }
+
+        @Override
+        public Object visitShort(short s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitString(String s, Void p) {
+            return s;
+        }
+
+        @Override
+        public Object visitType(TypeMirror t, Void p) {
+            return t;
+        }
+
+        @Override
+        public Object visitEnumConstant(VariableElement c, Void p) {
+            return c;
+        }
+
+        @Override
+        public Object visitAnnotation(AnnotationMirror a, Void p) {
+            return a;
+        }
+
+        @Override
+        public Object visitArray(List<? extends AnnotationValue> vals, Void p) {
+            return vals;
+        }
+
+    }
+
+    public static String printException(Throwable e) {
+        StringWriter string = new StringWriter();
+        PrintWriter writer = new PrintWriter(string);
+        e.printStackTrace(writer);
+        writer.flush();
+        string.flush();
+        return e.getMessage() + "\r\n" + string.toString();
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, Element element, Class<?> annotationClass) {
+        return findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), annotationClass);
+    }
+
+    public static AnnotationMirror findAnnotationMirror(ProcessingEnvironment processingEnv, List<? extends AnnotationMirror> mirrors, Class<?> annotationClass) {
+        TypeElement expectedAnnotationType = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
+        return findAnnotationMirror(mirrors, expectedAnnotationType.asType());
+    }
+
+    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
+        return findAnnotationMirror(mirrors, expectedAnnotationType.asType());
+    }
+
+    public static AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeMirror expectedAnnotationType) {
+        for (AnnotationMirror mirror : mirrors) {
+            if (typeEquals(mirror.getAnnotationType(), expectedAnnotationType)) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    public static PackageElement findPackageElement(Element type) {
+        List<Element> hierarchy = getElementHierarchy(type);
+        for (Element element : hierarchy) {
+            if (element.getKind() == ElementKind.PACKAGE) {
+                return (PackageElement) element;
+            }
+        }
+        return null;
+    }
+
+    public static String firstLetterUpperCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    public static String firstLetterLowerCase(String name) {
+        if (name == null || name.isEmpty()) {
+            return name;
+        }
+        return Character.toLowerCase(name.charAt(0)) + name.substring(1, name.length());
+    }
+
+    private static ExecutableElement getDeclaredMethod(TypeElement element, String name, TypeMirror[] params) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(element.getEnclosedElements());
+        method: for (ExecutableElement method : methods) {
+            if (!method.getSimpleName().toString().equals(name)) {
+                continue;
+            }
+            if (method.getParameters().size() != params.length) {
+                continue;
+            }
+            for (int i = 0; i < params.length; i++) {
+                TypeMirror param1 = params[i];
+                TypeMirror param2 = method.getParameters().get(i).asType();
+                if (param1.getKind() != TypeKind.TYPEVAR && param2.getKind() != TypeKind.TYPEVAR) {
+                    if (!getQualifiedName(param1).equals(getQualifiedName(param2))) {
+                        continue method;
+                    }
+                }
+            }
+            return method;
+        }
+        return null;
+    }
+
+    public static boolean isDeclaredMethodInSuperType(TypeElement element, String name, TypeMirror[] params) {
+        return !getDeclaredMethodsInSuperTypes(element, name, params).isEmpty();
+    }
+
+    /**
+     * Gets the methods in the super type hierarchy (excluding interfaces) that are overridden by a
+     * method in a subtype.
+     *
+     * @param declaringElement the subtype element declaring the method
+     * @param name the name of the method
+     * @param params the signature of the method
+     */
+    public static List<ExecutableElement> getDeclaredMethodsInSuperTypes(TypeElement declaringElement, String name, TypeMirror... params) {
+        List<ExecutableElement> superMethods = new ArrayList<>();
+        List<TypeElement> superElements = getSuperTypes(declaringElement);
+
+        for (TypeElement superElement : superElements) {
+            ExecutableElement superMethod = getDeclaredMethod(superElement, name, params);
+            if (superMethod != null) {
+                superMethods.add(superMethod);
+            }
+        }
+        return superMethods;
+    }
+
+    public static boolean typeEquals(TypeMirror type1, TypeMirror type2) {
+        if (type1 == type2) {
+            return true;
+        } else if (type1 == null || type2 == null) {
+            return false;
+        } else {
+            if (type1.getKind() == type2.getKind()) {
+                return getUniqueIdentifier(type1).equals(getUniqueIdentifier(type2));
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public static boolean areTypesCompatible(TypeMirror type1, TypeMirror type2) {
+        if (typeEquals(type1, type2)) {
+            return true;
+        } else if (kindIsIntegral(type1.getKind())) {
+            return kindIsIntegral(type2.getKind());
+        } else if (type1.getKind() == TypeKind.NULL) {
+            if (type2.getKind() == TypeKind.NULL) {
+                return false;
+            }
+            return true;
+        } else if (type2.getKind() == TypeKind.NULL) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean kindIsIntegral(TypeKind kind) {
+        return kind == TypeKind.BYTE || kind == TypeKind.SHORT || kind == TypeKind.INT || kind == TypeKind.LONG;
+    }
+
+    public static List<String> getUniqueIdentifiers(List<TypeMirror> typeMirror) {
+        List<String> ids = new ArrayList<>();
+        for (TypeMirror type : typeMirror) {
+            ids.add(getUniqueIdentifier(type));
+        }
+        return ids;
+    }
+
+    public static String getUniqueIdentifier(TypeMirror typeMirror) {
+        if (typeMirror.getKind() == TypeKind.ARRAY) {
+            return getUniqueIdentifier(((ArrayType) typeMirror).getComponentType()) + "[]";
+        } else {
+            return getQualifiedName(typeMirror);
+        }
+    }
+
+    public static int compareByTypeHierarchy(TypeMirror t1, TypeMirror t2) {
+        if (typeEquals(t1, t2)) {
+            return 0;
+        }
+        Set<String> t1SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t1)));
+        if (t1SuperSet.contains(getQualifiedName(t2))) {
+            return -1;
+        }
+
+        Set<String> t2SuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(t2)));
+        if (t2SuperSet.contains(getQualifiedName(t1))) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static boolean canThrowType(List<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) {
+        if (ElementUtils.containsType(thrownTypes, exceptionType)) {
+            return true;
+        }
+
+        if (isRuntimeException(exceptionType)) {
+            return true;
+        }
+
+        // search for any super types
+        for (TypeElement typeElement : getSuperTypes(fromTypeMirror(exceptionType))) {
+            if (ElementUtils.containsType(thrownTypes, typeElement.asType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static void setVisibility(Set<Modifier> modifiers, Modifier visibility) {
+        Modifier current = getVisibility(modifiers);
+        if (current != visibility) {
+            if (current != null) {
+                modifiers.remove(current);
+            }
+            if (visibility != null) {
+                modifiers.add(visibility);
+            }
+        }
+    }
+
+    public static Modifier getVisibility(Set<Modifier> modifier) {
+        for (Modifier mod : modifier) {
+            if (mod == Modifier.PUBLIC || mod == Modifier.PRIVATE || mod == Modifier.PROTECTED) {
+                return mod;
+            }
+        }
+        return null;
+    }
+
+    private static boolean isRuntimeException(TypeMirror type) {
+        Set<String> typeSuperSet = new HashSet<>(getQualifiedSuperTypeNames(fromTypeMirror(type)));
+        return typeSuperSet.contains(RuntimeException.class.getCanonicalName()) || getQualifiedName(type).equals(RuntimeException.class.getCanonicalName());
+    }
+
+    private static boolean containsType(Collection<? extends TypeMirror> collection, TypeMirror type) {
+        for (TypeMirror otherTypeMirror : collection) {
+            if (typeEquals(otherTypeMirror, type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isTopLevelClass(TypeMirror importType) {
+        TypeElement type = fromTypeMirror(importType);
+        if (type != null && type.getEnclosingElement() != null) {
+            return !type.getEnclosingElement().getKind().isClass();
+        }
+        return true;
+    }
+
+    public static boolean isObject(TypeMirror actualType) {
+        return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
+    }
+
+    public static TypeMirror fillInGenericWildcards(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        TypeElement element = (TypeElement) declaredType.asElement();
+        if (element == null) {
+            return type;
+        }
+        int typeParameters = element.getTypeParameters().size();
+        if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) {
+            return ProcessorContext.getInstance().getEnvironment().getTypeUtils().erasure(type);
+        }
+        return type;
+    }
+
+    public static TypeMirror eraseGenericTypes(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        if (declaredType.getTypeArguments().size() == 0) {
+            return type;
+        }
+        return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement());
+    }
+
+    public static boolean variableEquals(VariableElement var1, VariableElement var2) {
+        if (!var1.getSimpleName().equals(var2.getSimpleName())) {
+            return false;
+        }
+        if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) {
+            return false;
+        }
+        if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) {
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean executableEquals(ExecutableElement var1, ExecutableElement var2) {
+        if (!var1.getSimpleName().equals(var2.getSimpleName())) {
+            return false;
+        }
+        if (var1.getParameters().size() != var2.getParameters().size()) {
+            return false;
+        }
+        if (!ElementUtils.typeEquals(var1.asType(), var2.asType())) {
+            return false;
+        }
+        if (!ElementUtils.elementEquals(var1.getEnclosingElement(), var2.getEnclosingElement())) {
+            return false;
+        }
+        for (int i = 0; i < var1.getParameters().size(); i++) {
+            if (!typeEquals(var1.getParameters().get(i).asType(), var2.getParameters().get(i).asType())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static boolean elementEquals(Element element1, Element element2) {
+        if (element1.getKind() != element2.getKind()) {
+            return false;
+        } else if (element1 instanceof VariableElement) {
+            return variableEquals((VariableElement) element1, (VariableElement) element2);
+        } else if (element1 instanceof ExecutableElement) {
+            return executableEquals((ExecutableElement) element1, (ExecutableElement) element2);
+        } else if (element1 instanceof TypeElement) {
+            return typeEquals(element1.asType(), element2.asType());
+        } else if (element1 instanceof PackageElement) {
+            return element1.getSimpleName().equals(element2.getSimpleName());
+        } else {
+            throw new AssertionError("unsupported element type");
+        }
+    }
+
+    public static List<TypeMirror> sortTypes(List<TypeMirror> list, final boolean reverse) {
+        Collections.sort(list, new Comparator<TypeMirror>() {
+            public int compare(TypeMirror o1, TypeMirror o2) {
+                if (reverse) {
+                    return compareType(o2, o1);
+                } else {
+                    return compareType(o1, o2);
+                }
+            }
+        });
+        return list;
+    }
+
+    public static int compareType(TypeMirror signature1, TypeMirror signature2) {
+        if (signature1 == null) {
+            return 1;
+        } else if (signature2 == null) {
+            return -1;
+        }
+
+        if (ElementUtils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+
+        if (signature1.getKind() == TypeKind.DECLARED && signature2.getKind() == TypeKind.DECLARED) {
+            TypeElement element1 = ElementUtils.fromTypeMirror(signature1);
+            TypeElement element2 = ElementUtils.fromTypeMirror(signature2);
+
+            if (ElementUtils.getDirectSuperTypes(element1).contains(element2)) {
+                return -1;
+            } else if (ElementUtils.getDirectSuperTypes(element2).contains(element1)) {
+                return 1;
+            }
+        }
+        return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
+    }
+
+    public static List<TypeMirror> uniqueSortedTypes(Collection<TypeMirror> types, boolean reverse) {
+        if (types.isEmpty()) {
+            return new ArrayList<>(0);
+        } else if (types.size() <= 1) {
+            if (types instanceof List) {
+                return (List<TypeMirror>) types;
+            } else {
+                return new ArrayList<>(types);
+            }
+        }
+        Map<String, TypeMirror> sourceTypes = new HashMap<>();
+        for (TypeMirror type : types) {
+            sourceTypes.put(ElementUtils.getTypeId(type), type);
+        }
+        return sortTypes(new ArrayList<>(sourceTypes.values()), reverse);
+    }
+
+    public static int compareMethod(ExecutableElement method1, ExecutableElement method2) {
+        List<? extends VariableElement> parameters1 = method1.getParameters();
+        List<? extends VariableElement> parameters2 = method2.getParameters();
+        if (parameters1.size() != parameters2.size()) {
+            return Integer.compare(parameters1.size(), parameters2.size());
+        }
+
+        int result = 0;
+        for (int i = 0; i < parameters1.size(); i++) {
+            VariableElement var1 = parameters1.get(i);
+            VariableElement var2 = parameters2.get(i);
+            result = compareType(var1.asType(), var2.asType());
+            if (result != 0) {
+                return result;
+            }
+        }
+
+        result = method1.getSimpleName().toString().compareTo(method2.getSimpleName().toString());
+        if (result == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(method1);
+            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(method2);
+            result = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return result;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/AbstractCompiler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.lang.reflect.*;
+
+public abstract class AbstractCompiler implements Compiler {
+
+    protected static Object method(Object o, String methodName) throws Exception {
+        Method method = o.getClass().getMethod(methodName);
+        method.setAccessible(true);
+        return method.invoke(o);
+    }
+
+    protected static Object method(Object o, String methodName, Class<?>[] paramTypes, Object... values) throws Exception {
+        Method method = o.getClass().getMethod(methodName, paramTypes);
+        method.setAccessible(true);
+        return method.invoke(o, values);
+    }
+
+    protected static Object field(Object o, String fieldName) throws Exception {
+        if (o == null) {
+            return null;
+        }
+        Class<?> clazz = o.getClass();
+        Field field = null;
+        try {
+            field = clazz.getField(fieldName);
+        } catch (NoSuchFieldException e) {
+            while (clazz != null) {
+                try {
+                    field = clazz.getDeclaredField(fieldName);
+                    break;
+                } catch (NoSuchFieldException e1) {
+                    clazz = clazz.getSuperclass();
+                }
+            }
+            if (field == null) {
+                throw e;
+            }
+        }
+        field.setAccessible(true);
+        return field.get(o);
+    }
+
+    protected static String parseHeader(String content) {
+        int index = content.indexOf("/*");
+        if (index == -1) {
+            return null;
+        }
+        if (!content.substring(0, index).trim().equals("")) {
+            // just whitespace before
+            return null;
+        }
+
+        int endIndex = content.indexOf("*/", index);
+        if (endIndex == -1) {
+            return null;
+        }
+        return content.substring(index, endIndex + 2);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/Compiler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+public interface Compiler {
+
+    String getMethodBody(ProcessingEnvironment env, ExecutableElement method);
+
+    String getHeaderComment(ProcessingEnvironment env, Element type);
+
+    List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type);
+
+    List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/CompilerFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import javax.lang.model.element.*;
+
+public class CompilerFactory {
+
+    private static Compiler javac;
+    private static Compiler jdt;
+
+    public static Compiler getCompiler(Element currentElement) {
+        if (JavaCCompiler.isValidElement(currentElement)) {
+            if (javac == null) {
+                javac = new JavaCCompiler();
+            }
+            return javac;
+        } else if (JDTCompiler.isValidElement(currentElement)) {
+            if (jdt == null) {
+                jdt = new JDTCompiler();
+            }
+            return jdt;
+        } else {
+            throw new UnsupportedOperationException("Unsupported compiler for element " + currentElement.getClass().getName() + ".");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JDTCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("org.eclipse.jdt.internal.compiler.apt.model.ElementImpl");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(environment.getElementUtils().getAllMembers(type)));
+
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return sortBySourceOrder(new ArrayList<>(type.getEnclosedElements()));
+    }
+
+    private static List<? extends Element> sortBySourceOrder(List<Element> elements) {
+        Map<TypeElement, List<Element>> groupedByEnclosing = new HashMap<>();
+        for (Element element : elements) {
+            Element enclosing = element.getEnclosingElement();
+            List<Element> grouped = groupedByEnclosing.get(enclosing);
+            if (grouped == null) {
+                grouped = new ArrayList<>();
+                groupedByEnclosing.put((TypeElement) enclosing, grouped);
+            }
+            grouped.add(element);
+        }
+
+        for (TypeElement enclosing : groupedByEnclosing.keySet()) {
+            Collections.sort(groupedByEnclosing.get(enclosing), createSourceOrderComparator(enclosing));
+        }
+
+        if (groupedByEnclosing.size() == 1) {
+            return groupedByEnclosing.get(groupedByEnclosing.keySet().iterator().next());
+        } else {
+            List<TypeElement> enclosingTypes = new ArrayList<>(groupedByEnclosing.keySet());
+
+            Collections.sort(enclosingTypes, new Comparator<TypeElement>() {
+                public int compare(TypeElement o1, TypeElement o2) {
+                    if (ElementUtils.isSubtype(o1.asType(), o2.asType())) {
+                        return 1;
+                    } else {
+                        return -1;
+                    }
+                }
+            });
+
+            List<Element> sourceOrderElements = new ArrayList<>();
+            for (TypeElement typeElement : enclosingTypes) {
+                sourceOrderElements.addAll(groupedByEnclosing.get(typeElement));
+            }
+            return sourceOrderElements;
+        }
+
+    }
+
+    private static Comparator<Element> createSourceOrderComparator(final TypeElement enclosing) {
+
+        Comparator<Element> comparator = new Comparator<Element>() {
+
+            final List<Object> declarationOrder = lookupDeclarationOrder(enclosing);
+
+            public int compare(Element o1, Element o2) {
+                try {
+                    Element enclosing1Element = o1.getEnclosingElement();
+                    Element enclosing2Element = o2.getEnclosingElement();
+
+                    if (!ElementUtils.typeEquals(enclosing1Element.asType(), enclosing2Element.asType())) {
+                        throw new AssertionError();
+                    }
+
+                    Object o1Binding = field(o1, "_binding");
+                    Object o2Binding = field(o2, "_binding");
+
+                    int i1 = declarationOrder.indexOf(o1Binding);
+                    int i2 = declarationOrder.indexOf(o2Binding);
+
+                    if (i1 == -1 || i2 == -1) {
+                        return 0;
+                    }
+
+                    return i1 - i2;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        };
+        return comparator;
+    }
+
+    private static List<Object> lookupDeclarationOrder(TypeElement type) {
+
+        List<Object> declarationOrder;
+        try {
+            Object binding = field(type, "_binding");
+            Class<?> sourceTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+            Class<?> binaryTypeBinding = Class.forName("org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding");
+
+            declarationOrder = null;
+            if (sourceTypeBinding.isAssignableFrom(binding.getClass())) {
+                declarationOrder = findSourceTypeOrder(binding);
+            } else if (binaryTypeBinding.isAssignableFrom(binding.getClass())) {
+                declarationOrder = findBinaryTypeOrder(binding);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return declarationOrder;
+    }
+
+    private static List<Object> findBinaryTypeOrder(Object binding) throws Exception {
+        Object binaryType = lookupBinaryType(binding);
+        final Object[] sortedMethods = (Object[]) method(binaryType, "getMethods");
+
+        List<Object> sortedElements = new ArrayList<>();
+        if (sortedMethods != null) {
+            sortedElements.addAll(Arrays.asList(sortedMethods));
+        }
+        final Object[] sortedFields = (Object[]) method(binaryType, "getFields");
+        if (sortedFields != null) {
+            sortedElements.addAll(Arrays.asList(sortedFields));
+        }
+        final Object[] sortedTypes = (Object[]) method(binaryType, "getMemberTypes", new Class[0]);
+        if (sortedTypes != null) {
+            sortedElements.addAll(Arrays.asList(sortedTypes));
+        }
+
+        Collections.sort(sortedElements, new Comparator<Object>() {
+            public int compare(Object o1, Object o2) {
+                try {
+                    int structOffset1 = (int) field(o1, "structOffset");
+                    int structOffset2 = (int) field(o2, "structOffset");
+                    return structOffset1 - structOffset2;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+
+        Class<?> binaryMethod = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryMethod");
+        Class<?> binaryField = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryField");
+        Class<?> nestedType = Class.forName("org.eclipse.jdt.internal.compiler.env.IBinaryNestedType");
+
+        List<Object> bindings = new ArrayList<>();
+        for (Object sortedElement : sortedElements) {
+            Class<?> elementClass = sortedElement.getClass();
+            if (binaryMethod.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSelector");
+                Object[] foundBindings = (Object[]) method(binding, "getMethods", new Class[]{char[].class}, selector);
+                if (foundBindings == null || foundBindings.length == 0) {
+                    continue;
+                } else if (foundBindings.length == 1) {
+                    bindings.add(foundBindings[0]);
+                } else {
+                    char[] idescriptor = (char[]) method(sortedElement, "getMethodDescriptor");
+                    for (Object foundBinding : foundBindings) {
+                        char[] descriptor = (char[]) method(foundBinding, "signature");
+                        if (descriptor == null && idescriptor == null || Arrays.equals(descriptor, idescriptor)) {
+                            bindings.add(foundBinding);
+                            break;
+                        }
+                    }
+                }
+            } else if (binaryField.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getName");
+                Object foundField = method(binding, "getField", new Class[]{char[].class, boolean.class}, selector, true);
+                if (foundField != null) {
+                    bindings.add(foundField);
+                }
+            } else if (nestedType.isAssignableFrom(elementClass)) {
+                char[] selector = (char[]) method(sortedElement, "getSourceName");
+                Object foundType = method(binding, "getMemberType", new Class[]{char[].class}, selector);
+                if (foundType != null) {
+                    bindings.add(foundType);
+                }
+            } else {
+                throw new AssertionError("Unexpected encountered type " + elementClass);
+            }
+        }
+
+        return bindings;
+    }
+
+    private static Object lookupBinaryType(Object binding) throws Exception {
+        Object lookupEnvironment = field(binding, "environment");
+        Object compoundClassName = field(binding, "compoundName");
+        Object nameEnvironment = field(lookupEnvironment, "nameEnvironment");
+        Object nameEnvironmentAnswer = method(nameEnvironment, "findType", new Class[]{char[][].class}, compoundClassName);
+        Object binaryType = method(nameEnvironmentAnswer, "getBinaryType", new Class[0]);
+        return binaryType;
+    }
+
+    private static List<Object> findSourceTypeOrder(Object binding) throws Exception {
+        Object referenceContext = field(field(binding, "scope"), "referenceContext");
+
+        TreeMap<Integer, Object> orderedBindings = new TreeMap<>();
+
+        collectSourceOrder(orderedBindings, referenceContext, "methods");
+        collectSourceOrder(orderedBindings, referenceContext, "fields");
+        collectSourceOrder(orderedBindings, referenceContext, "memberTypes");
+
+        return new ArrayList<>(orderedBindings.values());
+    }
+
+    private static void collectSourceOrder(TreeMap<Integer, Object> orderedBindings, Object referenceContext, String fieldName) throws Exception {
+        Object[] declarations = (Object[]) field(referenceContext, fieldName);
+        if (declarations != null) {
+            for (int i = 0; i < declarations.length; i++) {
+                Integer declarationSourceStart = (Integer) field(declarations[i], "declarationSourceStart");
+                orderedBindings.put(declarationSourceStart, field(declarations[i], "binding"));
+            }
+        }
+    }
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+
+            char[] source = getSource(method);
+            if (source == null) {
+                return null;
+            }
+
+            /*
+             * AbstractMethodDeclaration decl =
+             * ((MethodBinding)(((ElementImpl)method)._binding)).sourceMethod(); int bodyStart =
+             * decl.bodyStart; int bodyEnd = decl.bodyEnd;
+             */
+            Object decl = method(field(method, "_binding"), "sourceMethod");
+            int bodyStart = (int) field(decl, "bodyStart");
+            int bodyEnd = (int) field(decl, "bodyEnd");
+
+            int length = bodyEnd - bodyStart;
+            char[] target = new char[length];
+            System.arraycopy(source, bodyStart, target, 0, length);
+
+            return new String(target);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    private static char[] getSource(Element element) throws Exception {
+        /*
+         * Binding binding = ((ElementImpl)element)._binding; char[] source = null; if (binding
+         * instanceof MethodBinding) { source = ((MethodBinding)
+         * binding).sourceMethod().compilationResult.getCompilationUnit().getContents(); } else if
+         * (binding instanceof SourceTypeBinding) { source =
+         * ((SourceTypeBinding)binding).scope.referenceContext
+         * .compilationResult.compilationUnit.getContents(); } return source;
+         */
+
+        Object binding = field(element, "_binding");
+        Class<?> methodBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.MethodBinding");
+        Class<?> referenceBindingClass = Class.forName("org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding");
+
+        char[] source = null;
+        if (methodBindingClass.isAssignableFrom(binding.getClass())) {
+            Object sourceMethod = method(binding, "sourceMethod");
+            if (sourceMethod == null) {
+                return null;
+            }
+            source = (char[]) method(method(field(sourceMethod, "compilationResult"), "getCompilationUnit"), "getContents");
+        } else if (referenceBindingClass.isAssignableFrom(binding.getClass())) {
+            source = (char[]) method(field(field(field(field(binding, "scope"), "referenceContext"), "compilationResult"), "compilationUnit"), "getContents");
+        }
+        return source;
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            char[] source = getSource(type);
+            if (source == null) {
+                return null;
+            }
+            return parseHeader(new String(source));
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JavaCCompiler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.compiler;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class JavaCCompiler extends AbstractCompiler {
+
+    public static boolean isValidElement(Element currentElement) {
+        try {
+            Class<?> elementClass = Class.forName("com.sun.tools.javac.code.Symbol");
+            return elementClass.isAssignableFrom(currentElement.getClass());
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
+    public List<? extends Element> getEnclosedElementsInDeclarationOrder(TypeElement type) {
+        return type.getEnclosedElements();
+    }
+
+    public List<? extends Element> getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) {
+        return environment.getElementUtils().getAllMembers(type);
+    }
+
+    private static final Class<?>[] getTreeAndTopLevelSignature = new Class[]{Element.class, AnnotationMirror.class, AnnotationValue.class};
+    private static final Class<?>[] getCharContentSignature = new Class[]{boolean.class};
+
+    @Override
+    public String getMethodBody(ProcessingEnvironment env, ExecutableElement method) {
+        try {
+            /*
+             * if (false) { Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+             * env.getElementUtils()).getTreeAndTopLevel(method, null, null); JCBlock block =
+             * ((JCMethodDecl) treeAndTopLevel.fst).getBody(); int startPos = block.pos; int endPos
+             * = block.endpos; String methodBody =
+             * treeAndTopLevel.snd.getSourceFile().getCharContent(true).subSequence(startPos + 1,
+             * endPos).toString(); return methodBody; }
+             */
+
+            Object treeAndTopLevel = getTreeAndTopLevel(env, method);
+            Object block = method(field(treeAndTopLevel, "fst"), "getBody");
+            int startPos = (int) field(block, "pos");
+            int endPos = (int) field(block, "endpos");
+            return getContent(treeAndTopLevel).subSequence(startPos + 1, endPos).toString();
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+    private static CharSequence getContent(Object treeAndTopLevel) throws Exception {
+        /*
+         * CharSequence content = treeAndTopLevel.snd.getSourceFile().getCharContent(true);
+         */
+        return (CharSequence) method(method(field(treeAndTopLevel, "snd"), "getSourceFile"), "getCharContent", getCharContentSignature, true);
+    }
+
+    private static Object getTreeAndTopLevel(ProcessingEnvironment env, Element element) throws Exception {
+        /*
+         * Pair<JCTree, JCCompilationUnit> treeAndTopLevel = ((JavacElements)
+         * env.getElementUtils()).getTreeAndTopLevel(method, null, null);
+         */
+        return method(method(env, "getElementUtils"), "getTreeAndTopLevel", getTreeAndTopLevelSignature, element, null, null);
+    }
+
+    @Override
+    public String getHeaderComment(ProcessingEnvironment env, Element type) {
+        try {
+            String content = getContent(getTreeAndTopLevel(env, type)).toString();
+            return parseHeader(content);
+        } catch (Exception e) {
+            return ElementUtils.printException(e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationMirror.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeAnnotationMirror implements AnnotationMirror {
+
+    private final DeclaredType annotationType;
+    private final Map<ExecutableElement, AnnotationValue> values = new LinkedHashMap<>();
+
+    public CodeAnnotationMirror(DeclaredType annotationType) {
+        this.annotationType = annotationType;
+    }
+
+    @Override
+    public DeclaredType getAnnotationType() {
+        return annotationType;
+    }
+
+    @Override
+    public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() {
+        return values;
+    }
+
+    public void setElementValue(ExecutableElement method, AnnotationValue value) {
+        values.put(method, value);
+    }
+
+    public ExecutableElement findExecutableElement(String name) {
+        return ElementUtils.findExecutableElement(annotationType, name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeAnnotationValue.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeAnnotationValue implements AnnotationValue {
+
+    private final Object value;
+
+    public CodeAnnotationValue(Object value) {
+        Objects.requireNonNull(value);
+        if ((value instanceof AnnotationMirror) || (value instanceof List<?>) || (value instanceof Boolean) || (value instanceof Byte) || (value instanceof Character) || (value instanceof Double) ||
+                        (value instanceof VariableElement) || (value instanceof Float) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short) ||
+                        (value instanceof String) || (value instanceof TypeMirror)) {
+            this.value = value;
+        } else {
+            throw new IllegalArgumentException("Invalid annotation value type " + value.getClass().getName());
+        }
+    }
+
+    @Override
+    public Object getValue() {
+        return value;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
+        if (value instanceof AnnotationMirror) {
+            return v.visitAnnotation((AnnotationMirror) value, p);
+        } else if (value instanceof List<?>) {
+            return v.visitArray((List<? extends AnnotationValue>) value, p);
+        } else if (value instanceof Boolean) {
+            return v.visitBoolean((boolean) value, p);
+        } else if (value instanceof Byte) {
+            return v.visitByte((byte) value, p);
+        } else if (value instanceof Character) {
+            return v.visitChar((char) value, p);
+        } else if (value instanceof Double) {
+            return v.visitDouble((double) value, p);
+        } else if (value instanceof VariableElement) {
+            return v.visitEnumConstant((VariableElement) value, p);
+        } else if (value instanceof Float) {
+            return v.visitFloat((float) value, p);
+        } else if (value instanceof Integer) {
+            return v.visitInt((int) value, p);
+        } else if (value instanceof Long) {
+            return v.visitLong((long) value, p);
+        } else if (value instanceof Short) {
+            return v.visitShort((short) value, p);
+        } else if (value instanceof String) {
+            return v.visitString((String) value, p);
+        } else if (value instanceof TypeMirror) {
+            return v.visitType((TypeMirror) value, p);
+        } else {
+            return v.visitUnknown(this, p);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeCompilationUnit.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeCompilationUnit extends CodeElement<TypeElement> {
+
+    public CodeCompilationUnit() {
+        super(Collections.<Modifier> emptySet());
+    }
+
+    @Override
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return ElementKind.OTHER;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        for (Element type : getEnclosedElements()) {
+            if (type.getKind().isClass()) {
+                type.accept(v, p);
+            } else {
+                throw new ClassCastException(type.getClass().getName());
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.transform.*;
+
+public abstract class CodeElement<E extends Element> implements Element, GeneratedElement {
+
+    private final Set<Modifier> modifiers;
+    private List<AnnotationMirror> annotations;
+    private List<E> enclosedElements;
+
+    private Element enclosingElement;
+
+    private Element generatorElement;
+    private AnnotationMirror generatorAnnotationMirror;
+
+    public CodeElement(Set<Modifier> modifiers) {
+        this.modifiers = new LinkedHashSet<>(modifiers);
+    }
+
+    @Override
+    public void setGeneratorAnnotationMirror(AnnotationMirror mirror) {
+        this.generatorAnnotationMirror = mirror;
+    }
+
+    @Override
+    public void setGeneratorElement(Element element) {
+        this.generatorElement = element;
+    }
+
+    @Override
+    public AnnotationMirror getGeneratorAnnotationMirror() {
+        return generatorAnnotationMirror;
+    }
+
+    @Override
+    public Element getGeneratorElement() {
+        return generatorElement;
+    }
+
+    public <T extends E> T add(T element) {
+        if (element == null) {
+            throw new NullPointerException();
+        }
+        getEnclosedElements().add(element);
+        return element;
+    }
+
+    public <T extends E> T addOptional(T element) {
+        if (element != null) {
+            add(element);
+        }
+        return element;
+    }
+
+    public void remove(E element) {
+        getEnclosedElements().remove(element);
+    }
+
+    @Override
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    @Override
+    public List<E> getEnclosedElements() {
+        if (enclosedElements == null) {
+            enclosedElements = parentableList(this, new ArrayList<E>());
+        }
+        return enclosedElements;
+    }
+
+    @Override
+    public List<AnnotationMirror> getAnnotationMirrors() {
+        if (annotations == null) {
+            annotations = parentableList(this, new ArrayList<AnnotationMirror>());
+        }
+        return annotations;
+    }
+
+    /**
+     * Support JDK8 langtools.
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotations(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Support for some JDK8 builds. (remove after jdk8 is released)
+     *
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void addAnnotationMirror(AnnotationMirror annotationMirror) {
+        getAnnotationMirrors().add(annotationMirror);
+    }
+
+    public void setEnclosingElement(Element parent) {
+        this.enclosingElement = parent;
+    }
+
+    public Element getEnclosingElement() {
+        return enclosingElement;
+    }
+
+    public CodeTypeElement getEnclosingClass() {
+        Element p = enclosingElement;
+        while (p != null && p.getKind() != ElementKind.CLASS && p.getKind() != ElementKind.ENUM) {
+            p = p.getEnclosingElement();
+        }
+        return (CodeTypeElement) p;
+    }
+
+    <T> List<T> parentableList(Element parent, List<T> list) {
+        return new ParentableList<>(parent, list);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilderCodeWriter codeWriter = new StringBuilderCodeWriter();
+        accept(codeWriter, null);
+        return codeWriter.getString();
+    }
+
+    private static class StringBuilderCodeWriter extends AbstractCodeWriter {
+
+        public StringBuilderCodeWriter() {
+            this.writer = new CharArrayWriter();
+        }
+
+        @Override
+        protected Writer createWriter(CodeTypeElement clazz) throws IOException {
+            return writer;
+        }
+
+        public String getString() {
+            return new String(((CharArrayWriter) writer).toCharArray()).trim();
+        }
+
+    }
+
+    private static class ParentableList<T> implements List<T> {
+
+        private final Element parent;
+        private final List<T> delegate;
+
+        public ParentableList(Element parent, List<T> delegate) {
+            this.parent = parent;
+            this.delegate = delegate;
+        }
+
+        private void addImpl(T element) {
+            if (element != null) {
+                if (element instanceof CodeElement<?>) {
+                    ((CodeElement<?>) element).setEnclosingElement(parent);
+                }
+            }
+        }
+
+        private static void removeImpl(Object element) {
+            if (element instanceof CodeElement<?>) {
+                ((CodeElement<?>) element).setEnclosingElement(null);
+            }
+        }
+
+        @Override
+        public int size() {
+            return delegate.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return delegate.isEmpty();
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return delegate.contains(o);
+        }
+
+        @Override
+        public Iterator<T> iterator() {
+            return delegate.iterator();
+        }
+
+        @Override
+        public Object[] toArray() {
+            return delegate.toArray();
+        }
+
+        @Override
+        public <E> E[] toArray(E[] a) {
+            return delegate.toArray(a);
+        }
+
+        @Override
+        public boolean add(T e) {
+            addImpl(e);
+            return delegate.add(e);
+        }
+
+        @Override
+        public boolean remove(Object o) {
+            boolean removed = delegate.remove(o);
+            if (removed) {
+                removeImpl(o);
+            }
+            return removed;
+        }
+
+        @Override
+        public boolean containsAll(Collection<?> c) {
+            return delegate.containsAll(c);
+        }
+
+        @Override
+        public boolean addAll(Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(c);
+        }
+
+        @Override
+        public boolean addAll(int index, Collection<? extends T> c) {
+            if (c != null) {
+                for (T t : c) {
+                    addImpl(t);
+                }
+            }
+            return delegate.addAll(index, c);
+        }
+
+        @Override
+        public boolean removeAll(Collection<?> c) {
+            if (c != null) {
+                for (Object t : c) {
+                    removeImpl(t);
+                }
+            }
+            return delegate.removeAll(c);
+        }
+
+        @Override
+        public String toString() {
+            return delegate.toString();
+        }
+
+        @Override
+        public boolean retainAll(Collection<?> c) {
+            throw new UnsupportedOperationException("Not supported by parentable list");
+        }
+
+        @Override
+        public void clear() {
+            for (Object e : this) {
+                removeImpl(e);
+            }
+            delegate.clear();
+        }
+
+        @Override
+        public T get(int index) {
+            return delegate.get(index);
+        }
+
+        @Override
+        public T set(int index, T element) {
+            removeImpl(delegate.get(index));
+            addImpl(element);
+            return delegate.set(index, element);
+        }
+
+        @Override
+        public void add(int index, T element) {
+            addImpl(element);
+            delegate.add(index, element);
+        }
+
+        @Override
+        public T remove(int index) {
+            T element = delegate.remove(index);
+            removeImpl(element);
+            return element;
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            return delegate.indexOf(o);
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            return delegate.lastIndexOf(o);
+        }
+
+        @Override
+        public ListIterator<T> listIterator() {
+            return delegate.listIterator();
+        }
+
+        @Override
+        public ListIterator<T> listIterator(int index) {
+            return delegate.listIterator(index);
+        }
+
+        @Override
+        public List<T> subList(int fromIndex, int toIndex) {
+            return new ParentableList<>(parent, delegate.subList(fromIndex, toIndex));
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeElementScanner.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+public abstract class CodeElementScanner<R, P> extends ElementScanner7<R, P> {
+
+    @Override
+    public final R visitExecutable(ExecutableElement e, P p) {
+        if (!(e instanceof CodeExecutableElement)) {
+            throw new ClassCastException(e.toString());
+        }
+        return visitExecutable(cast(e, CodeExecutableElement.class), p);
+    }
+
+    public R visitExecutable(CodeExecutableElement e, P p) {
+        R ret = super.visitExecutable(e, p);
+        if (e.getBodyTree() != null) {
+            visitTree(e.getBodyTree(), p, e);
+        }
+        return ret;
+    }
+
+    @Override
+    public R visitVariable(VariableElement e, P p) {
+        if (e instanceof CodeVariableElement) {
+            CodeTree init = ((CodeVariableElement) e).getInit();
+            if (init != null) {
+                visitTree(init, p, e);
+            }
+        }
+        return super.visitVariable(e, p);
+    }
+
+    @Override
+    public R visitPackage(PackageElement e, P p) {
+        return super.visitPackage(e, p);
+    }
+
+    @Override
+    public final R visitType(TypeElement e, P p) {
+        return visitType(cast(e, CodeTypeElement.class), p);
+    }
+
+    public R visitType(CodeTypeElement e, P p) {
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public R visitTypeParameter(TypeParameterElement e, P p) {
+        return super.visitTypeParameter(e, p);
+    }
+
+    private static <E> E cast(Element element, Class<E> clazz) {
+        return clazz.cast(element);
+    }
+
+    public void visitTree(CodeTree e, P p, Element parent) {
+        List<CodeTree> elements = e.getEnclosedElements();
+        if (elements != null) {
+            for (CodeTree tree : e.getEnclosedElements()) {
+                visitTree(tree, p, parent);
+            }
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public void visitImport(CodeImport e, P p) {
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeExecutableElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeExecutableElement extends CodeElement<Element> implements ExecutableElement {
+
+    private final List<TypeMirror> throwables = new ArrayList<>();
+    private final List<VariableElement> parameters = parentableList(this, new ArrayList<VariableElement>());
+
+    private TypeMirror returnType;
+    private Name name;
+
+    private CodeTree bodyTree;
+    private String body;
+    private AnnotationValue defaultValue;
+    private boolean varArgs;
+
+    public CodeExecutableElement(TypeMirror returnType, String name) {
+        super(ElementUtils.modifiers());
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeExecutableElement(Set<Modifier> modifiers, TypeMirror returnType, String name, CodeVariableElement... parameters) {
+        super(modifiers);
+        this.returnType = returnType;
+        this.name = CodeNames.of(name);
+        for (CodeVariableElement codeParameter : parameters) {
+            addParameter(codeParameter);
+        }
+    }
+
+    public void setVisibility(Modifier visibility) {
+        ElementUtils.setVisibility(getModifiers(), visibility);
+    }
+
+    public Modifier getVisibility() {
+        return ElementUtils.getVisibility(getModifiers());
+    }
+
+    /* Support JDK8 langtools. */
+    public boolean isDefault() {
+        return false;
+    }
+
+    @Override
+    public List<TypeMirror> getThrownTypes() {
+        return throwables;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return returnType;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getReturnType() == null) {
+            return ElementKind.CONSTRUCTOR;
+        } else {
+            return ElementKind.METHOD;
+        }
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public void setVarArgs(boolean varargs) {
+        this.varArgs = varargs;
+    }
+
+    @Override
+    public boolean isVarArgs() {
+        return varArgs;
+    }
+
+    public void setDefaultValue(AnnotationValue defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+
+    @Override
+    public AnnotationValue getDefaultValue() {
+        return defaultValue;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public CodeTreeBuilder getBuilder() {
+        CodeTree tree = this.bodyTree;
+        return createBuilder().tree(tree);
+    }
+
+    public CodeTreeBuilder createBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        builder.setEnclosingElement(this);
+        this.bodyTree = builder.getTree();
+        this.body = null;
+        return builder;
+    }
+
+    public CodeTreeBuilder appendBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        builder.setEnclosingElement(this);
+        if (bodyTree != null) {
+            builder.tree(bodyTree);
+        }
+        this.bodyTree = builder.getTree();
+        this.body = null;
+        return builder;
+    }
+
+    public void setBodyTree(CodeTree body) {
+        this.bodyTree = body;
+    }
+
+    public CodeTree getBodyTree() {
+        return bodyTree;
+    }
+
+    public TypeMirror getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public List<VariableElement> getParameters() {
+        return parameters;
+    }
+
+    public TypeMirror[] getParameterTypes() {
+        TypeMirror[] types = new TypeMirror[getParameters().size()];
+        for (int i = 0; i < types.length; i++) {
+            types[i] = parameters.get(i).asType();
+        }
+        return types;
+    }
+
+    public void setReturnType(TypeMirror type) {
+        returnType = type;
+    }
+
+    public void addParameter(VariableElement parameter) {
+        parameters.add(parameter);
+    }
+
+    public void addThrownType(TypeMirror thrownType) {
+        throwables.add(thrownType);
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitExecutable(this, p);
+    }
+
+    public static CodeExecutableElement clone(@SuppressWarnings("unused") ProcessingEnvironment env, ExecutableElement method) {
+        CodeExecutableElement copy = new CodeExecutableElement(method.getReturnType(), method.getSimpleName().toString());
+        for (TypeMirror thrownType : method.getThrownTypes()) {
+            copy.addThrownType(thrownType);
+        }
+        copy.setDefaultValue(method.getDefaultValue());
+
+        for (AnnotationMirror mirror : method.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (VariableElement var : method.getParameters()) {
+            copy.addParameter(CodeVariableElement.clone(var));
+        }
+        for (Element element : method.getEnclosedElements()) {
+            copy.add(element);
+        }
+        copy.getModifiers().addAll(method.getModifiers());
+        copy.setVarArgs(method.isVarArgs());
+        return copy;
+    }
+
+    public TypeMirror getReceiverType() {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeImport.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+public class CodeImport implements Comparable<CodeImport> {
+
+    private final String packageName;
+    private final String symbolName;
+    private final boolean staticImport;
+
+    public CodeImport(String packageName, String symbolName, boolean staticImport) {
+        this.packageName = packageName;
+        this.symbolName = symbolName;
+        this.staticImport = staticImport;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public String getSymbolName() {
+        return symbolName;
+    }
+
+    public boolean isStaticImport() {
+        return staticImport;
+    }
+
+    @Override
+    public int compareTo(CodeImport o) {
+        if (staticImport && !o.staticImport) {
+            return 1;
+        } else if (!staticImport && o.staticImport) {
+            return -1;
+        } else {
+            int result = getPackageName().compareTo(o.getPackageName());
+            if (result == 0) {
+                return getSymbolName().compareTo(o.getSymbolName());
+            }
+            return result;
+        }
+    }
+
+    public <P> void accept(CodeElementScanner<?, P> s, P p) {
+        s.visitImport(this, p);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageName, symbolName, staticImport);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof CodeImport) {
+            CodeImport otherImport = (CodeImport) obj;
+            return getPackageName().equals(otherImport.getPackageName()) && getSymbolName().equals(otherImport.getSymbolName()) //
+                            && staticImport == otherImport.staticImport;
+        }
+        return super.equals(obj);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeNames.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public abstract class CodeNames {
+
+    private static Map<String, Name> names = new HashMap<>();
+
+    public static Name of(String value) {
+        Name name = names.get(value);
+        if (name == null) {
+            name = new NameImpl(value);
+            names.put(value, name);
+        }
+        return name;
+    }
+
+    private static class NameImpl implements Name {
+
+        private final String name;
+
+        public NameImpl(String name) {
+            this.name = name;
+        }
+
+        @Override
+        public int length() {
+            return name.length();
+        }
+
+        @Override
+        public char charAt(int index) {
+            return name.charAt(index);
+        }
+
+        @Override
+        public CharSequence subSequence(int start, int end) {
+            return name.subSequence(start, end);
+        }
+
+        @Override
+        public boolean contentEquals(CharSequence cs) {
+            return name.contentEquals(cs);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Name) {
+                return ((Name) obj).contentEquals(name);
+            }
+            return super.equals(obj);
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTree.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+public class CodeTree {
+
+    private final CodeTreeKind kind;
+
+    private CodeTree parent;
+
+    private TypeMirror type;
+    private final String string;
+
+    private List<CodeTree> children;
+
+    CodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
+        this.parent = parent;
+        this.kind = kind;
+        this.type = type;
+        this.string = string;
+    }
+
+    public void setParent(CodeTree parent) {
+        this.parent = parent;
+    }
+
+    public CodeTree getParent() {
+        return parent;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public void add(CodeTree element) {
+        if (children == null) {
+            children = new ArrayList<>();
+        }
+        element.setParent(this);
+        children.add(element);
+    }
+
+    public final List<CodeTree> getEnclosedElements() {
+        return children;
+    }
+
+    public final CodeTreeKind getCodeKind() {
+        return kind;
+    }
+
+    public String getString() {
+        return string;
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+    public boolean isEmpty() {
+        return children == null || children.isEmpty();
+    }
+
+    public boolean containsKind(CodeTreeKind k) {
+        if (this.kind == k) {
+            return true;
+        }
+        if (children != null) {
+            for (CodeTree child : children) {
+                if (child.containsKind(k)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean isSingleLine() {
+        return !containsKind(CodeTreeKind.NEW_LINE);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import static com.oracle.truffle.dsl.processor.java.model.CodeTreeKind.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class CodeTreeBuilder {
+
+    private BuilderCodeTree currentElement;
+    private final BuilderCodeTree root;
+
+    private int treeCount;
+    private Element enclosingElement;
+
+    public CodeTreeBuilder(CodeTreeBuilder parent) {
+        this.root = new BuilderCodeTree(null, GROUP, null, null);
+        this.currentElement = root;
+        if (parent != null) {
+            this.enclosingElement = parent.enclosingElement;
+        }
+    }
+
+    public void setEnclosingElement(Element enclosingElement) {
+        this.enclosingElement = enclosingElement;
+    }
+
+    @Override
+    public String toString() {
+        return root.toString();
+    }
+
+    public int getTreeCount() {
+        return treeCount;
+    }
+
+    public boolean isEmpty() {
+        return treeCount == 0;
+    }
+
+    public CodeTreeBuilder statement(String statement) {
+        return startStatement().string(statement).end();
+    }
+
+    public CodeTreeBuilder statement(CodeTree statement) {
+        return startStatement().tree(statement).end();
+    }
+
+    public static CodeTreeBuilder createBuilder() {
+        return new CodeTreeBuilder(null);
+    }
+
+    public static CodeTree singleString(String s) {
+        return createBuilder().string(s).build();
+    }
+
+    public static CodeTree singleType(TypeMirror s) {
+        return createBuilder().type(s).build();
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind) {
+        return push(new BuilderCodeTree(currentElement, kind, null, null), kind == NEW_LINE);
+    }
+
+    private CodeTreeBuilder push(String string) {
+        return push(new BuilderCodeTree(currentElement, CodeTreeKind.STRING, null, string), false);
+    }
+
+    private CodeTreeBuilder push(TypeMirror type) {
+        return push(new BuilderCodeTree(currentElement, CodeTreeKind.TYPE, type, null), false);
+    }
+
+    private CodeTreeBuilder push(CodeTreeKind kind, TypeMirror type, String string) {
+        return push(new BuilderCodeTree(currentElement, kind, type, string), kind == NEW_LINE);
+    }
+
+    private CodeTreeBuilder push(BuilderCodeTree tree, boolean removeLast) {
+        if (currentElement != null) {
+            if (removeLast && !removeLastIfEnqueued(tree)) {
+                return this;
+            }
+            currentElement.add(tree);
+        }
+        switch (tree.getCodeKind()) {
+            case COMMA_GROUP:
+            case GROUP:
+            case INDENT:
+                currentElement = tree;
+                break;
+        }
+        treeCount++;
+        return this;
+    }
+
+    private boolean removeLastIfEnqueued(BuilderCodeTree tree) {
+        if (tree.getCodeKind() == REMOVE_LAST) {
+            return !clearLastRec(tree.removeLast, currentElement.getEnclosedElements());
+        }
+        List<CodeTree> childTree = tree.getEnclosedElements();
+        if (childTree != null && !childTree.isEmpty()) {
+            CodeTree last = childTree.get(0);
+            if (last instanceof BuilderCodeTree) {
+                if (!removeLastIfEnqueued((BuilderCodeTree) last)) {
+                    childTree.remove(0);
+                }
+            }
+        }
+        return true;
+    }
+
+    private void clearLast(CodeTreeKind kind) {
+        if (clearLastRec(kind, currentElement.getEnclosedElements())) {
+            treeCount--;
+        } else {
+            // delay clearing the last
+            BuilderCodeTree tree = new BuilderCodeTree(currentElement, REMOVE_LAST, null, null);
+            tree.removeLast = kind;
+            push(tree, false);
+        }
+    }
+
+    public CodeTreeBuilder startStatement() {
+        startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(";").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder startGroup() {
+        return push(CodeTreeKind.GROUP);
+    }
+
+    public CodeTreeBuilder startCommaGroup() {
+        return push(CodeTreeKind.COMMA_GROUP);
+    }
+
+    public CodeTreeBuilder startCall(String callSite) {
+        return startCall((CodeTree) null, callSite);
+    }
+
+    public CodeTreeBuilder startCall(String receiver, String callSite) {
+        if (receiver != null) {
+            return startCall(singleString(receiver), callSite);
+        } else {
+            return startCall(callSite);
+        }
+    }
+
+    public CodeTreeBuilder startCall(CodeTree receiver, String callSite) {
+        if (receiver == null) {
+            return startGroup().string(callSite).startParanthesesCommaGroup().endAfter();
+        } else {
+            return startGroup().tree(receiver).string(".").string(callSite).startParanthesesCommaGroup().endAfter();
+        }
+    }
+
+    public CodeTreeBuilder startStaticCall(TypeMirror type, String methodName) {
+        return startGroup().push(CodeTreeKind.STATIC_METHOD_REFERENCE, type, methodName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startStaticCall(ExecutableElement method) {
+        return startStaticCall(ElementUtils.findNearestEnclosingType(method).asType(), method.getSimpleName().toString());
+    }
+
+    public CodeTreeBuilder staticReference(TypeMirror type, String fieldName) {
+        return push(CodeTreeKind.STATIC_FIELD_REFERENCE, type, fieldName);
+    }
+
+    private CodeTreeBuilder endAndWhitespaceAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(" ");
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder endAfter() {
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                end();
+            }
+        });
+        return this;
+    }
+
+    private CodeTreeBuilder startParanthesesCommaGroup() {
+        startGroup();
+        string("(").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private CodeTreeBuilder startCurlyBracesCommaGroup() {
+        startGroup();
+        string("{").startCommaGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder startParantheses() {
+        startGroup();
+        string("(").startGroup();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string(")");
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    public CodeTreeBuilder doubleQuote(String s) {
+        return startGroup().string("\"" + s + "\"").end();
+    }
+
+    public CodeTreeBuilder string(String chunk1) {
+        return push(chunk1);
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2) {
+        return push(GROUP).string(chunk1).string(chunk2).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).end();
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4) {
+        return push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4).end();
+    }
+
+    public CodeTreeBuilder tree(CodeTree treeToAdd) {
+        if (treeToAdd instanceof BuilderCodeTree) {
+            return push((BuilderCodeTree) treeToAdd, true).end();
+        } else {
+            BuilderCodeTree tree = new BuilderCodeTree(currentElement, GROUP, null, null);
+            currentElement.add(treeToAdd);
+            return push(tree, true).end();
+        }
+    }
+
+    public CodeTreeBuilder trees(CodeTree... trees) {
+        for (CodeTree tree : trees) {
+            tree(tree);
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder string(String chunk1, String chunk2, String chunk3, String chunk4, String... chunks) {
+        push(GROUP).string(chunk1).string(chunk2).string(chunk3).string(chunk4);
+        for (int i = 0; i < chunks.length; i++) {
+            string(chunks[i]);
+        }
+        return end();
+    }
+
+    public CodeTreeBuilder newLine() {
+        return push(NEW_LINE);
+    }
+
+    public CodeTreeBuilder startWhile() {
+        return startGroup().string("while ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startDoBlock() {
+        return startGroup().string("do ").startBlock();
+    }
+
+    public CodeTreeBuilder startDoWhile() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startStatement().string(" while ").startParanthesesCommaGroup().endAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIf() {
+        return startGroup().string("if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startFor() {
+        return startGroup().string("for ").startParantheses().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public boolean startIf(boolean elseIf) {
+        if (elseIf) {
+            startElseIf();
+        } else {
+            startIf();
+        }
+        return true;
+    }
+
+    public CodeTreeBuilder startElseIf() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else if ").startParanthesesCommaGroup().endAndWhitespaceAfter().startGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startElseBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        return startGroup().string(" else ").startBlock().endAfter();
+    }
+
+    private boolean clearLastRec(CodeTreeKind kind, List<CodeTree> children) {
+        if (children == null) {
+            return false;
+        }
+        for (int i = children.size() - 1; i >= 0; i--) {
+            CodeTree child = children.get(i);
+            if (child.getCodeKind() == kind) {
+                children.remove(children.get(i));
+                return true;
+            } else {
+                if (clearLastRec(kind, child.getEnclosedElements())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public CodeTreeBuilder startCase() {
+        startGroup().string("case ");
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+                string(" :").newLine();
+            }
+
+            @Override
+            public void afterEnd() {
+            }
+        });
+        return this;
+    }
+
+    public CodeTreeBuilder caseDefault() {
+        return startGroup().string("default :").newLine().end();
+    }
+
+    public CodeTreeBuilder startSwitch() {
+        return startGroup().string("switch ").startParanthesesCommaGroup().endAndWhitespaceAfter();
+    }
+
+    public CodeTreeBuilder startReturn() {
+        ExecutableElement method = findMethod();
+        if (method != null && ElementUtils.isVoid(method.getReturnType())) {
+            startGroup();
+            registerCallBack(new EndCallback() {
+
+                @Override
+                public void beforeEnd() {
+                    string(";").newLine(); // complete statement to execute
+                }
+
+                @Override
+                public void afterEnd() {
+                    string("return").string(";").newLine(); // emit a return;
+                }
+            });
+            return this;
+        } else {
+            return startStatement().string("return ");
+        }
+    }
+
+    public CodeTreeBuilder startAssert() {
+        return startStatement().string("assert ");
+    }
+
+    public CodeTreeBuilder startNewArray(ArrayType arrayType, CodeTree size) {
+        startGroup().string("new ").type(arrayType.getComponentType()).string("[");
+        if (size != null) {
+            tree(size);
+        }
+        string("]");
+        if (size == null) {
+            string(" ");
+            startCurlyBracesCommaGroup().endAfter();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder startNew(TypeMirror uninializedNodeClass) {
+        return startGroup().string("new ").type(uninializedNodeClass).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startNew(String typeName) {
+        return startGroup().string("new ").string(typeName).startParanthesesCommaGroup().endAfter();
+    }
+
+    public CodeTreeBuilder startIndention() {
+        return push(CodeTreeKind.INDENT);
+    }
+
+    public CodeTreeBuilder end(int times) {
+        for (int i = 0; i < times; i++) {
+            end();
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder end() {
+        BuilderCodeTree tree = currentElement;
+        EndCallback callback = tree.getAtEndListener();
+        if (callback != null) {
+            callback.beforeEnd();
+            toParent();
+            callback.afterEnd();
+        } else {
+            toParent();
+        }
+        return this;
+    }
+
+    private void toParent() {
+        CodeTree parentElement = currentElement.getParent();
+        if (currentElement != root) {
+            this.currentElement = (BuilderCodeTree) parentElement;
+        } else {
+            this.currentElement = root;
+        }
+    }
+
+    public CodeTreeBuilder startBlock() {
+        startGroup();
+        string("{").newLine().startIndention();
+        registerCallBack(new EndCallback() {
+
+            @Override
+            public void beforeEnd() {
+            }
+
+            @Override
+            public void afterEnd() {
+                string("}").newLine();
+            }
+        });
+        endAfter();
+        return this;
+    }
+
+    private void registerCallBack(EndCallback callback) {
+        currentElement.registerAtEnd(callback);
+    }
+
+    public CodeTreeBuilder defaultDeclaration(TypeMirror type, String name) {
+        if (!ElementUtils.isVoid(type)) {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            string(" = ");
+            defaultValue(type);
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, CodeTree init) {
+        startStatement();
+        string(type);
+        string(" ");
+        string(name);
+        if (init != null) {
+            string(" = ");
+            tree(init);
+        }
+        end(); // statement
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(String type, String name, String init) {
+        return declaration(type, name, singleString(init));
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTree init) {
+        if (ElementUtils.isVoid(type)) {
+            startStatement();
+            tree(init);
+            end();
+        } else {
+            startStatement();
+            type(type);
+            string(" ");
+            string(name);
+            if (init != null) {
+                string(" = ");
+                tree(init);
+            }
+            end(); // statement
+        }
+        return this;
+    }
+
+    public CodeTreeBuilder declaration(TypeMirror type, String name, CodeTreeBuilder init) {
+        if (init == this) {
+            throw new IllegalArgumentException("Recursive builder usage.");
+        }
+        return declaration(type, name, init.getTree());
+    }
+
+    public CodeTreeBuilder create() {
+        return new CodeTreeBuilder(this);
+    }
+
+    public CodeTreeBuilder type(TypeMirror type) {
+        return push(type);
+    }
+
+    public CodeTreeBuilder typeLiteral(TypeMirror type) {
+        return startGroup().type(ElementUtils.eraseGenericTypes(type)).string(".class").end();
+    }
+
+    private void assertRoot() {
+        if (currentElement != root) {
+            throw new IllegalStateException("CodeTreeBuilder was not ended properly.");
+        }
+    }
+
+    public CodeTreeBuilder startCaseBlock() {
+        return startIndention();
+    }
+
+    public CodeTreeBuilder startThrow() {
+        return startStatement().string("throw ");
+    }
+
+    public CodeTree getTree() {
+        assertRoot();
+        return root;
+    }
+
+    public CodeTree build() {
+        return root;
+    }
+
+    public CodeTreeBuilder cast(TypeMirror type) {
+        string("(").type(type).string(") ");
+        return this;
+    }
+
+    public CodeTreeBuilder cast(TypeMirror type, CodeTree content) {
+        if (ElementUtils.isVoid(type)) {
+            tree(content);
+            return this;
+        } else if (type.getKind() == TypeKind.DECLARED && ElementUtils.getQualifiedName(type).equals("java.lang.Object")) {
+            tree(content);
+            return this;
+        } else {
+            return startGroup().string("(").type(type).string(")").string(" ").tree(content).end();
+        }
+    }
+
+    public CodeTreeBuilder startSuperCall() {
+        return string("super").startParanthesesCommaGroup();
+    }
+
+    public CodeTreeBuilder returnFalse() {
+        return startReturn().string("false").end();
+    }
+
+    public CodeTreeBuilder returnStatement() {
+        return statement("return");
+    }
+
+    public ExecutableElement findMethod() {
+        if (enclosingElement != null && (enclosingElement.getKind() == ElementKind.METHOD || enclosingElement.getKind() == ElementKind.CONSTRUCTOR)) {
+            return (ExecutableElement) enclosingElement;
+        }
+        return null;
+    }
+
+    public CodeTreeBuilder returnNull() {
+        return startReturn().string("null").end();
+    }
+
+    public CodeTreeBuilder returnTrue() {
+        return startReturn().string("true").end();
+    }
+
+    public CodeTreeBuilder instanceOf(CodeTree var, TypeMirror type) {
+        return tree(var).string(" instanceof ").type(type);
+    }
+
+    public CodeTreeBuilder defaultValue(TypeMirror mirror) {
+        switch (mirror.getKind()) {
+            case VOID:
+                return string("");
+            case ARRAY:
+            case DECLARED:
+            case PACKAGE:
+            case NULL:
+                return string("null");
+            case BOOLEAN:
+                return string("false");
+            case BYTE:
+                return string("(byte) 0");
+            case CHAR:
+                return string("(char) 0");
+            case DOUBLE:
+                return string("0.0D");
+            case LONG:
+                return string("0L");
+            case INT:
+                return string("0");
+            case FLOAT:
+                return string("0.0F");
+            case SHORT:
+                return string("(short) 0");
+            default:
+                throw new AssertionError();
+        }
+    }
+
+    public CodeTreeBuilder startTryBlock() {
+        return string("try ").startBlock();
+    }
+
+    public CodeTreeBuilder startCatchBlock(TypeMirror exceptionType, String localVarName) {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" catch (").type(exceptionType).string(" ").string(localVarName).string(") ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder startCatchBlock(TypeMirror[] exceptionTypes, String localVarName) {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" catch (");
+
+        for (int i = 0; i < exceptionTypes.length; i++) {
+            if (i != 0) {
+                string(" | ");
+            }
+            type(exceptionTypes[i]);
+        }
+
+        string(" ").string(localVarName).string(") ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder startFinallyBlock() {
+        clearLast(CodeTreeKind.NEW_LINE);
+        string(" finally ");
+        return startBlock();
+    }
+
+    public CodeTreeBuilder nullLiteral() {
+        return string("null");
+    }
+
+    private static class BuilderCodeTree extends CodeTree {
+
+        private EndCallback atEndListener;
+        private CodeTreeKind removeLast;
+
+        public BuilderCodeTree(CodeTree parent, CodeTreeKind kind, TypeMirror type, String string) {
+            super(parent, kind, type, string);
+        }
+
+        public void registerAtEnd(EndCallback atEnd) {
+            if (this.atEndListener != null) {
+                this.atEndListener = new CompoundCallback(this.atEndListener, atEnd);
+            } else {
+                this.atEndListener = atEnd;
+            }
+        }
+
+        public EndCallback getAtEndListener() {
+            return atEndListener;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder b = new StringBuilder();
+            new Printer(b).visitTree(this, null, null);
+            return b.toString();
+        }
+
+        private static class CompoundCallback implements EndCallback {
+
+            private final EndCallback callback1;
+            private final EndCallback callback2;
+
+            public CompoundCallback(EndCallback callback1, EndCallback callback2) {
+                this.callback1 = callback1;
+                this.callback2 = callback2;
+            }
+
+            @Override
+            public void afterEnd() {
+                callback1.afterEnd();
+                callback2.afterEnd();
+            }
+
+            @Override
+            public void beforeEnd() {
+                callback1.beforeEnd();
+                callback1.beforeEnd();
+            }
+        }
+
+    }
+
+    private interface EndCallback {
+
+        void beforeEnd();
+
+        void afterEnd();
+    }
+
+    private static class Printer extends CodeElementScanner<Void, Void> {
+
+        private int indent;
+        private boolean newLine;
+        private final String ln = "\n";
+
+        private final StringBuilder b;
+
+        Printer(StringBuilder b) {
+            this.b = b;
+        }
+
+        @Override
+        public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+            switch (e.getCodeKind()) {
+                case COMMA_GROUP:
+                    List<CodeTree> children = e.getEnclosedElements();
+                    if (children != null) {
+                        for (int i = 0; i < children.size(); i++) {
+                            visitTree(children.get(i), p, enclosingElement);
+                            if (i < e.getEnclosedElements().size() - 1) {
+                                b.append(", ");
+                            }
+                        }
+                    }
+                    break;
+                case GROUP:
+                    super.visitTree(e, p, enclosingElement);
+                    break;
+                case INDENT:
+                    indent();
+                    super.visitTree(e, p, enclosingElement);
+                    dedent();
+                    break;
+                case NEW_LINE:
+                    writeLn();
+                    break;
+                case STRING:
+                    if (e.getString() != null) {
+                        write(e.getString());
+                    } else {
+                        write("null");
+                    }
+                    break;
+                case TYPE:
+                    write(ElementUtils.getSimpleName(e.getType()));
+                    break;
+                default:
+                    assert false;
+                    return;
+            }
+        }
+
+        private void indent() {
+            indent++;
+        }
+
+        private void dedent() {
+            indent--;
+        }
+
+        private void writeLn() {
+            write(ln);
+            newLine = true;
+        }
+
+        private void write(String m) {
+            if (newLine && m != ln) {
+                writeIndent();
+                newLine = false;
+            }
+            b.append(m);
+        }
+
+        private void writeIndent() {
+            for (int i = 0; i < indent; i++) {
+                b.append("    ");
+            }
+        }
+    }
+
+    public CodeTreeBuilder returnDefault() {
+        ExecutableElement method = findMethod();
+        if (ElementUtils.isVoid(method.getReturnType())) {
+            returnStatement();
+        } else {
+            startReturn().defaultValue(method.getReturnType()).end();
+        }
+        return this;
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeKind.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+public enum CodeTreeKind {
+    STATIC_FIELD_REFERENCE,
+    STATIC_METHOD_REFERENCE,
+    GROUP,
+    COMMA_GROUP,
+    REMOVE_LAST,
+    INDENT,
+    STRING,
+    NEW_LINE,
+    TYPE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public class CodeTypeElement extends CodeElement<Element> implements TypeElement {
+
+    private final List<? extends CodeImport> imports = parentableList(this, new ArrayList<CodeImport>());
+
+    private final PackageElement packageElement;
+
+    private final Name simpleName;
+    private final Name packageName;
+    private Name qualifiedName;
+
+    private final List<TypeMirror> implementsInterfaces = new ArrayList<>();
+    private final ElementKind kind;
+    private TypeMirror superClass;
+
+    private final DeclaredCodeTypeMirror mirror = new DeclaredCodeTypeMirror(this);
+
+    public CodeTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers);
+        this.kind = kind;
+        this.packageElement = packageElement;
+        this.simpleName = CodeNames.of(simpleName);
+        if (this.packageElement != null) {
+            this.packageName = packageElement.getQualifiedName();
+        } else {
+            this.packageName = CodeNames.of("default");
+        }
+        this.qualifiedName = createQualifiedName();
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return mirror;
+    }
+
+    @Override
+    public ElementKind getKind() {
+        return kind;
+    }
+
+    public boolean containsField(String name) {
+        for (VariableElement field : getFields()) {
+            if (field.getSimpleName().toString().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public NestingKind getNestingKind() {
+        return isTopLevelClass() ? NestingKind.TOP_LEVEL : NestingKind.LOCAL;
+    }
+
+    @Override
+    public Element getEnclosingElement() {
+        if (isTopLevelClass()) {
+            return packageElement;
+        } else {
+            return super.getEnclosingElement();
+        }
+    }
+
+    @Override
+    public TypeMirror getSuperclass() {
+        return superClass;
+    }
+
+    @Override
+    public List<TypeMirror> getInterfaces() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public List<? extends TypeParameterElement> getTypeParameters() {
+        return Collections.emptyList();
+    }
+
+    public boolean isTopLevelClass() {
+        return super.getEnclosingElement() instanceof CodeCompilationUnit || super.getEnclosingElement() == null;
+    }
+
+    private Name createQualifiedName() {
+        TypeElement enclosingType = getEnclosingClass();
+        if (enclosingType == null) {
+            return CodeNames.of(packageName + "." + simpleName);
+        } else {
+            return CodeNames.of(enclosingType.getQualifiedName() + "." + simpleName);
+        }
+    }
+
+    @Override
+    public void setEnclosingElement(Element element) {
+        super.setEnclosingElement(element);
+
+        // update qualified name on container change
+        this.qualifiedName = createQualifiedName();
+    }
+
+    public Name getPackageName() {
+        return packageName;
+    }
+
+    @Override
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    @Override
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public void setSuperClass(TypeMirror superType) {
+        this.superClass = superType;
+    }
+
+    public List<? extends CodeImport> getImports() {
+        return imports;
+    }
+
+    public List<TypeMirror> getImplements() {
+        return implementsInterfaces;
+    }
+
+    @Override
+    public int hashCode() {
+        return getQualifiedName().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj instanceof TypeElement) {
+            return getQualifiedName().equals(((TypeElement) obj).getQualifiedName());
+        }
+        return false;
+    }
+
+    public List<VariableElement> getFields() {
+        return ElementFilter.fieldsIn(getEnclosedElements());
+    }
+
+    public List<ExecutableElement> getMethods() {
+        return ElementFilter.methodsIn(getEnclosedElements());
+    }
+
+    public List<TypeElement> getInnerClasses() {
+        return ElementFilter.typesIn(getEnclosedElements());
+    }
+
+    @Override
+    public String toString() {
+        return getQualifiedName().toString();
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitType(this, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class CodeTypeMirror implements TypeMirror {
+
+    private final TypeKind kind;
+
+    public CodeTypeMirror(TypeKind kind) {
+        this.kind = kind;
+    }
+
+    @Override
+    public TypeKind getKind() {
+        return kind;
+    }
+
+    @Override
+    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+        throw new UnsupportedOperationException();
+    }
+
+    public static class WildcardTypeMirror extends CodeTypeMirror implements WildcardType {
+
+        private final TypeMirror extendsBounds;
+        private final TypeMirror superBounds;
+
+        public WildcardTypeMirror(TypeMirror extendsBounds, TypeMirror superBounds) {
+            super(TypeKind.WILDCARD);
+            this.extendsBounds = extendsBounds;
+            this.superBounds = superBounds;
+        }
+
+        public TypeMirror getExtendsBound() {
+            return extendsBounds;
+        }
+
+        public TypeMirror getSuperBound() {
+            return superBounds;
+        }
+
+    }
+
+    public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
+
+        private final TypeMirror component;
+
+        public ArrayCodeTypeMirror(TypeMirror component) {
+            super(TypeKind.ARRAY);
+            this.component = component;
+        }
+
+        @Override
+        public TypeMirror getComponentType() {
+            return component;
+        }
+
+    }
+
+    public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
+
+        private final TypeElement clazz;
+        private final List<TypeMirror> typeArguments;
+
+        public DeclaredCodeTypeMirror(TypeElement clazz) {
+            this(clazz, Collections.<TypeMirror> emptyList());
+        }
+
+        public DeclaredCodeTypeMirror(TypeElement clazz, List<TypeMirror> typeArguments) {
+            super(TypeKind.DECLARED);
+            this.clazz = clazz;
+            this.typeArguments = typeArguments;
+        }
+
+        @Override
+        public Element asElement() {
+            return clazz;
+        }
+
+        @Override
+        public TypeMirror getEnclosingType() {
+            return clazz.getEnclosingElement().asType();
+        }
+
+        @Override
+        public List<TypeMirror> getTypeArguments() {
+            return typeArguments;
+        }
+
+        @Override
+        public String toString() {
+            return clazz.getQualifiedName().toString();
+        }
+
+    }
+
+    public List<? extends AnnotationMirror> getAnnotationMirrors() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param annotationType
+     */
+    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
+        throw new UnsupportedOperationException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeVariableElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class CodeVariableElement extends CodeElement<Element> implements VariableElement {
+
+    private Name name;
+    private TypeMirror type;
+    private Object constantValue;
+
+    private CodeTree init;
+
+    public CodeVariableElement(TypeMirror type, String name) {
+        super(ElementUtils.modifiers());
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name) {
+        super(modifiers);
+        this.type = type;
+        this.name = CodeNames.of(name);
+    }
+
+    public CodeVariableElement(Set<Modifier> modifiers, TypeMirror type, String name, String init) {
+        this(modifiers, type, name);
+        if (init != null) {
+            this.init = new CodeTree(null, CodeTreeKind.STRING, null, init);
+        }
+    }
+
+    public CodeTreeBuilder createInitBuilder() {
+        CodeTreeBuilder builder = new CodeTreeBuilder(null);
+        builder.setEnclosingElement(this);
+        init = builder.getTree();
+        return builder;
+    }
+
+    public void setInit(CodeTree init) {
+        this.init = init;
+    }
+
+    public CodeTree getInit() {
+        return init;
+    }
+
+    public Name getSimpleName() {
+        return name;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    @Override
+    public TypeMirror asType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + "/* " + ElementUtils.getSimpleName(type) + "*/";
+    }
+
+    @Override
+    public ElementKind getKind() {
+        if (getEnclosingElement() instanceof ExecutableElement) {
+            return ElementKind.PARAMETER;
+        } else if (getEnclosingElement() instanceof TypeElement) {
+            return ElementKind.FIELD;
+        } else {
+            return ElementKind.PARAMETER;
+        }
+    }
+
+    public void setConstantValue(Object constantValue) {
+        this.constantValue = constantValue;
+    }
+
+    @Override
+    public Object getConstantValue() {
+        return constantValue;
+    }
+
+    public String getName() {
+        return getSimpleName().toString();
+    }
+
+    public void setSimpleName(Name name) {
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = CodeNames.of(name);
+    }
+
+    public void setType(TypeMirror type) {
+        this.type = type;
+    }
+
+    @Override
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitVariable(this, p);
+    }
+
+    public static CodeVariableElement clone(VariableElement var) {
+        CodeVariableElement copy = new CodeVariableElement(var.getModifiers(), var.asType(), var.getSimpleName().toString());
+        copy.setConstantValue(var.getConstantValue());
+        for (AnnotationMirror mirror : var.getAnnotationMirrors()) {
+            copy.addAnnotationMirror(mirror);
+        }
+        for (Element element : var.getEnclosedElements()) {
+            copy.add(element);
+        }
+        return copy;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import javax.lang.model.element.*;
+
+public interface GeneratedElement {
+
+    AnnotationMirror getGeneratorAnnotationMirror();
+
+    void setGeneratorAnnotationMirror(AnnotationMirror mirror);
+
+    Element getGeneratorElement();
+
+    void setGeneratorElement(Element element);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedPackageElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public final class GeneratedPackageElement extends CodeElement<Element> implements PackageElement {
+
+    private final Name qualifiedName;
+    private final Name simpleName;
+
+    public GeneratedPackageElement(String qualifiedName) {
+        super(Collections.<Modifier> emptySet());
+        this.qualifiedName = CodeNames.of(qualifiedName);
+        int lastIndex = qualifiedName.lastIndexOf('.');
+        if (lastIndex == -1) {
+            simpleName = CodeNames.of("");
+        } else {
+            simpleName = CodeNames.of(qualifiedName.substring(lastIndex, qualifiedName.length()));
+        }
+    }
+
+    public TypeMirror asType() {
+        throw new UnsupportedOperationException();
+    }
+
+    public ElementKind getKind() {
+        return ElementKind.PACKAGE;
+    }
+
+    public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+        return v.visitPackage(this, p);
+    }
+
+    public Name getQualifiedName() {
+        return qualifiedName;
+    }
+
+    public Name getSimpleName() {
+        return simpleName;
+    }
+
+    public boolean isUnnamed() {
+        return simpleName.toString().equals("");
+    }
+
+    @Override
+    public int hashCode() {
+        return qualifiedName.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof PackageElement) {
+            return qualifiedName.equals(((PackageElement) obj).getQualifiedName());
+        }
+        return super.equals(obj);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeElement.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+public final class GeneratedTypeElement extends CodeTypeElement {
+
+    public GeneratedTypeElement(Set<Modifier> modifiers, ElementKind kind, PackageElement packageElement, String simpleName) {
+        super(modifiers, kind, packageElement, simpleName);
+        setEnclosingElement(packageElement);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/GeneratedTypeMirror.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+
+public final class GeneratedTypeMirror extends DeclaredCodeTypeMirror {
+
+    public GeneratedTypeMirror(String packageName, String name) {
+        super(new GeneratedTypeElement(Collections.<Modifier> emptySet(), ElementKind.CLASS, new GeneratedPackageElement(packageName), name));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/AbstractCodeWriter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,765 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public abstract class AbstractCodeWriter extends CodeElementScanner<Void, Void> {
+
+    private static final int MAX_LINE_LENGTH = Integer.MAX_VALUE; // line wrapping disabled
+    private static final int LINE_WRAP_INDENTS = 3;
+    private static final String IDENT_STRING = "    ";
+    private static final String LN = "\n"; /* unix style */
+
+    protected Writer writer;
+    private int indent;
+    private boolean newLine;
+    private int lineLength;
+    private boolean lineWrapping = false;
+
+    private OrganizedImports imports;
+
+    protected abstract Writer createWriter(CodeTypeElement clazz) throws IOException;
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        if (e.isTopLevelClass()) {
+            Writer w = null;
+            try {
+                imports = OrganizedImports.organize(e);
+                w = new TrimTrailingSpaceWriter(createWriter(e));
+                writer = w;
+                writeRootClass(e);
+            } catch (IOException ex) {
+                throw new RuntimeException(ex);
+            } finally {
+                if (w != null) {
+                    try {
+                        w.close();
+                    } catch (Throwable e1) {
+                        // see eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361378
+                        // TODO temporary suppress errors on close.
+                    }
+                }
+                writer = null;
+            }
+        } else {
+            writeClassImpl(e);
+        }
+        return null;
+    }
+
+    private void writeRootClass(CodeTypeElement e) {
+        writeHeader();
+        write("package ").write(e.getPackageName()).write(";").writeLn();
+        writeEmptyLn();
+
+        Set<CodeImport> generateImports = imports.generateImports();
+        List<CodeImport> typeImports = new ArrayList<>();
+        List<CodeImport> staticImports = new ArrayList<>();
+
+        for (CodeImport codeImport : generateImports) {
+            if (codeImport.isStaticImport()) {
+                staticImports.add(codeImport);
+            } else {
+                typeImports.add(codeImport);
+            }
+        }
+        Collections.sort(typeImports);
+        Collections.sort(staticImports);
+
+        for (CodeImport imp : staticImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!staticImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        for (CodeImport imp : typeImports) {
+            imp.accept(this, null);
+            writeLn();
+        }
+        if (!typeImports.isEmpty()) {
+            writeEmptyLn();
+        }
+
+        writeClassImpl(e);
+    }
+
+    private String useImport(Element enclosedType, TypeMirror type) {
+        if (imports != null) {
+            return imports.createTypeReference(enclosedType, type);
+        } else {
+            return ElementUtils.getSimpleName(type);
+        }
+    }
+
+    private void writeClassImpl(CodeTypeElement e) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers(), true);
+        if (e.getKind() == ElementKind.ENUM) {
+            write("enum ");
+        } else {
+            write("class ");
+        }
+        write(e.getSimpleName());
+        if (e.getSuperclass() != null && !getQualifiedName(e.getSuperclass()).equals("java.lang.Object")) {
+            write(" extends ").write(useImport(e, e.getSuperclass()));
+        }
+        if (e.getImplements().size() > 0) {
+            write(" implements ");
+            for (int i = 0; i < e.getImplements().size(); i++) {
+                write(useImport(e, e.getImplements().get(i)));
+                if (i < e.getImplements().size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        write(" {").writeLn();
+        writeEmptyLn();
+        indent(1);
+
+        List<VariableElement> staticFields = getStaticFields(e);
+        List<VariableElement> instanceFields = getInstanceFields(e);
+
+        for (int i = 0; i < staticFields.size(); i++) {
+            VariableElement field = staticFields.get(i);
+            field.accept(this, null);
+            if (e.getKind() == ElementKind.ENUM && i < staticFields.size() - 1) {
+                write(",");
+                writeLn();
+            } else {
+                write(";");
+                writeLn();
+            }
+        }
+
+        if (staticFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (VariableElement field : instanceFields) {
+            field.accept(this, null);
+            write(";");
+            writeLn();
+        }
+        if (instanceFields.size() > 0) {
+            writeEmptyLn();
+        }
+
+        for (ExecutableElement method : ElementFilter.constructorsIn(e.getEnclosedElements())) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getInstanceMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (ExecutableElement method : getStaticMethods(e)) {
+            method.accept(this, null);
+        }
+
+        for (TypeElement clazz : e.getInnerClasses()) {
+            clazz.accept(this, null);
+        }
+
+        dedent(1);
+        write("}");
+        writeEmptyLn();
+    }
+
+    private static List<VariableElement> getStaticFields(CodeTypeElement clazz) {
+        List<VariableElement> staticFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                staticFields.add(field);
+            }
+        }
+        return staticFields;
+    }
+
+    private static List<VariableElement> getInstanceFields(CodeTypeElement clazz) {
+        List<VariableElement> instanceFields = new ArrayList<>();
+        for (VariableElement field : clazz.getFields()) {
+            if (!field.getModifiers().contains(Modifier.STATIC)) {
+                instanceFields.add(field);
+            }
+        }
+        return instanceFields;
+    }
+
+    private static List<ExecutableElement> getStaticMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> staticMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (method.getModifiers().contains(Modifier.STATIC)) {
+                staticMethods.add(method);
+            }
+        }
+        return staticMethods;
+    }
+
+    private static List<ExecutableElement> getInstanceMethods(CodeTypeElement clazz) {
+        List<ExecutableElement> instanceMethods = new ArrayList<>();
+        for (ExecutableElement method : clazz.getMethods()) {
+            if (!method.getModifiers().contains(Modifier.STATIC)) {
+                instanceMethods.add(method);
+            }
+        }
+        return instanceMethods;
+    }
+
+    @Override
+    public Void visitVariable(VariableElement f, Void p) {
+        Element parent = f.getEnclosingElement();
+
+        for (AnnotationMirror annotation : f.getAnnotationMirrors()) {
+            visitAnnotation(f, annotation);
+            write(" ");
+        }
+
+        CodeTree init = null;
+        if (f instanceof CodeVariableElement) {
+            init = ((CodeVariableElement) f).getInit();
+        }
+
+        if (parent != null && parent.getKind() == ElementKind.ENUM && f.getModifiers().contains(Modifier.STATIC)) {
+            write(f.getSimpleName());
+            if (init != null) {
+                write("(");
+                visitTree(init, p, f);
+                write(")");
+            }
+        } else {
+            writeModifiers(f.getModifiers(), true);
+
+            boolean varArgs = false;
+            if (parent != null && parent.getKind() == ElementKind.METHOD) {
+                ExecutableElement method = (ExecutableElement) parent;
+                if (method.isVarArgs() && method.getParameters().indexOf(f) == method.getParameters().size() - 1) {
+                    varArgs = true;
+                }
+            }
+
+            TypeMirror varType = f.asType();
+            if (varArgs) {
+                if (varType.getKind() == TypeKind.ARRAY) {
+                    varType = ((ArrayType) varType).getComponentType();
+                }
+                write(useImport(f, varType));
+                write("...");
+            } else {
+                write(useImport(f, varType));
+            }
+
+            write(" ");
+            write(f.getSimpleName());
+            if (init != null) {
+                write(" = ");
+                visitTree(init, p, f);
+            }
+        }
+        return null;
+    }
+
+    private void visitAnnotation(Element enclosedElement, AnnotationMirror e) {
+        write("@").write(useImport(enclosedElement, e.getAnnotationType()));
+
+        if (!e.getElementValues().isEmpty()) {
+            write("(");
+            final ExecutableElement defaultElement = findExecutableElement(e.getAnnotationType(), "value");
+
+            Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+            if (defaultElement != null && values.size() == 1 && values.get(defaultElement) != null) {
+                visitAnnotationValue(enclosedElement, values.get(defaultElement));
+            } else {
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                Collections.sort(methodsList, new Comparator<ExecutableElement>() {
+
+                    @Override
+                    public int compare(ExecutableElement o1, ExecutableElement o2) {
+                        return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString());
+                    }
+                });
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    ExecutableElement method = methodsList.get(i);
+                    AnnotationValue value = values.get(method);
+                    write(method.getSimpleName().toString());
+                    write(" = ");
+                    visitAnnotationValue(enclosedElement, value);
+
+                    if (i < methodsList.size() - 1) {
+                        write(", ");
+                    }
+                }
+            }
+
+            write(")");
+        }
+    }
+
+    private void visitAnnotationValue(Element enclosedElement, AnnotationValue e) {
+        e.accept(new AnnotationValueWriterVisitor(enclosedElement), null);
+    }
+
+    private class AnnotationValueWriterVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+        private final Element enclosedElement;
+
+        public AnnotationValueWriterVisitor(Element enclosedElement) {
+            this.enclosedElement = enclosedElement;
+        }
+
+        @Override
+        public Void visitBoolean(boolean b, Void p) {
+            write(Boolean.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitByte(byte b, Void p) {
+            write(Byte.toString(b));
+            return null;
+        }
+
+        @Override
+        public Void visitChar(char c, Void p) {
+            write(Character.toString(c));
+            return null;
+        }
+
+        @Override
+        public Void visitDouble(double d, Void p) {
+            write(Double.toString(d));
+            return null;
+        }
+
+        @Override
+        public Void visitFloat(float f, Void p) {
+            write(Float.toString(f));
+            return null;
+        }
+
+        @Override
+        public Void visitInt(int i, Void p) {
+            write(Integer.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitLong(long i, Void p) {
+            write(Long.toString(i));
+            return null;
+        }
+
+        @Override
+        public Void visitShort(short s, Void p) {
+            write(Short.toString(s));
+            return null;
+        }
+
+        @Override
+        public Void visitString(String s, Void p) {
+            write("\"");
+            write(s);
+            write("\"");
+            return null;
+        }
+
+        @Override
+        public Void visitType(TypeMirror t, Void p) {
+            write(useImport(enclosedElement, t));
+            write(".class");
+            return null;
+        }
+
+        @Override
+        public Void visitEnumConstant(VariableElement c, Void p) {
+            write(useImport(enclosedElement, c.asType()));
+            write(".");
+            write(c.getSimpleName().toString());
+            return null;
+        }
+
+        @Override
+        public Void visitAnnotation(AnnotationMirror a, Void p) {
+            AbstractCodeWriter.this.visitAnnotation(enclosedElement, a);
+            return null;
+        }
+
+        @Override
+        public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+            write("{");
+            for (int i = 0; i < vals.size(); i++) {
+                AnnotationValue value = vals.get(i);
+                AbstractCodeWriter.this.visitAnnotationValue(enclosedElement, value);
+                if (i < vals.size() - 1) {
+                    write(", ");
+                }
+            }
+            write("}");
+            return null;
+        }
+    }
+
+    private static ExecutableElement findExecutableElement(DeclaredType type, String name) {
+        List<? extends ExecutableElement> elements = ElementFilter.methodsIn(type.asElement().getEnclosedElements());
+        for (ExecutableElement executableElement : elements) {
+            if (executableElement.getSimpleName().toString().equals(name)) {
+                return executableElement;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void visitImport(CodeImport e, Void p) {
+        write("import ");
+        if (e.isStaticImport()) {
+            write("static ");
+        }
+        write(e.getPackageName());
+        write(".");
+        write(e.getSymbolName());
+        write(";");
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        for (AnnotationMirror annotation : e.getAnnotationMirrors()) {
+            visitAnnotation(e, annotation);
+            writeLn();
+        }
+
+        writeModifiers(e.getModifiers(), !e.getEnclosingClass().getModifiers().contains(Modifier.FINAL));
+
+        if (e.getReturnType() != null) {
+            write(useImport(e, e.getReturnType()));
+            write(" ");
+        }
+        write(e.getSimpleName());
+        write("(");
+
+        for (int i = 0; i < e.getParameters().size(); i++) {
+            VariableElement param = e.getParameters().get(i);
+            param.accept(this, p);
+            if (i < e.getParameters().size() - 1) {
+                write(", ");
+            }
+        }
+        write(")");
+
+        List<TypeMirror> throwables = e.getThrownTypes();
+        if (throwables.size() > 0) {
+            write(" throws ");
+            for (int i = 0; i < throwables.size(); i++) {
+                write(useImport(e, throwables.get(i)));
+                if (i < throwables.size() - 1) {
+                    write(", ");
+                }
+            }
+        }
+
+        if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            writeLn(";");
+        } else if (e.getBodyTree() != null) {
+            writeLn(" {");
+            indent(1);
+            visitTree(e.getBodyTree(), p, e);
+            dedent(1);
+            writeLn("}");
+        } else if (e.getBody() != null) {
+            write(" {");
+            write(e.getBody());
+            writeLn("}");
+        } else {
+            writeLn(" {");
+            writeLn("}");
+        }
+        writeEmptyLn();
+        return null;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+        CodeTreeKind kind = e.getCodeKind();
+
+        switch (kind) {
+            case COMMA_GROUP:
+                List<CodeTree> children = e.getEnclosedElements();
+                if (children != null) {
+                    for (int i = 0; i < children.size(); i++) {
+                        visitTree(children.get(i), p, enclosingElement);
+                        if (i < e.getEnclosedElements().size() - 1) {
+                            write(", ");
+                        }
+                    }
+                }
+                break;
+            case GROUP:
+                super.visitTree(e, p, enclosingElement);
+                break;
+            case INDENT:
+                indent(1);
+                super.visitTree(e, p, enclosingElement);
+                dedent(1);
+                break;
+            case NEW_LINE:
+                writeLn();
+                break;
+            case STRING:
+                if (e.getString() != null) {
+                    write(e.getString());
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_FIELD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticFieldReference(enclosingElement, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case STATIC_METHOD_REFERENCE:
+                if (e.getString() != null) {
+                    write(imports.createStaticMethodReference(enclosingElement, e.getType(), e.getString()));
+                } else {
+                    write("null");
+                }
+                break;
+            case TYPE:
+                write(useImport(enclosingElement, e.getType()));
+                break;
+            default:
+                assert false;
+                return;
+        }
+    }
+
+    protected void writeHeader() {
+        // default implementation does nothing
+    }
+
+    private void writeModifiers(Set<Modifier> modifiers, boolean includeFinal) {
+        if (modifiers != null && !modifiers.isEmpty()) {
+            Modifier[] modArray = modifiers.toArray(new Modifier[modifiers.size()]);
+            Arrays.sort(modArray);
+            for (Modifier mod : modArray) {
+                if (mod == Modifier.FINAL && !includeFinal) {
+                    continue;
+                }
+                write(mod.toString());
+                write(" ");
+            }
+        }
+    }
+
+    private void indent(int count) {
+        indent += count;
+    }
+
+    private void dedent(int count) {
+        indent -= count;
+    }
+
+    private void writeLn() {
+        writeLn("");
+    }
+
+    protected void writeLn(String text) {
+        write(text);
+        write(LN);
+        lineLength = 0;
+        newLine = true;
+        if (lineWrapping) {
+            dedent(LINE_WRAP_INDENTS);
+            lineWrapping = false;
+        }
+        lineWrapping = false;
+    }
+
+    private void writeEmptyLn() {
+        writeLn();
+    }
+
+    private AbstractCodeWriter write(Name name) {
+        return write(name.toString());
+    }
+
+    private AbstractCodeWriter write(String m) {
+        if (m.isEmpty()) {
+            return this;
+        }
+        try {
+            String s = m;
+            lineLength += s.length();
+            if (newLine && s != LN) {
+                writeIndent();
+                newLine = false;
+            }
+            if (lineLength > MAX_LINE_LENGTH) {
+                s = wrapLine(s);
+            }
+            writer.write(s);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return this;
+    }
+
+    private String wrapLine(String m) throws IOException {
+        assert !m.isEmpty();
+
+        char firstCharacter = m.charAt(0);
+        char lastCharacter = m.charAt(m.length() - 1);
+        if (firstCharacter == '\"' && lastCharacter == '\"') {
+            // string line wrapping
+            String string = m.substring(1, m.length() - 1);
+            if (string.isEmpty()) {
+                return m;
+            }
+
+            // restore original line length
+            lineLength = lineLength - m.length();
+            int size = 0;
+            for (int i = 0; i < string.length(); i += size) {
+                if (i != 0) {
+                    write("+ ");
+                }
+
+                int nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                if (nextSize <= 0) {
+                    writeLn();
+                    nextSize = MAX_LINE_LENGTH - lineLength - 2;
+                }
+
+                int end = Math.min(i + nextSize, string.length());
+
+                // TODO(CH): fails in normal usage - output ok though
+                // assert lineLength + (end - i) + 2 < MAX_LINE_LENGTH;
+                write("\"");
+                write(string.substring(i, end));
+                write("\"");
+                size = nextSize;
+            }
+
+            return "";
+        } else if (!Character.isAlphabetic(firstCharacter) && firstCharacter != '+') {
+            return m;
+        }
+
+        if (!lineWrapping) {
+            indent(LINE_WRAP_INDENTS);
+        }
+        lineWrapping = true;
+        lineLength = 0;
+        write(LN);
+        writeIndent();
+        return m;
+    }
+
+    private void writeIndent() throws IOException {
+        lineLength += indentSize();
+        for (int i = 0; i < indent; i++) {
+            writer.write(IDENT_STRING);
+        }
+    }
+
+    private int indentSize() {
+        return IDENT_STRING.length() * indent;
+    }
+
+    private static class TrimTrailingSpaceWriter extends Writer {
+
+        private final Writer delegate;
+        private final StringBuilder buffer = new StringBuilder();
+
+        public TrimTrailingSpaceWriter(Writer delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public void close() throws IOException {
+            this.delegate.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            this.delegate.flush();
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            buffer.append(cbuf, off, len);
+            int newLinePoint = buffer.indexOf(LN);
+
+            if (newLinePoint != -1) {
+                String lhs = trimTrailing(buffer.substring(0, newLinePoint));
+                delegate.write(lhs);
+                delegate.write(LN);
+                buffer.delete(0, newLinePoint + 1);
+            }
+        }
+
+        private static String trimTrailing(String s) {
+            int cut = 0;
+            for (int i = s.length() - 1; i >= 0; i--) {
+                if (Character.isWhitespace(s.charAt(i))) {
+                    cut++;
+                } else {
+                    break;
+                }
+            }
+            if (cut > 0) {
+                return s.substring(0, s.length() - cut);
+            }
+            return s;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/FixWarningsVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static javax.lang.model.element.Modifier.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class FixWarningsVisitor extends CodeElementScanner<Void, Void> {
+
+    private final Set<String> symbolsUsed = new HashSet<>();
+
+    private final ProcessingEnvironment processingEnv;
+    private final DeclaredType unusedAnnotation;
+    private final DeclaredType overrideType;
+
+    public FixWarningsVisitor(ProcessingEnvironment processingEnv, DeclaredType unusedAnnotation, DeclaredType overrideType) {
+        this.processingEnv = processingEnv;
+        this.unusedAnnotation = unusedAnnotation;
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitType(CodeTypeElement e, Void p) {
+        List<TypeElement> superTypes = ElementUtils.getSuperTypes(e);
+        for (TypeElement type : superTypes) {
+            String qualifiedName = ElementUtils.getQualifiedName(type);
+            if (qualifiedName.equals(Serializable.class.getCanonicalName())) {
+                if (!e.containsField("serialVersionUID")) {
+                    e.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), ElementUtils.getType(processingEnv, long.class), "serialVersionUID", "1L"));
+                }
+                break;
+            }
+        }
+
+        return super.visitType(e, p);
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (e.getParameters().isEmpty()) {
+            return null;
+        } else if (e.getModifiers().contains(Modifier.ABSTRACT)) {
+            return null;
+        } else if (containsOverride(e)) {
+            return null;
+        }
+
+        symbolsUsed.clear();
+        super.visitExecutable(e, p);
+
+        for (VariableElement parameter : e.getParameters()) {
+            if (!symbolsUsed.contains(parameter.getSimpleName().toString())) {
+                e.getAnnotationMirrors().add(createUnusedAnnotationMirror());
+                break;
+            }
+        }
+        return null;
+    }
+
+    private boolean containsOverride(CodeExecutableElement e) {
+        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+            if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private CodeAnnotationMirror createUnusedAnnotationMirror() {
+        CodeAnnotationMirror mirror = new CodeAnnotationMirror(unusedAnnotation);
+        mirror.setElementValue(mirror.findExecutableElement("value"), new CodeAnnotationValue("unused"));
+        return mirror;
+    }
+
+    @Override
+    public void visitTree(CodeTree e, Void p, Element enclosingElement) {
+        if (e.getString() != null) {
+            computeSymbols(e.getString());
+        }
+        super.visitTree(e, p, enclosingElement);
+    }
+
+    private void computeSymbols(String s) {
+        // TODO there should not be any need for a StringTokenizer if we have a real AST for
+        // method bodies. Also the current solution is not perfect. What if one token
+        // is spread across multiple CodeTree instances? But for now that works.
+        StringTokenizer tokenizer = new StringTokenizer(s, ".= :,()[];{}\"\"'' ", false);
+        while (tokenizer.hasMoreElements()) {
+            String token = tokenizer.nextToken().trim();
+            if (token.length() > 0) {
+                symbolsUsed.add(token);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/GenerateOverrideVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public class GenerateOverrideVisitor extends CodeElementScanner<Void, Void> {
+
+    private final DeclaredType overrideType;
+
+    public GenerateOverrideVisitor(DeclaredType overrideType) {
+        this.overrideType = overrideType;
+    }
+
+    @Override
+    public Void visitExecutable(CodeExecutableElement e, Void p) {
+        if (!e.getModifiers().contains(Modifier.STATIC) && !e.getModifiers().contains(Modifier.PRIVATE)) {
+            String name = e.getSimpleName().toString();
+            TypeMirror[] params = e.getParameterTypes();
+
+            for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
+                if (ElementUtils.typeEquals(overrideType, mirror.getAnnotationType())) {
+                    // already declared (may happen if method copied from super class)
+                    return super.visitExecutable(e, p);
+                }
+            }
+
+            if (isDeclaredMethodInSuperType(e.getEnclosingClass(), name, params)) {
+                e.addAnnotationMirror(new CodeAnnotationMirror(overrideType));
+            }
+        }
+        return super.visitExecutable(e, p);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.java.transform;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+
+public final class OrganizedImports {
+
+    private final Map<String, String> classImportUsage = new HashMap<>();
+    private final Map<String, Set<String>> autoImportCache = new HashMap<>();
+
+    private final CodeTypeElement topLevelClass;
+
+    private OrganizedImports(CodeTypeElement topLevelClass) {
+        this.topLevelClass = topLevelClass;
+    }
+
+    public static OrganizedImports organize(CodeTypeElement topLevelClass) {
+        OrganizedImports organized = new OrganizedImports(topLevelClass);
+        organized.organizeImpl();
+        return organized;
+    }
+
+    private void organizeImpl() {
+        ImportTypeReferenceVisitor reference = new ImportTypeReferenceVisitor();
+        topLevelClass.accept(reference, null);
+    }
+
+    public String createTypeReference(Element enclosedElement, TypeMirror type) {
+        switch (type.getKind()) {
+            case BOOLEAN:
+            case BYTE:
+            case CHAR:
+            case DOUBLE:
+            case FLOAT:
+            case SHORT:
+            case INT:
+            case LONG:
+            case VOID:
+                return ElementUtils.getSimpleName(type);
+            case DECLARED:
+                return createDeclaredTypeName(enclosedElement, (DeclaredType) type);
+            case ARRAY:
+                return createTypeReference(enclosedElement, ((ArrayType) type).getComponentType()) + "[]";
+            case WILDCARD:
+                return createWildcardName(enclosedElement, (WildcardType) type);
+            case TYPEVAR:
+                return "?";
+            default:
+                throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+        }
+    }
+
+    public String createStaticFieldReference(Element enclosedElement, TypeMirror type, String fieldName) {
+        return createStaticReference(enclosedElement, type, fieldName);
+    }
+
+    public String createStaticMethodReference(Element enclosedElement, TypeMirror type, String methodName) {
+        return createStaticReference(enclosedElement, type, methodName);
+    }
+
+    private String createStaticReference(Element enclosedElement, TypeMirror type, String name) {
+        // ambiguous import
+        return createTypeReference(enclosedElement, type) + "." + name;
+    }
+
+    private String createWildcardName(Element enclosedElement, WildcardType type) {
+        StringBuilder b = new StringBuilder();
+        if (type.getExtendsBound() != null) {
+            b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else if (type.getSuperBound() != null) {
+            b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else {
+            b.append("?");
+        }
+        return b.toString();
+    }
+
+    private String createDeclaredTypeName(Element enclosedElement, DeclaredType type) {
+        String name = ElementUtils.fixECJBinaryNameIssue(type.asElement().getSimpleName().toString());
+        if (classImportUsage.containsKey(name)) {
+            String qualifiedImport = classImportUsage.get(name);
+            String qualifiedName = ElementUtils.getEnclosedQualifiedName(type);
+
+            if (!qualifiedName.equals(qualifiedImport)) {
+                name = qualifiedName;
+            }
+        }
+
+        List<? extends TypeMirror> genericTypes = type.getTypeArguments();
+        if (genericTypes.size() == 0) {
+            return name;
+        }
+
+        StringBuilder b = new StringBuilder(name);
+        b.append("<");
+        for (int i = 0; i < genericTypes.size(); i++) {
+            TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null;
+            if (genericType != null) {
+                b.append(createTypeReference(enclosedElement, genericType));
+            } else {
+                b.append("?");
+            }
+
+            if (i < genericTypes.size() - 1) {
+                b.append(", ");
+            }
+        }
+        b.append(">");
+        return b.toString();
+    }
+
+    public Set<CodeImport> generateImports() {
+        Set<CodeImport> imports = new HashSet<>();
+
+        imports.addAll(generateImports(classImportUsage));
+
+        return imports;
+    }
+
+    private boolean needsImport(Element enclosed, TypeMirror importType) {
+        String importPackagName = getPackageName(importType);
+        TypeElement enclosedElement = findNearestEnclosingType(enclosed);
+        if (importPackagName == null) {
+            return false;
+        } else if (importPackagName.equals("java.lang")) {
+            return false;
+        } else if (importPackagName.equals(getPackageName(topLevelClass)) && ElementUtils.isTopLevelClass(importType)) {
+            return false; // same package name -> no import
+        }
+
+        String enclosedElementId = ElementUtils.getUniqueIdentifier(enclosedElement.asType());
+        Set<String> autoImportedTypes = autoImportCache.get(enclosedElementId);
+        if (autoImportedTypes == null) {
+            List<Element> elements = ElementUtils.getElementHierarchy(enclosedElement);
+            autoImportedTypes = new HashSet<>();
+            for (Element element : elements) {
+                if (element.getKind().isClass()) {
+                    collectSuperTypeImports((TypeElement) element, autoImportedTypes);
+                    collectInnerTypeImports((TypeElement) element, autoImportedTypes);
+                }
+            }
+            autoImportCache.put(enclosedElementId, autoImportedTypes);
+        }
+
+        String qualifiedName = getQualifiedName(importType);
+        if (autoImportedTypes.contains(qualifiedName)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static Set<CodeImport> generateImports(Map<String, String> symbols) {
+        TreeSet<CodeImport> importObjects = new TreeSet<>();
+        for (String symbol : symbols.keySet()) {
+            String packageName = symbols.get(symbol);
+            if (packageName != null) {
+                importObjects.add(new CodeImport(packageName, symbol, false));
+            }
+        }
+        return importObjects;
+    }
+
+    private static void collectInnerTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        autoImportedTypes.add(getQualifiedName(e));
+        for (TypeElement innerClass : ElementFilter.typesIn(e.getEnclosedElements())) {
+            collectInnerTypeImports(innerClass, autoImportedTypes);
+        }
+    }
+
+    private static void collectSuperTypeImports(TypeElement e, Set<String> autoImportedTypes) {
+        List<TypeElement> superTypes = getSuperTypes(e);
+        for (TypeElement superType : superTypes) {
+            List<TypeElement> declaredTypes = getDeclaredTypes(superType);
+            for (TypeElement declaredType : declaredTypes) {
+                if (!superTypes.contains(declaredType)) {
+                    autoImportedTypes.add(getQualifiedName(declaredType));
+                }
+            }
+        }
+    }
+
+    private abstract static class TypeReferenceVisitor extends CodeElementScanner<Void, Void> {
+
+        @Override
+        public void visitTree(CodeTree e, Void p, Element enclosing) {
+            if (e.getCodeKind() == CodeTreeKind.STATIC_FIELD_REFERENCE) {
+                visitStaticFieldReference(enclosing, e.getType(), e.getString());
+            } else if (e.getCodeKind() == CodeTreeKind.STATIC_METHOD_REFERENCE) {
+                visitStaticMethodReference(enclosing, e.getType(), e.getString());
+            } else if (e.getType() != null) {
+                visitTypeReference(enclosing, e.getType());
+            }
+            super.visitTree(e, p, enclosing);
+        }
+
+        @Override
+        public Void visitExecutable(CodeExecutableElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+            if (e.getReturnType() != null) {
+                visitTypeReference(e, e.getReturnType());
+            }
+            for (TypeMirror type : e.getThrownTypes()) {
+                visitTypeReference(e, type);
+            }
+            return super.visitExecutable(e, p);
+        }
+
+        @Override
+        public Void visitType(CodeTypeElement e, Void p) {
+            visitAnnotations(e, e.getAnnotationMirrors());
+
+            visitTypeReference(e, e.getSuperclass());
+            for (TypeMirror type : e.getImplements()) {
+                visitTypeReference(e, type);
+            }
+
+            return super.visitType(e, p);
+        }
+
+        private void visitAnnotations(Element enclosingElement, List<? extends AnnotationMirror> mirrors) {
+            for (AnnotationMirror mirror : mirrors) {
+                visitAnnotation(enclosingElement, mirror);
+            }
+        }
+
+        public void visitAnnotation(Element enclosingElement, AnnotationMirror e) {
+            visitTypeReference(enclosingElement, e.getAnnotationType());
+            if (!e.getElementValues().isEmpty()) {
+                Map<? extends ExecutableElement, ? extends AnnotationValue> values = e.getElementValues();
+                Set<? extends ExecutableElement> methodsSet = values.keySet();
+                List<ExecutableElement> methodsList = new ArrayList<>();
+                for (ExecutableElement method : methodsSet) {
+                    if (values.get(method) == null) {
+                        continue;
+                    }
+                    methodsList.add(method);
+                }
+
+                for (int i = 0; i < methodsList.size(); i++) {
+                    AnnotationValue value = values.get(methodsList.get(i));
+                    visitAnnotationValue(enclosingElement, value);
+                }
+            }
+        }
+
+        public void visitAnnotationValue(Element enclosingElement, AnnotationValue e) {
+            e.accept(new AnnotationValueReferenceVisitor(enclosingElement), null);
+        }
+
+        private class AnnotationValueReferenceVisitor extends AbstractAnnotationValueVisitor7<Void, Void> {
+
+            private final Element enclosingElement;
+
+            public AnnotationValueReferenceVisitor(Element enclosedElement) {
+                this.enclosingElement = enclosedElement;
+            }
+
+            @Override
+            public Void visitBoolean(boolean b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitByte(byte b, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitChar(char c, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitDouble(double d, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitFloat(float f, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitInt(int i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitLong(long i, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitShort(short s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitString(String s, Void p) {
+                return null;
+            }
+
+            @Override
+            public Void visitType(TypeMirror t, Void p) {
+                visitTypeReference(enclosingElement, t);
+                return null;
+            }
+
+            @Override
+            public Void visitEnumConstant(VariableElement c, Void p) {
+                visitTypeReference(enclosingElement, c.asType());
+                return null;
+            }
+
+            @Override
+            public Void visitAnnotation(AnnotationMirror a, Void p) {
+                TypeReferenceVisitor.this.visitAnnotation(enclosingElement, a);
+                return null;
+            }
+
+            @Override
+            public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
+                for (int i = 0; i < vals.size(); i++) {
+                    TypeReferenceVisitor.this.visitAnnotationValue(enclosingElement, vals.get(i));
+                }
+                return null;
+            }
+        }
+
+        @Override
+        public Void visitVariable(VariableElement f, Void p) {
+            visitAnnotations(f, f.getAnnotationMirrors());
+            visitTypeReference(f, f.asType());
+            return super.visitVariable(f, p);
+        }
+
+        @Override
+        public void visitImport(CodeImport e, Void p) {
+        }
+
+        public abstract void visitTypeReference(Element enclosedType, TypeMirror type);
+
+        public abstract void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName);
+
+        public abstract void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName);
+
+    }
+
+    private class ImportTypeReferenceVisitor extends TypeReferenceVisitor {
+
+        @Override
+        public void visitStaticFieldReference(Element enclosedType, TypeMirror type, String elementName) {
+            visitTypeReference(enclosedType, type);
+        }
+
+        @Override
+        public void visitStaticMethodReference(Element enclosedType, TypeMirror type, String elementName) {
+            visitTypeReference(enclosedType, type);
+        }
+
+        @Override
+        public void visitTypeReference(Element enclosedType, TypeMirror type) {
+            if (type != null) {
+                switch (type.getKind()) {
+                    case BOOLEAN:
+                    case BYTE:
+                    case CHAR:
+                    case DOUBLE:
+                    case FLOAT:
+                    case SHORT:
+                    case INT:
+                    case LONG:
+                    case VOID:
+                        return;
+                    case DECLARED:
+                        if (needsImport(enclosedType, type)) {
+                            DeclaredType declard = (DeclaredType) type;
+                            registerSymbol(classImportUsage, ElementUtils.getEnclosedQualifiedName(declard), ElementUtils.getDeclaredName(declard, false));
+                        }
+                        for (TypeMirror argument : ((DeclaredType) type).getTypeArguments()) {
+                            visitTypeReference(enclosedType, argument);
+                        }
+                        return;
+                    case ARRAY:
+                        visitTypeReference(enclosedType, ((ArrayType) type).getComponentType());
+                        return;
+                    case WILDCARD:
+                        WildcardType wildcard = (WildcardType) type;
+                        if (wildcard.getExtendsBound() != null) {
+                            visitTypeReference(enclosedType, wildcard.getExtendsBound());
+                        } else if (wildcard.getSuperBound() != null) {
+                            visitTypeReference(enclosedType, wildcard.getSuperBound());
+                        }
+                        return;
+                    case TYPEVAR:
+                        return;
+                    default:
+                        throw new RuntimeException("Unknown type specified " + type.getKind() + " mirror: " + type);
+                }
+
+            }
+        }
+
+        private void registerSymbol(Map<String, String> symbolUsage, String elementQualifiedName, String elementName) {
+            if (symbolUsage.containsKey(elementName)) {
+                String otherQualifiedName = symbolUsage.get(elementName);
+                if (otherQualifiedName == null) {
+                    // already registered ambiguous
+                    return;
+                }
+                if (!otherQualifiedName.equals(elementQualifiedName)) {
+                    symbolUsage.put(elementName, null);
+                }
+            } else {
+                symbolUsage.put(elementName, elementQualifiedName);
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AnnotatedParameterSpec.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class AnnotatedParameterSpec extends ParameterSpec {
+
+    private final DeclaredType annotationType;
+
+    public AnnotatedParameterSpec(DeclaredType type) {
+        super("annotated", Collections.<TypeMirror> emptyList());
+        this.annotationType = type;
+    }
+
+    public DeclaredType getAnnotationType() {
+        return annotationType;
+    }
+
+    @Override
+    public boolean isAnnotated() {
+        return true;
+    }
+
+    @Override
+    public boolean matches(VariableElement variable) {
+        if (ElementUtils.findAnnotationMirror(variable.getAnnotationMirrors(), annotationType) != null) {
+            return true;
+        }
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/AssumptionExpression.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class AssumptionExpression extends MessageContainer {
+
+    private final TemplateMethod source;
+    private final DSLExpression expression;
+    private final String id;
+
+    public AssumptionExpression(TemplateMethod source, DSLExpression expression, String id) {
+        this.source = source;
+        this.expression = expression;
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return source.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return source.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "assumptions");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CacheExpression.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class CacheExpression extends MessageContainer {
+
+    private final DSLExpression expression;
+    private final Parameter sourceParameter;
+    private final AnnotationMirror sourceAnnotationMirror;
+
+    public CacheExpression(Parameter sourceParameter, AnnotationMirror sourceAnnotationMirror, DSLExpression expression) {
+        this.sourceParameter = sourceParameter;
+        this.expression = expression;
+        this.sourceAnnotationMirror = sourceAnnotationMirror;
+    }
+
+    public Parameter getParameter() {
+        return sourceParameter;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return sourceParameter.getVariableElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return sourceAnnotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "value");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/CreateCastData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+public class CreateCastData extends TemplateMethod {
+
+    private final List<String> childNames;
+
+    public CreateCastData(TemplateMethod method, List<String> childNames) {
+        super(method);
+        this.childNames = childNames;
+    }
+
+    public List<String> getChildNames() {
+        return childNames;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ExecutableTypeData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class ExecutableTypeData extends MessageContainer implements Comparable<ExecutableTypeData> {
+
+    private final NodeData node;
+    private final ExecutableElement method;
+    private final TypeMirror returnType;
+    private final TypeMirror frameParameter;
+    private final List<TypeMirror> evaluatedParameters;
+    private ExecutableTypeData delegatedTo;
+    private final List<ExecutableTypeData> delegatedFrom = new ArrayList<>();
+
+    private String uniqueName;
+
+    public ExecutableTypeData(NodeData node, TypeMirror returnType, String uniqueName, TypeMirror frameParameter, List<TypeMirror> evaluatedParameters) {
+        this.node = node;
+        this.returnType = returnType;
+        this.frameParameter = frameParameter;
+        this.evaluatedParameters = evaluatedParameters;
+        this.uniqueName = uniqueName;
+        this.method = null;
+    }
+
+    public ExecutableTypeData(NodeData node, ExecutableElement method, int signatureSize, List<TypeMirror> frameTypes) {
+        this.node = node;
+        this.method = method;
+        this.returnType = method.getReturnType();
+        TypeMirror foundFrameParameter = null;
+        List<? extends VariableElement> parameters = method.getParameters();
+
+        int parameterIndex = 0;
+        evaluatedParameters = new ArrayList<>();
+        if (!parameters.isEmpty()) {
+            TypeMirror firstParameter = parameters.get(0).asType();
+            for (TypeMirror frameType : frameTypes) {
+                if (ElementUtils.typeEquals(firstParameter, frameType)) {
+                    foundFrameParameter = firstParameter;
+                    parameterIndex++;
+                    break;
+                }
+            }
+        }
+
+        int numberParameters = Math.max(parameters.size() - parameterIndex, signatureSize);
+        for (int i = 0; i < numberParameters; i++) {
+            TypeMirror parameter;
+            if (method.isVarArgs() && parameterIndex >= parameters.size() - 1) {
+                ArrayType varArgsArray = (ArrayType) parameters.get(parameters.size() - 1).asType();
+                parameter = varArgsArray.getComponentType();
+            } else if (parameterIndex < parameters.size()) {
+                parameter = parameters.get(parameterIndex).asType();
+            } else {
+                break;
+            }
+            parameterIndex++;
+            evaluatedParameters.add(parameter);
+        }
+        this.frameParameter = foundFrameParameter;
+        this.uniqueName = createName(this);
+    }
+
+    public static String createName(ExecutableTypeData type) {
+        return "execute" + (ElementUtils.isObject(type.getReturnType()) ? "" : ElementUtils.getTypeId(type.getReturnType()));
+    }
+
+    public void addDelegatedFrom(ExecutableTypeData child) {
+        this.delegatedFrom.add(child);
+        child.delegatedTo = this;
+    }
+
+    public List<ExecutableTypeData> getDelegatedFrom() {
+        return delegatedFrom;
+    }
+
+    public ExecutableTypeData getDelegatedTo() {
+        return delegatedTo;
+    }
+
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getUniqueName() {
+        return uniqueName;
+    }
+
+    public void setUniqueName(String name) {
+        this.uniqueName = name;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    public List<TypeMirror> getEvaluatedParameters() {
+        return evaluatedParameters;
+    }
+
+    public List<TypeMirror> getSignatureParameters() {
+        List<TypeMirror> signaturetypes = new ArrayList<>();
+        int index = 0;
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                index++;
+            }
+            if (index < getEvaluatedCount()) {
+                signaturetypes.add(getEvaluatedParameters().get(index));
+            }
+            index++;
+        }
+        return signaturetypes;
+    }
+
+    public int getVarArgsIndex(int parameterIndex) {
+        if (method.isVarArgs()) {
+            int index = parameterIndex - (method.getParameters().size() - 1);
+            return index;
+        }
+        return -1;
+    }
+
+    public int getParameterIndex(int signatureIndex) {
+        return frameParameter != null ? signatureIndex + 1 : signatureIndex;
+    }
+
+    public TypeMirror getFrameParameter() {
+        return frameParameter;
+    }
+
+    public TypeMirror getReturnType() {
+        return returnType;
+    }
+
+    public boolean hasUnexpectedValue(ProcessorContext context) {
+        return method == null ? false : ElementUtils.canThrowType(method.getThrownTypes(), context.getType(UnexpectedResultException.class));
+    }
+
+    public boolean isFinal() {
+        return method == null ? false : method.getModifiers().contains(Modifier.FINAL);
+    }
+
+    public boolean isAbstract() {
+        return method == null ? false : method.getModifiers().contains(Modifier.ABSTRACT);
+    }
+
+    public int getEvaluatedCount() {
+        return evaluatedParameters.size();
+    }
+
+    public boolean canDelegateTo(ExecutableTypeData to) {
+        ExecutableTypeData from = this;
+        if (to.getEvaluatedCount() < from.getEvaluatedCount()) {
+            return false;
+        }
+
+        ProcessorContext context = node.getContext();
+
+        // we cannot delegate from generic to unexpected
+        if (!from.hasUnexpectedValue(context) && to.hasUnexpectedValue(context)) {
+            return false;
+        }
+
+        // we can skip the return type check for void. everything is assignable to void.
+        if (!isVoid(from.getReturnType())) {
+            if (!isSubtypeBoxed(context, from.getReturnType(), to.getReturnType()) && !isSubtypeBoxed(context, to.getReturnType(), from.getReturnType())) {
+                return false;
+            }
+        }
+        if (from.getFrameParameter() != to.getFrameParameter() && from.getFrameParameter() != null && to.getFrameParameter() != null &&
+                        !isSubtypeBoxed(context, from.getFrameParameter(), to.getFrameParameter())) {
+            return false;
+        }
+
+        for (int i = 0; i < from.getEvaluatedCount(); i++) {
+            if (!isSubtypeBoxed(context, from.getEvaluatedParameters().get(i), to.getEvaluatedParameters().get(i))) {
+                return false;
+            }
+        }
+
+        List<TypeMirror> fromSignatureParameters = from.getSignatureParameters();
+        List<TypeMirror> toSignatureParameters = to.getSignatureParameters();
+        for (int i = fromSignatureParameters.size(); i < toSignatureParameters.size(); i++) {
+            TypeMirror delegateToParameter = toSignatureParameters.get(i);
+            if (i < node.getChildExecutions().size()) {
+                TypeMirror genericType = node.getGenericType(node.getChildExecutions().get(i));
+                if (!isSubtypeBoxed(context, genericType, delegateToParameter)) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public int compareTo(ExecutableTypeData o2) {
+        ExecutableTypeData o1 = this;
+        ProcessorContext context = ProcessorContext.getInstance();
+
+        if (canDelegateTo(o2)) {
+            if (!o2.canDelegateTo(this)) {
+                return 1;
+            }
+        } else if (o2.canDelegateTo(this)) {
+            return -1;
+        }
+
+        int result = Integer.compare(o2.getEvaluatedCount(), o1.getEvaluatedCount());
+        if (result != 0) {
+            return result;
+        }
+
+        result = Boolean.compare(o1.hasUnexpectedValue(context), o2.hasUnexpectedValue(context));
+        if (result != 0) {
+            return result;
+        }
+
+        result = compareType(context, o1.getReturnType(), o2.getReturnType());
+        if (result != 0) {
+            return result;
+        }
+        result = compareType(context, o1.getFrameParameter(), o2.getFrameParameter());
+        if (result != 0) {
+            return result;
+        }
+
+        for (int i = 0; i < o1.getEvaluatedCount(); i++) {
+            result = compareType(context, o1.getEvaluatedParameters().get(i), o2.getEvaluatedParameters().get(i));
+            if (result != 0) {
+                return result;
+            }
+        }
+
+        result = o1.getUniqueName().compareTo(o2.getUniqueName());
+        if (result != 0) {
+            return result;
+        }
+
+        if (o1.getMethod() != null && o2.getMethod() != null) {
+            result = ElementUtils.compareMethod(o1.getMethod(), o2.getMethod());
+            if (result != 0) {
+                return result;
+            }
+        }
+        return 0;
+    }
+
+    public static int compareType(ProcessorContext context, TypeMirror signature1, TypeMirror signature2) {
+        if (signature1 == null) {
+            if (signature2 == null) {
+                return 0;
+            }
+            return -1;
+        } else if (signature2 == null) {
+            return 1;
+        }
+        if (ElementUtils.typeEquals(signature1, signature2)) {
+            return 0;
+        }
+        if (isVoid(signature1)) {
+            if (isVoid(signature2)) {
+                return 0;
+            }
+            return 1;
+        } else if (isVoid(signature2)) {
+            return -1;
+        }
+
+        TypeMirror boxedType1 = ElementUtils.boxType(context, signature1);
+        TypeMirror boxedType2 = ElementUtils.boxType(context, signature2);
+
+        if (ElementUtils.isSubtype(boxedType1, boxedType2)) {
+            if (ElementUtils.isSubtype(boxedType2, boxedType1)) {
+                return 0;
+            }
+            return 1;
+        } else if (ElementUtils.isSubtype(boxedType2, boxedType1)) {
+            return -1;
+        } else {
+            return ElementUtils.getSimpleName(signature1).compareTo(ElementUtils.getSimpleName(signature2));
+        }
+    }
+
+    public String getName() {
+        if (method != null) {
+            return method.getSimpleName().toString();
+        } else {
+            return getUniqueName();
+        }
+
+    }
+
+    private static String formatType(TypeMirror type) {
+        return type == null ? "null" : ElementUtils.getSimpleName(type);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s %s(%s,%s)", formatType(getReturnType()), getName(), formatType(getFrameParameter()), getEvaluatedParameters());
+    }
+
+    public boolean sameParameters(ExecutableTypeData other) {
+        if (!typeEquals(other.getFrameParameter(), getFrameParameter())) {
+            return false;
+        }
+
+        if (getEvaluatedCount() != other.getEvaluatedCount()) {
+            return false;
+        }
+
+        for (int i = 0; i < getEvaluatedCount(); i++) {
+            if (!typeEquals(getEvaluatedParameters().get(i), other.getEvaluatedParameters().get(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean sameSignature(ExecutableTypeData other) {
+        if (!typeEquals(other.getReturnType(), getReturnType())) {
+            return false;
+        }
+
+        if (other.getFrameParameter() != null) {
+            if (!typeEquals(getFrameParameter(), other.getFrameParameter())) {
+                return false;
+            }
+        }
+
+        if (getEvaluatedCount() != other.getEvaluatedCount()) {
+            return false;
+        }
+
+        for (int i = 0; i < getEvaluatedCount(); i++) {
+            if (!typeEquals(getEvaluatedParameters().get(i), other.getEvaluatedParameters().get(i))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class GuardExpression extends MessageContainer {
+
+    private final TemplateMethod source;
+    private final DSLExpression expression;
+
+    public GuardExpression(TemplateMethod source, DSLExpression expression) {
+        this.source = source;
+        this.expression = expression;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return source.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return source.getMessageAnnotation();
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return ElementUtils.getAnnotationValue(getMessageAnnotation(), "guards");
+    }
+
+    public DSLExpression getExpression() {
+        return expression;
+    }
+
+    public boolean equalsNegated(GuardExpression other) {
+        boolean negated = false;
+        DSLExpression thisExpression = expression;
+        if (thisExpression instanceof Negate) {
+            negated = true;
+            thisExpression = ((Negate) thisExpression).getReceiver();
+        }
+
+        boolean otherNegated = false;
+        DSLExpression otherExpression = other.expression;
+        if (otherExpression instanceof Negate) {
+            otherNegated = true;
+            otherExpression = ((Negate) otherExpression).getReceiver();
+        }
+        return Objects.equals(thisExpression, otherExpression) && negated != otherNegated;
+    }
+
+    public boolean implies(GuardExpression other) {
+        if (Objects.equals(expression, other.expression)) {
+            return true;
+        }
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ImplicitCastData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+public class ImplicitCastData extends TemplateMethod {
+
+    private final TypeMirror sourceType;
+    private final TypeMirror targetType;
+
+    public ImplicitCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public TypeMirror getSourceType() {
+        return sourceType;
+    }
+
+    public TypeMirror getTargetType() {
+        return targetType;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        return super.compareTo(o);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class MessageContainer implements Iterable<MessageContainer> {
+
+    private final List<Message> messages = new ArrayList<>();
+
+    public final void addWarning(String text, Object... params) {
+        getMessages().add(new Message(null, null, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addWarning(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.WARNING));
+    }
+
+    public final void addError(String text, Object... params) {
+        addError(null, text, params);
+    }
+
+    public final void addError(AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(null, value, this, String.format(text, params), Kind.ERROR));
+    }
+
+    public final void addError(AnnotationMirror mirror, AnnotationValue value, String text, Object... params) {
+        getMessages().add(new Message(mirror, value, this, String.format(text, params), Kind.ERROR));
+    }
+
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public abstract Element getMessageElement();
+
+    public MessageContainer getBaseContainer() {
+        return null;
+    }
+
+    public Iterator<MessageContainer> iterator() {
+        return findChildContainers().iterator();
+    }
+
+    public final void emitMessages(ProcessorContext context, Log log) {
+        emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
+    }
+
+    private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
+        List<Message> childMessages;
+        if (verifiedMessages == null) {
+            childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
+        } else {
+            childMessages = verifiedMessages;
+        }
+        verifyExpectedMessages(context, log, childMessages);
+
+        for (int i = getMessages().size() - 1; i >= 0; i--) {
+            emitDefault(context, log, getMessages().get(i));
+        }
+
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                continue;
+            }
+
+            visitedSinks.add(sink);
+            if (sink.getMessageElement() == this.getMessageElement()) {
+                sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
+            } else {
+                sink.emitMessagesImpl(context, log, visitedSinks, null);
+            }
+        }
+    }
+
+    private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
+        if (visitedSinks.contains(this)) {
+            return Collections.emptyList();
+        }
+        visitedSinks.add(this);
+
+        List<Message> foundMessages = new ArrayList<>();
+        if (getMessageElement() != null && ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) {
+            foundMessages.addAll(getMessages());
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
+        }
+        return foundMessages;
+    }
+
+    private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            Element element = getMessageElement();
+            if (element != null) {
+                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError.asType());
+                if (mirror != null) {
+                    List<String> values = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                    if (values == null) {
+                        values = Collections.emptyList();
+                    }
+                    if (values.size() != msgs.size()) {
+                        log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
+                    }
+                }
+            }
+        }
+    }
+
+    private void emitDefault(ProcessorContext context, Log log, Message message) {
+        Kind kind = message.getKind();
+
+        Element messageElement = getMessageElement();
+        AnnotationMirror messageAnnotation = getMessageAnnotation();
+        AnnotationValue messageValue = getMessageAnnotationValue();
+        if (message.getAnnotationValue() != null) {
+            messageValue = message.getAnnotationValue();
+        }
+        if (message.getAnnotationMirror() != null) {
+            messageAnnotation = message.getAnnotationMirror();
+        }
+
+        String text = message.getText();
+
+        TypeElement expectError = context.getTruffleTypes().getExpectError();
+        if (expectError != null) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError.asType());
+            if (mirror != null) {
+                List<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+                boolean found = false;
+                for (String expectedText : expectedTexts) {
+                    if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
+                        found = true;
+                        break;
+                    } else if (text.equals(expectedText)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
+                } else {
+                    return;
+                }
+
+            }
+        }
+
+        log.message(kind, messageElement, messageAnnotation, messageValue, text);
+    }
+
+    public AnnotationMirror getMessageAnnotation() {
+        return null;
+    }
+
+    public AnnotationValue getMessageAnnotationValue() {
+        return null;
+    }
+
+    public final boolean hasErrors() {
+        return hasErrorsImpl(new HashSet<MessageContainer>());
+    }
+
+    public final List<Message> collectMessages() {
+        List<Message> collectedMessages = new ArrayList<>();
+        collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
+        return collectedMessages;
+    }
+
+    private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
+        collectedMessages.addAll(getMessages());
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return;
+            }
+
+            visitedSinks.add(sink);
+            sink.collectMessagesImpl(collectedMessages, visitedSinks);
+        }
+    }
+
+    private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
+        for (Message msg : getMessages()) {
+            if (msg.getKind() == Kind.ERROR) {
+                return true;
+            }
+        }
+        for (MessageContainer sink : findChildContainers()) {
+            if (visitedSinks.contains(sink)) {
+                return false;
+            }
+
+            visitedSinks.add(sink);
+
+            if (sink.hasErrorsImpl(visitedSinks)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<Message> getMessages() {
+        return messages;
+    }
+
+    public static final class Message {
+
+        private final MessageContainer originalContainer;
+        private final AnnotationMirror annotationMirror;
+        private final AnnotationValue annotationValue;
+        private final String text;
+        private final Kind kind;
+
+        public Message(AnnotationMirror annotationMirror, AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
+            this.annotationMirror = annotationMirror;
+            this.annotationValue = annotationValue;
+            this.originalContainer = originalContainer;
+            this.text = text;
+            this.kind = kind;
+        }
+
+        public AnnotationMirror getAnnotationMirror() {
+            return annotationMirror;
+        }
+
+        public AnnotationValue getAnnotationValue() {
+            return annotationValue;
+        }
+
+        public MessageContainer getOriginalContainer() {
+            return originalContainer;
+        }
+
+        public String getText() {
+            return text;
+        }
+
+        public Kind getKind() {
+            return kind;
+        }
+
+        @Override
+        public String toString() {
+            return kind + ": " + text;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MethodSpec.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class MethodSpec {
+
+    private final ParameterSpec returnType;
+    private final List<ParameterSpec> optional = new ArrayList<>();
+    private final List<ParameterSpec> required = new ArrayList<>();
+    private final List<ParameterSpec> annotations = new ArrayList<>();
+
+    private boolean ignoreAdditionalParameters;
+    private boolean ignoreAdditionalSpecifications;
+    private boolean variableRequiredParameters;
+
+    private List<TypeDef> typeDefinitions;
+
+    public MethodSpec(ParameterSpec returnType) {
+        this.returnType = returnType;
+    }
+
+    public void setVariableRequiredParameters(boolean variableRequiredParameters) {
+        this.variableRequiredParameters = variableRequiredParameters;
+    }
+
+    public boolean isVariableRequiredParameters() {
+        return variableRequiredParameters;
+    }
+
+    public void setIgnoreAdditionalParameters(boolean ignoreAdditionalParameter) {
+        this.ignoreAdditionalParameters = ignoreAdditionalParameter;
+    }
+
+    public boolean isIgnoreAdditionalParameters() {
+        return ignoreAdditionalParameters;
+    }
+
+    public void addOptional(ParameterSpec spec) {
+        optional.add(spec);
+    }
+
+    public ParameterSpec addRequired(ParameterSpec spec) {
+        required.add(spec);
+        return spec;
+    }
+
+    public List<ParameterSpec> getAnnotations() {
+        return annotations;
+    }
+
+    public ParameterSpec getReturnType() {
+        return returnType;
+    }
+
+    public List<ParameterSpec> getRequired() {
+        return required;
+    }
+
+    public List<ParameterSpec> getOptional() {
+        return optional;
+    }
+
+    public List<ParameterSpec> getAll() {
+        List<ParameterSpec> specs = new ArrayList<>();
+        specs.add(getReturnType());
+        specs.addAll(getOptional());
+        specs.addAll(getRequired());
+        return specs;
+    }
+
+    public void applyTypeDefinitions(String prefix) {
+        this.typeDefinitions = createTypeDefinitions(prefix);
+    }
+
+    private List<TypeDef> createTypeDefinitions(String prefix) {
+        List<TypeDef> typeDefs = new ArrayList<>();
+
+        int defIndex = 0;
+        for (ParameterSpec spec : getAll()) {
+            Collection<TypeMirror> allowedTypes = spec.getAllowedTypes();
+            Collection<TypeMirror> types = spec.getAllowedTypes();
+            if (types != null && allowedTypes.size() > 1) {
+                TypeDef foundDef = null;
+                for (TypeDef def : typeDefs) {
+                    if (allowedTypes.equals(def.getTypes())) {
+                        foundDef = def;
+                        break;
+                    }
+                }
+                if (foundDef == null) {
+                    foundDef = new TypeDef(types, prefix + defIndex);
+                    typeDefs.add(foundDef);
+                    defIndex++;
+                }
+
+                spec.setTypeDefinition(foundDef);
+            }
+        }
+
+        return typeDefs;
+    }
+
+    public String toSignatureString(String methodName) {
+        StringBuilder b = new StringBuilder();
+        b.append("    ");
+        b.append(createTypeSignature(returnType, true));
+
+        b.append(" ");
+        b.append(methodName);
+        b.append("(");
+
+        String sep = "";
+
+        for (ParameterSpec optionalSpec : getOptional()) {
+            b.append(sep);
+            b.append("[");
+            b.append(createTypeSignature(optionalSpec, false));
+            b.append("]");
+            sep = ", ";
+        }
+
+        for (int i = 0; i < getRequired().size(); i++) {
+            ParameterSpec requiredSpec = getRequired().get(i);
+            b.append(sep);
+
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("{"));
+            }
+            b.append(createTypeSignature(requiredSpec, false));
+            if (isVariableRequiredParameters() && i == getRequired().size() - 1) {
+                b.append(("}"));
+            }
+
+            sep = ", ";
+        }
+
+        b.append(")");
+
+        if (typeDefinitions != null && !typeDefinitions.isEmpty()) {
+            b.append("\n\n");
+
+            String lineSep = "";
+            for (TypeDef def : typeDefinitions) {
+                b.append(lineSep);
+                b.append("    <").append(def.getName()).append(">");
+                b.append(" = {");
+                String separator = "";
+                for (TypeMirror type : def.getTypes()) {
+                    b.append(separator).append(ElementUtils.getSimpleName(type));
+                    separator = ", ";
+                }
+                b.append("}");
+                lineSep = "\n";
+
+            }
+        }
+        return b.toString();
+    }
+
+    private static String createTypeSignature(ParameterSpec spec, boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        TypeDef foundTypeDef = spec.getTypeDefinition();
+        if (foundTypeDef != null) {
+            builder.append("<" + foundTypeDef.getName() + ">");
+        } else if (spec.getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(spec.getAllowedTypes().iterator().next()));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(spec.getName());
+        }
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString("methodName");
+    }
+
+    static final class TypeDef {
+
+        private final Collection<TypeMirror> types;
+        private final String name;
+
+        private TypeDef(Collection<TypeMirror> types, String name) {
+            this.types = types;
+            this.name = name;
+        }
+
+        public Collection<TypeMirror> getTypes() {
+            return types;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    public void setIgnoreAdditionalSpecifications(boolean ignoreAdditoinalSpecifications) {
+        this.ignoreAdditionalSpecifications = ignoreAdditoinalSpecifications;
+    }
+
+    public boolean isIgnoreAdditionalSpecifications() {
+        return ignoreAdditionalSpecifications;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeChildData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+
+public class NodeChildData extends MessageContainer {
+
+    public enum Cardinality {
+        ONE,
+        MANY;
+
+        public boolean isMany() {
+            return this == MANY;
+        }
+
+        public boolean isOne() {
+            return this == ONE;
+        }
+    }
+
+    private final Element sourceElement;
+    private final AnnotationMirror sourceAnnotationMirror;
+    private final String name;
+    private final TypeMirror type;
+    private final TypeMirror originalType;
+    private final Element accessElement;
+    private final Cardinality cardinality;
+
+    private List<NodeExecutionData> executeWith = Collections.emptyList();
+
+    private NodeData childNode;
+
+    public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality) {
+        this.sourceElement = sourceElement;
+        this.sourceAnnotationMirror = sourceMirror;
+        this.name = name;
+        this.type = nodeType;
+        this.originalType = originalNodeType;
+        this.accessElement = accessElement;
+        this.cardinality = cardinality;
+    }
+
+    public List<NodeExecutionData> getExecuteWith() {
+        return executeWith;
+    }
+
+    public void setExecuteWith(List<NodeExecutionData> executeWith) {
+        this.executeWith = executeWith;
+    }
+
+    public ExecutableTypeData findExecutableType(TypeMirror targetType) {
+        return childNode.findExecutableType(targetType, getExecuteWith().size());
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context) {
+        return childNode.findGenericExecutableTypes(context, getExecuteWith().size());
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context) {
+        return childNode.findAnyGenericExecutableType(context, getExecuteWith().size());
+    }
+
+    public TypeMirror getOriginalType() {
+        return originalType;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return sourceElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return sourceAnnotationMirror;
+    }
+
+    public void setNode(NodeData nodeData) {
+        this.childNode = nodeData;
+        if (nodeData != null) {
+            getMessages().addAll(nodeData.collectMessages());
+        }
+    }
+
+    public Element getAccessElement() {
+        return accessElement;
+    }
+
+    public TypeMirror getNodeType() {
+        return type;
+    }
+
+    public Cardinality getCardinality() {
+        return cardinality;
+    }
+
+    public NodeData getNodeData() {
+        return childNode;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "NodeFieldData[name=" + getName() + ", kind=" + cardinality + ", node=" + getNodeData() + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeData extends Template implements Comparable<NodeData> {
+
+    private final String nodeId;
+    private final String shortName;
+    private final List<NodeData> enclosingNodes = new ArrayList<>();
+    private NodeData declaringNode;
+
+    private final TypeSystemData typeSystem;
+    private final List<NodeChildData> children;
+    private final List<NodeExecutionData> childExecutions;
+    private final List<NodeFieldData> fields;
+
+    private ParameterSpec instanceParameterSpec;
+
+    private final List<SpecializationData> specializations = new ArrayList<>();
+    private final List<ShortCircuitData> shortCircuits = new ArrayList<>();
+    private final List<CreateCastData> casts = new ArrayList<>();
+    private final List<ExecutableTypeData> executableTypes = new ArrayList<>();
+
+    private final NodeExecutionData thisExecution;
+    private final boolean generateFactory;
+
+    private TypeMirror frameType;
+
+    public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, boolean generateFactory) {
+        super(context, type, null);
+        this.nodeId = ElementUtils.getSimpleName(type);
+        this.shortName = shortName;
+        this.typeSystem = typeSystem;
+        this.fields = new ArrayList<>();
+        this.children = new ArrayList<>();
+        this.childExecutions = new ArrayList<>();
+        this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, -1, false);
+        this.thisExecution.getChild().setNode(this);
+        this.generateFactory = generateFactory;
+    }
+
+    public NodeData(ProcessorContext context, TypeElement type) {
+        this(context, type, null, null, false);
+    }
+
+    public boolean isGenerateFactory() {
+        return generateFactory;
+    }
+
+    public NodeExecutionData getThisExecution() {
+        return thisExecution;
+    }
+
+    public boolean isFallbackReachable() {
+        SpecializationData generic = getGenericSpecialization();
+        if (generic != null) {
+            return generic.isReachable();
+        }
+        return false;
+    }
+
+    public void setFrameType(TypeMirror frameType) {
+        this.frameType = frameType;
+    }
+
+    public TypeMirror getFrameType() {
+        return frameType;
+    }
+
+    public void addEnclosedNode(NodeData node) {
+        this.enclosingNodes.add(node);
+        node.declaringNode = this;
+    }
+
+    public List<NodeExecutionData> getChildExecutions() {
+        return childExecutions;
+    }
+
+    public Set<TypeMirror> findSpecializedTypes(NodeExecutionData execution) {
+        Set<TypeMirror> types = new HashSet<>();
+        for (SpecializationData specialization : getSpecializations()) {
+            if (!specialization.isSpecialized()) {
+                continue;
+            }
+            List<Parameter> parameters = specialization.findByExecutionData(execution);
+            for (Parameter parameter : parameters) {
+                TypeMirror type = parameter.getType();
+                if (type == null) {
+                    throw new AssertionError();
+                }
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public Collection<TypeMirror> findSpecializedReturnTypes() {
+        Set<TypeMirror> types = new HashSet<>();
+        for (SpecializationData specialization : getSpecializations()) {
+            if (!specialization.isSpecialized()) {
+                continue;
+            }
+            types.add(specialization.getReturnType().getType());
+        }
+        return types;
+    }
+
+    public int getExecutionCount() {
+        return getChildExecutions().size();
+    }
+
+    public int getSignatureSize() {
+        int count = 0;
+        for (NodeExecutionData execution : getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                count++;
+            }
+            count++;
+        }
+        return count;
+    }
+
+    public boolean isFrameUsedByAnyGuard() {
+        for (SpecializationData specialization : specializations) {
+            if (!specialization.isReachable()) {
+                continue;
+            }
+            Parameter frame = specialization.getFrame();
+            if (frame != null) {
+                for (GuardExpression guard : specialization.getGuards()) {
+                    if (guard.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) {
+                        return true;
+                    }
+                }
+                for (CacheExpression cache : specialization.getCaches()) {
+                    if (cache.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    public List<CreateCastData> getCasts() {
+        return casts;
+    }
+
+    public String getShortName() {
+        return shortName;
+    }
+
+    public List<NodeFieldData> getFields() {
+        return fields;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> containerChildren = new ArrayList<>();
+        if (enclosingNodes != null) {
+            containerChildren.addAll(enclosingNodes);
+        }
+        if (typeSystem != null) {
+            containerChildren.add(typeSystem);
+        }
+        if (specializations != null) {
+            for (MessageContainer specialization : specializations) {
+                if (specialization.getMessageElement() != null) {
+                    containerChildren.add(specialization);
+                }
+            }
+        }
+        if (executableTypes != null) {
+            containerChildren.addAll(getExecutableTypes());
+        }
+        if (shortCircuits != null) {
+            containerChildren.addAll(shortCircuits);
+        }
+        if (children != null) {
+            containerChildren.addAll(children);
+        }
+        if (fields != null) {
+            containerChildren.addAll(fields);
+        }
+        if (casts != null) {
+            containerChildren.addAll(casts);
+        }
+        return containerChildren;
+    }
+
+    public ParameterSpec getInstanceParameterSpec() {
+        return instanceParameterSpec;
+    }
+
+    public void setInstanceParameterSpec(ParameterSpec instanceParameter) {
+        this.instanceParameterSpec = instanceParameter;
+    }
+
+    public String getNodeId() {
+        return nodeId;
+    }
+
+    public TypeMirror getNodeType() {
+        return getTemplateType().asType();
+    }
+
+    public boolean needsFactory() {
+        if (specializations == null) {
+            return false;
+        }
+        if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+            return false;
+        }
+
+        boolean noSpecialization = true;
+        for (SpecializationData specialization : specializations) {
+            noSpecialization = noSpecialization && !specialization.isSpecialized();
+        }
+        return !noSpecialization;
+    }
+
+    public boolean supportsFrame() {
+        if (executableTypes != null) {
+            for (ExecutableTypeData execType : getExecutableTypes(-1)) {
+                if (execType.getFrameParameter() == null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public NodeExecutionData findExecutionByExpression(String childNameExpression) {
+        String childName = childNameExpression;
+        int index = -1;
+
+        int start = childName.indexOf('[');
+        int end = childName.lastIndexOf(']');
+        if (start != -1 && end != -1 && start < end) {
+            try {
+                index = Integer.parseInt(childName.substring(start + 1, end));
+                childName = childName.substring(0, start);
+                childName = NodeExecutionData.createName(childName, index);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        for (NodeExecutionData execution : childExecutions) {
+            if (execution.getName().equals(childName) && (execution.getChildIndex() == -1 || execution.getChildIndex() == index)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
+    public List<NodeData> getNodesWithFactories() {
+        List<NodeData> nodeChildren = new ArrayList<>();
+        for (NodeData child : getEnclosingNodes()) {
+            if (child.needsFactory() && child.isGenerateFactory()) {
+                nodeChildren.add(child);
+            }
+            nodeChildren.addAll(child.getNodesWithFactories());
+        }
+        return nodeChildren;
+    }
+
+    public NodeData getDeclaringNode() {
+        return declaringNode;
+    }
+
+    public List<NodeData> getEnclosingNodes() {
+        return enclosingNodes;
+    }
+
+    public List<ExecutableElement> getAllTemplateMethods() {
+        List<ExecutableElement> methods = new ArrayList<>();
+
+        for (SpecializationData specialization : getSpecializations()) {
+            methods.add(specialization.getMethod());
+        }
+
+        for (ExecutableTypeData execType : getExecutableTypes()) {
+            if (execType.getMethod() != null) {
+                methods.add(execType.getMethod());
+            }
+        }
+        for (ShortCircuitData shortcircuit : getShortCircuits()) {
+            methods.add(shortcircuit.getMethod());
+        }
+
+        if (getCasts() != null) {
+            for (CreateCastData castData : getCasts()) {
+                methods.add(castData.getMethod());
+            }
+        }
+
+        return methods;
+    }
+
+    public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount);
+        for (ExecutableTypeData type : types) {
+            if (context.isType(type.getReturnType(), Object.class)) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            if (!context.isType(type.getReturnType(), void.class)) {
+                return type;
+            }
+        }
+
+        for (ExecutableTypeData type : types) {
+            return type;
+        }
+        return null;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) {
+        if (evaluatedCount == -1) {
+            return executableTypes;
+        } else {
+            List<ExecutableTypeData> filteredTypes = new ArrayList<>();
+            for (ExecutableTypeData type : executableTypes) {
+                if (type.getEvaluatedCount() == evaluatedCount) {
+                    filteredTypes.add(type);
+                }
+            }
+            return filteredTypes;
+        }
+    }
+
+    public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) {
+        List<ExecutableTypeData> types = new ArrayList<>();
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (!type.hasUnexpectedValue(context)) {
+                types.add(type);
+            }
+        }
+        return types;
+    }
+
+    public ExecutableTypeData findExecutableType(TypeMirror primitiveType, int evaluatedCount) {
+        for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) {
+            if (ElementUtils.typeEquals(type.getReturnType(), primitiveType)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public boolean needsRewrites(ProcessorContext context) {
+        boolean needsRewrites = false;
+
+        for (SpecializationData specialization : getSpecializations()) {
+            if (specialization.hasRewrite(context)) {
+                needsRewrites = true;
+                break;
+            }
+        }
+        return needsRewrites || getSpecializations().size() > 1;
+    }
+
+    public SpecializationData getPolymorphicSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isPolymorphic()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getGenericSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isFallback()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    public SpecializationData getUninitializedSpecialization() {
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isUninitialized()) {
+                return specialization;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return typeSystem;
+    }
+
+    @Override
+    public String dump() {
+        return dump(0);
+    }
+
+    private String dump(int level) {
+        String indent = "";
+        for (int i = 0; i < level; i++) {
+            indent += "    ";
+        }
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("%s%s {", indent, toString()));
+
+        dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType()));
+        dumpProperty(builder, indent, "typeSystem", getTypeSystem());
+        dumpProperty(builder, indent, "fields", getChildren());
+        dumpProperty(builder, indent, "executableTypes", getExecutableTypes());
+        dumpProperty(builder, indent, "specializations", getSpecializations());
+        dumpProperty(builder, indent, "casts", getCasts());
+        dumpProperty(builder, indent, "messages", collectMessages());
+        if (getEnclosingNodes().size() > 0) {
+            builder.append(String.format("\n%s  children = [", indent));
+            for (NodeData node : getEnclosingNodes()) {
+                builder.append("\n");
+                builder.append(node.dump(level + 1));
+            }
+            builder.append(String.format("\n%s  ]", indent));
+        }
+        builder.append(String.format("%s}", indent));
+        return builder.toString();
+    }
+
+    private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) {
+        if (value instanceof List) {
+            List<?> list = (List<?>) value;
+            if (!list.isEmpty()) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, dumpList(indent, (List<?>) value)));
+            }
+        } else {
+            if (value != null) {
+                b.append(String.format("\n%s  %s = %s", indent, propertyName, value));
+            }
+        }
+    }
+
+    private static String dumpList(String indent, List<?> array) {
+        if (array == null) {
+            return "null";
+        }
+
+        if (array.isEmpty()) {
+            return "[]";
+        } else if (array.size() == 1) {
+            return "[" + array.get(0).toString() + "]";
+        }
+
+        StringBuilder b = new StringBuilder();
+        b.append("[");
+        for (Object object : array) {
+            b.append("\n        ");
+            b.append(indent);
+            b.append(object);
+            b.append(", ");
+        }
+        b.append("\n    ").append(indent).append("]");
+        return b.toString();
+    }
+
+    public NodeChildData findChild(String name) {
+        for (NodeChildData field : getChildren()) {
+            if (field.getName().equals(name)) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    public List<NodeChildData> getChildren() {
+        return children;
+    }
+
+    public List<SpecializationData> getSpecializations() {
+        return specializations;
+    }
+
+    public ExecutableTypeData getGenericExecutableType(ExecutableTypeData typeHint) {
+        ExecutableTypeData polymorphicDelegate = null;
+        if (typeHint != null) {
+            polymorphicDelegate = typeHint;
+            while (polymorphicDelegate.getDelegatedTo() != null && polymorphicDelegate.getEvaluatedCount() != getSignatureSize()) {
+                polymorphicDelegate = polymorphicDelegate.getDelegatedTo();
+            }
+        }
+        if (polymorphicDelegate == null) {
+            for (ExecutableTypeData type : getExecutableTypes()) {
+                if (type.getDelegatedTo() == null && type.getEvaluatedCount() == getSignatureSize()) {
+                    polymorphicDelegate = type;
+                    break;
+                }
+            }
+        }
+        return polymorphicDelegate;
+    }
+
+    public List<ExecutableTypeData> getExecutableTypes() {
+        return getExecutableTypes(-1);
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public int getMinimalEvaluatedParameters() {
+        int minimalEvaluatedParameters = Integer.MAX_VALUE;
+        for (ExecutableTypeData type : getExecutableTypes()) {
+            minimalEvaluatedParameters = Math.min(minimalEvaluatedParameters, type.getEvaluatedCount());
+        }
+        return minimalEvaluatedParameters;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + getNodeId() + "]";
+    }
+
+    public CreateCastData findCast(String name) {
+        if (getCasts() != null) {
+            for (CreateCastData cast : getCasts()) {
+                if (cast.getChildNames().contains(name)) {
+                    return cast;
+                }
+            }
+        }
+        return null;
+    }
+
+    public int compareTo(NodeData o) {
+        return getNodeId().compareTo(o.getNodeId());
+    }
+
+    public TypeMirror getGenericType(NodeExecutionData execution) {
+        return ElementUtils.getCommonSuperType(getContext(), getGenericTypes(execution));
+    }
+
+    public List<TypeMirror> getGenericTypes(NodeExecutionData execution) {
+        List<TypeMirror> types = new ArrayList<>();
+
+        // add types possible through return types and evaluated parameters in execute methods
+        if (execution.getChild() != null) {
+            for (ExecutableTypeData executable : execution.getChild().getNodeData().getExecutableTypes()) {
+                if (executable.hasUnexpectedValue(getContext())) {
+                    continue;
+                }
+                types.add(executable.getReturnType());
+            }
+        }
+
+        int executionIndex = execution.getIndex();
+        if (executionIndex >= 0) {
+            for (ExecutableTypeData typeData : getExecutableTypes()) {
+                List<TypeMirror> signatureParameters = typeData.getSignatureParameters();
+                if (executionIndex < signatureParameters.size()) {
+                    TypeMirror genericType = signatureParameters.get(executionIndex);
+                    types.add(genericType);
+                }
+            }
+        }
+
+        return ElementUtils.uniqueSortedTypes(types, false);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+
+public class NodeExecutionData {
+
+    private final NodeChildData child;
+    private final String name;
+    private final int index;
+    private final int childIndex;
+    private final boolean shortCircuit;
+    private final List<TypeMirror> typeRestrictions = new ArrayList<>();
+
+    public NodeExecutionData(NodeChildData child, int index, int childIndex, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.childIndex = childIndex;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        return child != null ? createName(child.getName(), childIndex) : ("arg" + index);
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public List<TypeMirror> getTypeRestrictions() {
+        return typeRestrictions;
+    }
+
+    public TypeMirror getNodeType() {
+        TypeMirror type;
+        if (child.getCardinality() == Cardinality.MANY && child.getNodeType().getKind() == TypeKind.ARRAY) {
+            type = ((ArrayType) child.getNodeType()).getComponentType();
+        } else {
+            type = child.getNodeType();
+        }
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public NodeChildData getChild() {
+        return child;
+    }
+
+    public int getChildIndex() {
+        return childIndex;
+    }
+
+    public boolean isIndexed() {
+        return childIndex > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getIndexedName() {
+        return createIndexedName(child, childIndex);
+    }
+
+    public static String createIndexedName(NodeChildData child, int varArgsIndex) {
+        String shortCircuitName = child.getName();
+        if (child.getCardinality().isMany()) {
+            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
+        }
+        return shortCircuitName;
+    }
+
+    public static String createName(String childName, int index) {
+        if (index > -1) {
+            return childName + index;
+        }
+        return childName;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeFieldData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class NodeFieldData extends MessageContainer {
+
+    private final Element messageElement;
+    private final AnnotationMirror messageAnnotation;
+    private final boolean generated;
+    private ExecutableElement getter;
+    private final VariableElement variable;
+
+    public NodeFieldData(Element messageElement, AnnotationMirror messageAnnotation, VariableElement variableElement, boolean generated) {
+        this.messageElement = messageElement;
+        this.messageAnnotation = messageAnnotation;
+        this.generated = generated;
+        this.variable = variableElement;
+    }
+
+    public VariableElement getVariable() {
+        return variable;
+    }
+
+    public void setGetter(ExecutableElement getter) {
+        this.getter = getter;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return messageElement;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return messageAnnotation;
+    }
+
+    public String getName() {
+        return variable.getSimpleName().toString();
+    }
+
+    public TypeMirror getType() {
+        return variable.asType();
+    }
+
+    public boolean isGenerated() {
+        return generated;
+    }
+
+    public ExecutableElement getGetter() {
+        return getter;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Parameter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public final class Parameter {
+
+    private final ParameterSpec specification;
+    private TemplateMethod method;
+    private String localName;
+    private final int specificationVarArgsIndex;
+    private final int typeVarArgsIndex;
+    private final VariableElement variableElement;
+    private final TypeMirror type;
+
+    public Parameter(ParameterSpec specification, VariableElement variableElement, int specificationVarArgsIndex, int typeVarArgsIndex) {
+        this.specification = specification;
+        this.variableElement = variableElement;
+        this.type = variableElement.asType();
+        this.specificationVarArgsIndex = specificationVarArgsIndex;
+
+        String valueName = specification.getName() + "Value";
+        if (specificationVarArgsIndex > -1) {
+            valueName += specificationVarArgsIndex;
+        }
+        this.typeVarArgsIndex = typeVarArgsIndex;
+        this.localName = valueName;
+    }
+
+    public Parameter(Parameter parameter) {
+        this.specification = parameter.specification;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
+        this.localName = parameter.localName;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+        this.variableElement = parameter.variableElement;
+        this.type = parameter.type;
+    }
+
+    public Parameter(Parameter parameter, TypeMirror newType) {
+        this.specification = parameter.specification;
+        this.specificationVarArgsIndex = parameter.specificationVarArgsIndex;
+        this.localName = parameter.localName;
+        this.typeVarArgsIndex = parameter.typeVarArgsIndex;
+        this.variableElement = parameter.variableElement;
+        this.type = newType;
+    }
+
+    public void setLocalName(String localName) {
+        this.localName = localName;
+    }
+
+    public VariableElement getVariableElement() {
+        return variableElement;
+    }
+
+    public int getTypeVarArgsIndex() {
+        return typeVarArgsIndex;
+    }
+
+    public int getSpecificationVarArgsIndex() {
+        return specificationVarArgsIndex;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    void setMethod(TemplateMethod method) {
+        this.method = method;
+    }
+
+    public ParameterSpec getSpecification() {
+        return specification;
+    }
+
+    public TemplateMethod getMethod() {
+        return method;
+    }
+
+    public TypeMirror getType() {
+        return type;
+    }
+
+    public boolean isTypeVarArgs() {
+        return typeVarArgsIndex >= 0;
+    }
+
+    public Parameter getPreviousParameter() {
+        return method.getPreviousParam(this);
+    }
+
+    @Override
+    public String toString() {
+        return "Parameter [localName=" + localName + ", type=" + getType() + ", variableElement=" + variableElement + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
+
+public class ParameterSpec {
+
+    private final String name;
+    private final Collection<TypeMirror> allowedTypes;
+    private final boolean anyType;
+
+    /** Type is bound to local final variable. */
+    private boolean local;
+    private boolean signature;
+    private boolean allowSubclasses = true;
+
+    /** Optional bound execution of node. */
+    private NodeExecutionData execution;
+    private TypeDef typeDefinition;
+
+    public ParameterSpec(String name, Collection<TypeMirror> allowedTypes) {
+        this.name = name;
+        this.allowedTypes = allowedTypes;
+        boolean anyTypeTemp = false;
+        for (TypeMirror type : allowedTypes) {
+            if (ElementUtils.isObject(type)) {
+                anyTypeTemp = true;
+                break;
+            }
+        }
+        this.anyType = anyTypeTemp;
+    }
+
+    public boolean isAnnotated() {
+        return false;
+    }
+
+    public ParameterSpec(ParameterSpec original, TypeMirror newType) {
+        this(original.name, newType);
+        this.local = original.local;
+        this.signature = original.signature;
+        this.execution = original.execution;
+        this.typeDefinition = original.typeDefinition;
+        this.allowSubclasses = original.allowSubclasses;
+    }
+
+    public ParameterSpec(String name, TypeMirror type) {
+        this(name, Arrays.asList(type));
+    }
+
+    public void setAllowSubclasses(boolean allowSubclasses) {
+        this.allowSubclasses = allowSubclasses;
+    }
+
+    public NodeExecutionData getExecution() {
+        return execution;
+    }
+
+    public void setExecution(NodeExecutionData executionData) {
+        this.execution = executionData;
+        this.signature = execution != null;
+    }
+
+    public void setSignature(boolean signature) {
+        this.signature = signature;
+    }
+
+    void setTypeDefinition(TypeDef typeDefinition) {
+        this.typeDefinition = typeDefinition;
+    }
+
+    TypeDef getTypeDefinition() {
+        return typeDefinition;
+    }
+
+    public void setLocal(boolean local) {
+        this.local = local;
+    }
+
+    public boolean isSignature() {
+        return signature;
+    }
+
+    public boolean isLocal() {
+        return local;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Collection<TypeMirror> getAllowedTypes() {
+        return allowedTypes;
+    }
+
+    public boolean matches(VariableElement variable) {
+        if (anyType) {
+            return true;
+        } else {
+            for (TypeMirror type : allowedTypes) {
+                if (ElementUtils.typeEquals(variable.asType(), type)) {
+                    return true;
+                }
+            }
+            if (allowSubclasses) {
+                for (TypeMirror type : allowedTypes) {
+                    if (ElementUtils.isSubtypeBoxed(ProcessorContext.getInstance(), variable.asType(), type)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toSignatureString(false);
+    }
+
+    public String toSignatureString(boolean typeOnly) {
+        StringBuilder builder = new StringBuilder();
+        if (typeDefinition != null) {
+            builder.append("<" + typeDefinition.getName() + ">");
+        } else if (getAllowedTypes().size() >= 1) {
+            builder.append(ElementUtils.getSimpleName(getAllowedTypes().iterator().next()));
+        } else {
+            builder.append("void");
+        }
+        if (!typeOnly) {
+            builder.append(" ");
+            builder.append(getName());
+        }
+        return builder.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ShortCircuitData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class ShortCircuitData extends TemplateMethod {
+
+    private ShortCircuitData genericShortCircuitMethod;
+    private final String valueName;
+
+    public ShortCircuitData(TemplateMethod template, String valueName) {
+        super(template);
+        this.valueName = valueName;
+    }
+
+    public String getValueName() {
+        return valueName;
+    }
+
+    public void setGenericShortCircuitMethod(ShortCircuitData genericShortCircuitMethod) {
+        this.genericShortCircuitMethod = genericShortCircuitMethod;
+    }
+
+    public boolean isGeneric() {
+        return genericShortCircuitMethod == null;
+    }
+
+    public ShortCircuitData getGeneric() {
+        if (isGeneric()) {
+            return this;
+        } else {
+            return genericShortCircuitMethod;
+        }
+    }
+
+    public boolean isCompatibleTo(SpecializationData specialization) {
+        if (isGeneric() && specialization.isFallback()) {
+            return true;
+        }
+
+        for (Parameter param : getParameters()) {
+            Parameter specializationParam = specialization.findParameter(param.getLocalName());
+            if (!ElementUtils.typeEquals(param.getType(), specializationParam.getType())) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public final class SpecializationData extends TemplateMethod {
+
+    public enum SpecializationKind {
+        UNINITIALIZED,
+        SPECIALIZED,
+        POLYMORPHIC,
+        FALLBACK
+    }
+
+    private final NodeData node;
+    private SpecializationKind kind;
+    private final List<SpecializationThrowsData> exceptions;
+    private List<GuardExpression> guards = Collections.emptyList();
+    private List<CacheExpression> caches = Collections.emptyList();
+    private List<AssumptionExpression> assumptionExpressions = Collections.emptyList();
+    private List<ShortCircuitData> shortCircuits;
+    private final Set<SpecializationData> contains = new TreeSet<>();
+    private final Set<String> containsNames = new TreeSet<>();
+    private final Set<SpecializationData> excludedBy = new TreeSet<>();
+    private String insertBeforeName;
+    private SpecializationData insertBefore;
+    private boolean reachable;
+    private int index;
+    private DSLExpression limitExpression;
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) {
+        super(template);
+        this.node = node;
+        this.kind = kind;
+        this.exceptions = exceptions;
+        this.index = template.getNaturalOrder();
+
+        for (SpecializationThrowsData exception : exceptions) {
+            exception.setSpecialization(this);
+        }
+    }
+
+    public boolean isCacheBoundByGuard(CacheExpression cacheExpression) {
+        for (GuardExpression expression : getGuards()) {
+            if (expression.getExpression().findBoundVariableElements().contains(cacheExpression.getParameter().getVariableElement())) {
+                return true;
+            }
+        }
+
+        // check all next binding caches if they are bound by guard
+        Set<VariableElement> boundVariables = cacheExpression.getExpression().findBoundVariableElements();
+        boolean found = false;
+        for (CacheExpression expression : getCaches()) {
+            if (cacheExpression == expression) {
+                found = true;
+            } else if (found) {
+                if (boundVariables.contains(expression.getParameter().getVariableElement())) {
+                    if (isCacheBoundByGuard(expression)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    public void setKind(SpecializationKind kind) {
+        this.kind = kind;
+    }
+
+    public boolean isDynamicParameterBound(DSLExpression expression) {
+        Set<VariableElement> boundVariables = expression.findBoundVariableElements();
+        for (Parameter parameter : getDynamicParameters()) {
+            if (boundVariables.contains(parameter.getVariableElement())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Parameter findByVariable(VariableElement variable) {
+        for (Parameter parameter : getParameters()) {
+            if (ElementUtils.variableEquals(parameter.getVariableElement(), variable)) {
+                return parameter;
+            }
+        }
+        return null;
+    }
+
+    public DSLExpression getLimitExpression() {
+        return limitExpression;
+    }
+
+    public void setLimitExpression(DSLExpression limitExpression) {
+        this.limitExpression = limitExpression;
+    }
+
+    public void setInsertBefore(SpecializationData insertBefore) {
+        this.insertBefore = insertBefore;
+    }
+
+    public void setInsertBeforeName(String insertBeforeName) {
+        this.insertBeforeName = insertBeforeName;
+    }
+
+    public SpecializationData getInsertBefore() {
+        return insertBefore;
+    }
+
+    public String getInsertBeforeName() {
+        return insertBeforeName;
+    }
+
+    public Set<String> getContainsNames() {
+        return containsNames;
+    }
+
+    public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) {
+        this(node, template, kind, new ArrayList<SpecializationThrowsData>());
+    }
+
+    public Set<SpecializationData> getContains() {
+        return contains;
+    }
+
+    public Set<SpecializationData> getExcludedBy() {
+        return excludedBy;
+    }
+
+    public void setReachable(boolean reachable) {
+        this.reachable = reachable;
+    }
+
+    public boolean isReachable() {
+        return reachable;
+    }
+
+    public boolean isPolymorphic() {
+        return kind == SpecializationKind.POLYMORPHIC;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (exceptions != null) {
+            sinks.addAll(exceptions);
+        }
+        if (guards != null) {
+            sinks.addAll(guards);
+        }
+        if (caches != null) {
+            sinks.addAll(caches);
+        }
+        if (assumptionExpressions != null) {
+            sinks.addAll(assumptionExpressions);
+        }
+        return sinks;
+    }
+
+    public boolean hasRewrite(ProcessorContext context) {
+        if (!getExceptions().isEmpty()) {
+            return true;
+        }
+        if (!getGuards().isEmpty()) {
+            return true;
+        }
+        if (!getAssumptionExpressions().isEmpty()) {
+            return true;
+        }
+
+        for (Parameter parameter : getSignatureParameters()) {
+            NodeChildData child = parameter.getSpecification().getExecution().getChild();
+            if (child != null) {
+                ExecutableTypeData type = child.findExecutableType(parameter.getType());
+                if (type == null) {
+                    type = child.findAnyGenericExecutableType(context);
+                }
+                if (type.hasUnexpectedValue(context)) {
+                    return true;
+                }
+                if (ElementUtils.needsCastTo(type.getReturnType(), parameter.getType())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int compareTo(TemplateMethod other) {
+        if (this == other) {
+            return 0;
+        } else if (!(other instanceof SpecializationData)) {
+            return super.compareTo(other);
+        }
+        SpecializationData m2 = (SpecializationData) other;
+        int kindOrder = kind.compareTo(m2.kind);
+        if (kindOrder != 0) {
+            return kindOrder;
+        }
+
+        int compare = 0;
+        int order1 = index;
+        int order2 = m2.index;
+        if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) {
+            compare = Integer.compare(order1, order2);
+            if (compare != 0) {
+                return compare;
+            }
+        }
+
+        return super.compareTo(other);
+    }
+
+    public void setIndex(int order) {
+        this.index = order;
+    }
+
+    public int getIndex() {
+        return index;
+    }
+
+    public NodeData getNode() {
+        return node;
+    }
+
+    public void setGuards(List<GuardExpression> guards) {
+        this.guards = guards;
+    }
+
+    public boolean isSpecialized() {
+        return kind == SpecializationKind.SPECIALIZED;
+    }
+
+    public boolean isFallback() {
+        return kind == SpecializationKind.FALLBACK;
+    }
+
+    public boolean isUninitialized() {
+        return kind == SpecializationKind.UNINITIALIZED;
+    }
+
+    public List<SpecializationThrowsData> getExceptions() {
+        return exceptions;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public void setShortCircuits(List<ShortCircuitData> shortCircuits) {
+        this.shortCircuits = shortCircuits;
+    }
+
+    public List<ShortCircuitData> getShortCircuits() {
+        return shortCircuits;
+    }
+
+    public SpecializationData findNextSpecialization() {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = 0; i < specializations.size() - 1; i++) {
+            if (specializations.get(i) == this) {
+                return specializations.get(i + 1);
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getDynamicTypes());
+    }
+
+    public boolean isFrameUsed() {
+        return getFrame() != null;
+    }
+
+    public List<CacheExpression> getCaches() {
+        return caches;
+    }
+
+    public void setCaches(List<CacheExpression> caches) {
+        this.caches = caches;
+    }
+
+    public void setAssumptionExpressions(List<AssumptionExpression> assumptionExpressions) {
+        this.assumptionExpressions = assumptionExpressions;
+    }
+
+    public List<AssumptionExpression> getAssumptionExpressions() {
+        return assumptionExpressions;
+    }
+
+    public boolean hasMultipleInstances() {
+        if (!getCaches().isEmpty()) {
+            for (GuardExpression guard : getGuards()) {
+                DSLExpression guardExpression = guard.getExpression();
+                Set<VariableElement> boundVariables = guardExpression.findBoundVariableElements();
+                if (isDynamicParameterBound(guardExpression)) {
+                    for (CacheExpression cache : getCaches()) {
+                        if (boundVariables.contains(cache.getParameter().getVariableElement())) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean isReachableAfter(SpecializationData prev) {
+        if (!prev.isSpecialized()) {
+            return true;
+        }
+
+        if (!prev.getExceptions().isEmpty()) {
+            // may get excluded by exception
+            return true;
+        }
+
+        if (hasMultipleInstances()) {
+            // may fallthrough due to limit
+            return true;
+        }
+
+        Iterator<Parameter> currentSignature = getSignatureParameters().iterator();
+        Iterator<Parameter> prevSignature = prev.getSignatureParameters().iterator();
+
+        TypeSystemData typeSystem = prev.getNode().getTypeSystem();
+        while (currentSignature.hasNext() && prevSignature.hasNext()) {
+            TypeMirror currentType = currentSignature.next().getType();
+            TypeMirror prevType = prevSignature.next().getType();
+
+            if (!typeSystem.isImplicitSubtypeOf(currentType, prevType)) {
+                return true;
+            }
+        }
+
+        if (!prev.getAssumptionExpressions().isEmpty()) {
+            // TODO: chumer: we could at least check reachability after trivial assumptions
+            // not sure if this is worth it.
+            return true;
+        }
+
+        Iterator<GuardExpression> prevGuards = prev.getGuards().iterator();
+        Iterator<GuardExpression> currentGuards = getGuards().iterator();
+        while (prevGuards.hasNext()) {
+            GuardExpression prevGuard = prevGuards.next();
+            GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null;
+            if (currentGuard == null || !currentGuard.implies(prevGuard)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public CacheExpression findCache(Parameter resolvedParameter) {
+        for (CacheExpression cache : getCaches()) {
+            if (cache.getParameter() == resolvedParameter) {
+                return cache;
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationThrowsData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class SpecializationThrowsData extends MessageContainer {
+
+    private final AnnotationValue annotationValue;
+    private final AnnotationMirror annotationMirror;
+    private final TypeMirror javaClass;
+    private SpecializationData specialization;
+
+    public SpecializationThrowsData(AnnotationMirror annotationMirror, AnnotationValue value, TypeMirror javaClass) {
+        this.annotationMirror = annotationMirror;
+        this.annotationValue = value;
+        this.javaClass = javaClass;
+    }
+
+    void setSpecialization(SpecializationData specialization) {
+        this.specialization = specialization;
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return specialization.getMessageElement();
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return annotationMirror;
+    }
+
+    @Override
+    public AnnotationValue getMessageAnnotationValue() {
+        return annotationValue;
+    }
+
+    public TypeMirror getJavaClass() {
+        return javaClass;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    public AnnotationMirror getAnnotationMirror() {
+        return annotationMirror;
+    }
+
+    public SpecializationData getTransitionTo() {
+        return specialization.findNextSpecialization();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/Template.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public abstract class Template extends MessageContainer {
+
+    private final ProcessorContext context;
+    private final TypeElement templateType;
+    private final AnnotationMirror annotation;
+
+    public Template(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation) {
+        this.context = context;
+        this.templateType = templateType;
+        this.annotation = annotation;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    @Override
+    public MessageContainer getBaseContainer() {
+        return this;
+    }
+
+    public abstract TypeSystemData getTypeSystem();
+
+    @Override
+    public Element getMessageElement() {
+        return templateType;
+    }
+
+    public String dump() {
+        return toString();
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public TypeElement getTemplateType() {
+        return templateType;
+    }
+
+    public AnnotationMirror getTemplateTypeAnnotation() {
+        return annotation;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + ElementUtils.getSimpleName(getTemplateType()) + "]";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.util.*;
+
+/**
+ * Note: this class has a natural ordering that is inconsistent with equals.
+ */
+public class TemplateMethod extends MessageContainer implements Comparable<TemplateMethod> {
+
+    public static final String FRAME_NAME = "frameValue";
+    public static final int NO_NATURAL_ORDER = -1;
+
+    private String id;
+    private final Template template;
+    private final int naturalOrder;
+    private final MethodSpec specification;
+    private final ExecutableElement method;
+    private final AnnotationMirror markerAnnotation;
+    private Parameter returnType;
+    private final List<Parameter> parameters;
+    private final Map<String, Parameter> parameterCache = new HashMap<>();
+
+    public TemplateMethod(String id, int naturalOrder, Template template, MethodSpec specification, ExecutableElement method, AnnotationMirror markerAnnotation, Parameter returnType,
+                    List<Parameter> parameters) {
+        this.template = template;
+        this.specification = specification;
+        this.naturalOrder = naturalOrder;
+        this.method = method;
+        this.markerAnnotation = markerAnnotation;
+        this.returnType = returnType;
+        this.parameters = new ArrayList<>();
+        for (Parameter param : parameters) {
+            Parameter newParam = new Parameter(param);
+            this.parameters.add(newParam);
+            newParam.setMethod(this);
+            parameterCache.put(param.getLocalName(), param);
+        }
+        if (returnType != null) {
+            parameterCache.put(returnType.getLocalName(), returnType);
+        }
+        this.id = id;
+    }
+
+    public final Parameter getFrame() {
+        return findParameter(FRAME_NAME);
+    }
+
+    public void removeParameter(Parameter p) {
+        this.parameters.remove(p);
+        this.parameterCache.remove(p.getLocalName());
+        p.setMethod(this);
+    }
+
+    public void addParameter(int index, Parameter p) {
+        this.parameters.add(index, p);
+        this.parameterCache.put(p.getLocalName(), p);
+        p.setMethod(this);
+    }
+
+    public String createReferenceName() {
+        if (getMethod() == null) {
+            return "-";
+        }
+        return ElementUtils.createReferenceName(getMethod());
+    }
+
+    public int getNaturalOrder() {
+        return naturalOrder;
+    }
+
+    public TemplateMethod(TemplateMethod method) {
+        this(method.id, method.naturalOrder, method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    public TemplateMethod(TemplateMethod method, ExecutableElement executable) {
+        this(method.id, method.naturalOrder, method.template, method.specification, executable, method.markerAnnotation, method.returnType, method.parameters);
+        getMessages().addAll(method.getMessages());
+    }
+
+    @Override
+    public Element getMessageElement() {
+        return method;
+    }
+
+    @Override
+    public AnnotationMirror getMessageAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        return Collections.emptyList();
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public MethodSpec getSpecification() {
+        return specification;
+    }
+
+    public Parameter getReturnType() {
+        return returnType;
+    }
+
+    public void replaceParameter(String localName, Parameter newParameter) {
+        if (returnType.getLocalName().equals(localName)) {
+            returnType = newParameter;
+        } else {
+            Parameter local = findParameter(localName);
+            int index = parameters.indexOf(local);
+            parameters.set(index, newParameter);
+        }
+        parameterCache.put(newParameter.getLocalName(), newParameter);
+        newParameter.setMethod(this);
+    }
+
+    public Iterable<Parameter> getDynamicParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
+            public boolean evaluate(Parameter value) {
+                return !value.getSpecification().isLocal() && !value.getSpecification().isAnnotated();
+            }
+        });
+    }
+
+    public Iterable<Parameter> getSignatureParameters() {
+        return new FilteredIterable<>(getParameters(), new Predicate<Parameter>() {
+            public boolean evaluate(Parameter value) {
+                return value.getSpecification().isSignature();
+            }
+        });
+    }
+
+    public List<Parameter> getParameters() {
+        return parameters;
+    }
+
+    public Parameter findParameterOrDie(NodeExecutionData execution) {
+        for (Parameter parameter : parameters) {
+            if (parameter.getSpecification().isSignature() && parameter.getSpecification().getExecution() == execution) {
+                return parameter;
+            }
+        }
+        throw new AssertionError("Could not find parameter for execution");
+    }
+
+    public List<Parameter> findByExecutionData(NodeExecutionData execution) {
+        List<Parameter> foundParameters = new ArrayList<>();
+        for (Parameter parameter : getParameters()) {
+            ParameterSpec spec = parameter.getSpecification();
+            if (spec != null && spec.getExecution() != null && spec.getExecution().equals(execution) && parameter.getSpecification().isSignature()) {
+                foundParameters.add(parameter);
+            }
+        }
+        return foundParameters;
+    }
+
+    public Parameter findParameter(String valueName) {
+        return parameterCache.get(valueName);
+    }
+
+    public List<Parameter> getReturnTypeAndParameters() {
+        List<Parameter> allParameters = new ArrayList<>(getParameters().size() + 1);
+        if (getReturnType() != null) {
+            allParameters.add(getReturnType());
+        }
+        allParameters.addAll(getParameters());
+        return Collections.unmodifiableList(allParameters);
+    }
+
+    public ExecutableElement getMethod() {
+        return method;
+    }
+
+    public String getMethodName() {
+        if (getMethod() != null) {
+            return getMethod().getSimpleName().toString();
+        } else {
+            return "$synthetic";
+        }
+    }
+
+    public AnnotationMirror getMarkerAnnotation() {
+        return markerAnnotation;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s [id = %s, method = %s]", getClass().getSimpleName(), getId(), getMethod());
+    }
+
+    public Parameter getPreviousParam(Parameter searchParam) {
+        Parameter prev = null;
+        for (Parameter param : getParameters()) {
+            if (param == searchParam) {
+                return prev;
+            }
+            prev = param;
+        }
+        return prev;
+    }
+
+    @SuppressWarnings("unused")
+    public int getSignatureSize() {
+        int signatureSize = 0;
+        for (Parameter parameter : getSignatureParameters()) {
+            signatureSize++;
+        }
+        return signatureSize;
+    }
+
+    public TypeSignature getTypeSignature() {
+        TypeSignature signature = new TypeSignature();
+        signature.types.add(getReturnType().getType());
+        for (Parameter parameter : getSignatureParameters()) {
+            TypeMirror typeData = parameter.getType();
+            if (typeData != null) {
+                signature.types.add(typeData);
+            }
+        }
+        return signature;
+    }
+
+    public void updateSignature(TypeSignature signature) {
+        // TODO(CH): fails in normal usage - output ok though
+        // assert signature.size() >= 1;
+
+        int signatureIndex = 0;
+        for (Parameter parameter : getReturnTypeAndParameters()) {
+            if (!parameter.getSpecification().isSignature()) {
+                continue;
+            }
+            if (signatureIndex >= signature.size()) {
+                break;
+            }
+            TypeMirror newType = signature.get(signatureIndex++);
+            if (!ElementUtils.typeEquals(newType, parameter.getType())) {
+                replaceParameter(parameter.getLocalName(), new Parameter(parameter, newType));
+            }
+        }
+    }
+
+    @Override
+    public int compareTo(TemplateMethod o) {
+        if (this == o) {
+            return 0;
+        }
+
+        int compare = compareBySignature(o);
+        if (compare == 0) {
+            // if signature sorting failed sort by id
+            compare = getId().compareTo(o.getId());
+        }
+        if (compare == 0) {
+            // if still no difference sort by enclosing type name
+            TypeElement enclosingType1 = ElementUtils.findNearestEnclosingType(getMethod());
+            TypeElement enclosingType2 = ElementUtils.findNearestEnclosingType(o.getMethod());
+            compare = enclosingType1.getQualifiedName().toString().compareTo(enclosingType2.getQualifiedName().toString());
+        }
+        return compare;
+    }
+
+    public int compareBySignature(TemplateMethod compareMethod) {
+        List<TypeMirror> signature1 = getDynamicTypes();
+        List<TypeMirror> signature2 = compareMethod.getDynamicTypes();
+
+        int result = 0;
+        for (int i = 0; i < Math.max(signature1.size(), signature2.size()); i++) {
+            TypeMirror t1 = i < signature1.size() ? signature1.get(i) : null;
+            TypeMirror t2 = i < signature2.size() ? signature2.get(i) : null;
+            result = ElementUtils.compareType(t1, t2);
+            if (result != 0) {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    public List<TypeMirror> getDynamicTypes() {
+        List<TypeMirror> types = new ArrayList<>();
+        for (Parameter param : getDynamicParameters()) {
+            types.add(param.getType());
+        }
+        return types;
+    }
+
+    public static class TypeSignature implements Iterable<TypeMirror> {
+
+        private final List<TypeMirror> types;
+
+        public TypeSignature() {
+            this.types = new ArrayList<>();
+        }
+
+        public TypeSignature(List<TypeMirror> signature) {
+            this.types = signature;
+        }
+
+        @Override
+        public int hashCode() {
+            return types.hashCode();
+        }
+
+        public int size() {
+            return types.size();
+        }
+
+        public TypeMirror get(int index) {
+            return types.get(index);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TypeSignature) {
+                return ((TypeSignature) obj).types.equals(types);
+            }
+            return super.equals(obj);
+        }
+
+        public Iterator<TypeMirror> iterator() {
+            return types.iterator();
+        }
+
+        @Override
+        public String toString() {
+            return types.toString();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCastData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+public class TypeCastData extends TemplateMethod {
+
+    private final TypeMirror targetType;
+    private final TypeMirror sourceType;
+
+    public TypeCastData(TemplateMethod method, TypeMirror sourceType, TypeMirror targetType) {
+        super(method);
+        this.sourceType = sourceType;
+        this.targetType = targetType;
+    }
+
+    public TypeMirror getSourceType() {
+        return sourceType;
+    }
+
+    public TypeMirror getTargetType() {
+        return targetType;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeCheckData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import javax.lang.model.type.*;
+
+public class TypeCheckData extends TemplateMethod {
+
+    private final TypeMirror checkedType;
+    private final TypeMirror valueType;
+
+    public TypeCheckData(TemplateMethod method, TypeMirror checkedType, TypeMirror valueType) {
+        super(method);
+        this.checkedType = checkedType;
+        this.valueType = valueType;
+    }
+
+    public TypeMirror getCheckedType() {
+        return checkedType;
+    }
+
+    public TypeMirror getValueType() {
+        return valueType;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.model;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+
+public class TypeSystemData extends Template {
+
+    private final List<ImplicitCastData> implicitCasts = new ArrayList<>();
+    private final List<TypeCastData> casts = new ArrayList<>();
+    private final List<TypeCheckData> checks = new ArrayList<>();
+    private final List<TypeMirror> legacyTypes = new ArrayList<>();
+
+    private Set<String> legacyTypeIds;
+
+    private final boolean isDefault;
+    private final DSLOptions options;
+
+    public TypeSystemData(ProcessorContext context, TypeElement templateType, AnnotationMirror annotation, DSLOptions options, boolean isDefault) {
+        super(context, templateType, annotation);
+        this.options = options;
+        this.isDefault = isDefault;
+    }
+
+    public boolean isDefault() {
+        return isDefault;
+    }
+
+    public DSLOptions getOptions() {
+        return options;
+    }
+
+    @Override
+    public TypeSystemData getTypeSystem() {
+        return this;
+    }
+
+    public List<TypeMirror> getLegacyTypes() {
+        return legacyTypes;
+    }
+
+    public TypeCastData getCast(TypeMirror targetType) {
+        for (TypeCastData cast : casts) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                return cast;
+            }
+        }
+        return null;
+    }
+
+    public TypeCheckData getCheck(TypeMirror type) {
+        for (TypeCheckData check : checks) {
+            if (ElementUtils.typeEquals(check.getCheckedType(), type)) {
+                return check;
+            }
+        }
+        return null;
+    }
+
+    public List<ImplicitCastData> getImplicitCasts() {
+        return implicitCasts;
+    }
+
+    public List<TypeCastData> getCasts() {
+        return casts;
+    }
+
+    public List<TypeCheckData> getChecks() {
+        return checks;
+    }
+
+    @Override
+    protected List<MessageContainer> findChildContainers() {
+        List<MessageContainer> sinks = new ArrayList<>();
+        if (checks != null) {
+            sinks.addAll(checks);
+        }
+        if (casts != null) {
+            sinks.addAll(casts);
+        }
+        if (implicitCasts != null) {
+            sinks.addAll(implicitCasts);
+        }
+        return sinks;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[template = " + ElementUtils.getSimpleName(getTemplateType()) + "]";
+    }
+
+    public List<ImplicitCastData> lookupByTargetType(TypeMirror targetType) {
+        if (getImplicitCasts() == null) {
+            return Collections.emptyList();
+        }
+        List<ImplicitCastData> foundCasts = new ArrayList<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                foundCasts.add(cast);
+            }
+        }
+        return foundCasts;
+    }
+
+    public ImplicitCastData lookupCast(TypeMirror sourceType, TypeMirror targetType) {
+        if (getImplicitCasts() == null) {
+            return null;
+        }
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (ElementUtils.typeEquals(cast.getSourceType(), sourceType) && ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                return cast;
+            }
+        }
+        return null;
+    }
+
+    public boolean hasImplicitSourceTypes(TypeMirror targetType) {
+        if (getImplicitCasts() == null) {
+            return false;
+        }
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public List<TypeMirror> lookupTargetTypes() {
+        List<TypeMirror> sourceTypes = new ArrayList<>();
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            sourceTypes.add(cast.getTargetType());
+        }
+        return ElementUtils.uniqueSortedTypes(sourceTypes, true);
+    }
+
+    public List<TypeMirror> lookupSourceTypes(TypeMirror targetType) {
+        List<TypeMirror> sourceTypes = new ArrayList<>();
+        sourceTypes.add(targetType);
+        for (ImplicitCastData cast : getImplicitCasts()) {
+            if (ElementUtils.typeEquals(cast.getTargetType(), targetType)) {
+                sourceTypes.add(cast.getSourceType());
+            }
+        }
+        return ElementUtils.uniqueSortedTypes(sourceTypes, true);
+    }
+
+    public boolean isImplicitSubtypeOf(TypeMirror source, TypeMirror target) {
+        List<ImplicitCastData> targetCasts = lookupByTargetType(target);
+        for (ImplicitCastData cast : targetCasts) {
+            if (ElementUtils.isSubtype(boxType(source), boxType(cast.getSourceType()))) {
+                return true;
+            }
+        }
+        return ElementUtils.isSubtype(boxType(source), boxType(target));
+    }
+
+    public TypeMirror boxType(TypeMirror type) {
+        return ElementUtils.boxType(getContext(), type);
+    }
+
+    public boolean hasType(TypeMirror type) {
+        if (legacyTypeIds == null) {
+            legacyTypeIds = new HashSet<>();
+            for (TypeMirror legacyType : legacyTypes) {
+                legacyTypeIds.add(ElementUtils.getTypeId(legacyType));
+            }
+        }
+        return legacyTypeIds.contains(ElementUtils.getTypeId(type));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/AbstractParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.MessageContainer.Message;
+
+/**
+ * THIS IS NOT PUBLIC API.
+ */
+public abstract class AbstractParser<M extends MessageContainer> {
+
+    protected final ProcessorContext context;
+    protected final ProcessingEnvironment processingEnv;
+
+    protected final Log log;
+
+    public AbstractParser() {
+        this.context = ProcessorContext.getInstance();
+        this.processingEnv = context.getEnvironment();
+        this.log = context.getLog();
+    }
+
+    public final M parse(Element element) {
+        M model = null;
+        try {
+            AnnotationMirror mirror = null;
+            if (getAnnotationType() != null) {
+                mirror = ElementUtils.findAnnotationMirror(processingEnv, element.getAnnotationMirrors(), getAnnotationType());
+            }
+
+            if (!context.getTruffleTypes().verify(context, element, mirror)) {
+                return null;
+            }
+            model = parse(element, mirror);
+            if (model == null) {
+                return null;
+            }
+
+            redirectMessages(new HashSet<MessageContainer>(), model, model);
+            model.emitMessages(context, log);
+            return filterErrorElements(model);
+        } catch (CompileErrorException e) {
+            log.message(Kind.WARNING, element, null, null, "The truffle processor could not parse class due to error: %s", e.getMessage());
+            return null;
+        }
+    }
+
+    private void redirectMessages(Set<MessageContainer> visitedSinks, MessageContainer model, MessageContainer baseContainer) {
+        List<Message> messages = model.getMessages();
+        for (int i = messages.size() - 1; i >= 0; i--) {
+            Message message = messages.get(i);
+            if (!ElementUtils.isEnclosedIn(baseContainer.getMessageElement(), message.getOriginalContainer().getMessageElement())) {
+                // redirect message
+                MessageContainer original = message.getOriginalContainer();
+                String text = wrapText(original.getMessageElement(), original.getMessageAnnotation(), message.getText());
+                Message redirectedMessage = new Message(null, null, baseContainer, text, message.getKind());
+                model.getMessages().remove(i);
+                baseContainer.getMessages().add(redirectedMessage);
+            }
+        }
+
+        for (MessageContainer childContainer : model) {
+            if (visitedSinks.contains(childContainer)) {
+                continue;
+            }
+            visitedSinks.add(childContainer);
+
+            MessageContainer newBase = baseContainer;
+            if (childContainer.getBaseContainer() != null) {
+                newBase = childContainer.getBaseContainer();
+            }
+            redirectMessages(visitedSinks, childContainer, newBase);
+        }
+    }
+
+    private static String wrapText(Element element, AnnotationMirror mirror, String text) {
+        StringBuilder b = new StringBuilder();
+        if (element != null) {
+            if (element.getKind() == ElementKind.METHOD) {
+                b.append("Method " + ElementUtils.createReferenceName((ExecutableElement) element));
+            } else {
+                b.append("Element " + element.getSimpleName());
+            }
+        }
+        if (mirror != null) {
+            b.append(" at annotation @" + ElementUtils.getSimpleName(mirror.getAnnotationType()).trim());
+        }
+
+        if (b.length() > 0) {
+            b.append(" is erroneous: ").append(text);
+            return b.toString();
+        } else {
+            return text;
+        }
+    }
+
+    protected M filterErrorElements(M model) {
+        return model.hasErrors() ? null : model;
+    }
+
+    protected abstract M parse(Element element, AnnotationMirror mirror);
+
+    public abstract Class<? extends Annotation> getAnnotationType();
+
+    public boolean isDelegateToRootDeclaredType() {
+        return false;
+    }
+
+    public List<Class<? extends Annotation>> getAllAnnotationTypes() {
+        List<Class<? extends Annotation>> list = new ArrayList<>();
+        if (getAnnotationType() != null) {
+            list.add(getAnnotationType());
+        }
+        list.addAll(getTypeDelegatedAnnotationTypes());
+        return list;
+    }
+
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return Collections.emptyList();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/CreateCastParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class CreateCastParser extends NodeMethodParser<CreateCastData> {
+
+    public CreateCastParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return CreateCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        NodeChildData foundChild = null;
+        for (String childName : childNames) {
+            foundChild = getNode().findChild(childName);
+            if (foundChild != null) {
+                break;
+            }
+        }
+        TypeMirror baseType = getContext().getTruffleTypes().getNode();
+        if (foundChild != null) {
+            baseType = foundChild.getOriginalType();
+        }
+
+        MethodSpec spec = new MethodSpec(new ParameterSpec("child", baseType));
+        addDefaultFieldMethodSpec(spec);
+        ParameterSpec childSpec = new ParameterSpec("castedChild", baseType);
+        childSpec.setSignature(true);
+        spec.addRequired(childSpec);
+        return spec;
+    }
+
+    @Override
+    public CreateCastData create(TemplateMethod method, boolean invalid) {
+        AnnotationMirror mirror = method.getMarkerAnnotation();
+        List<String> childNames = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
+        CreateCastData cast = new CreateCastData(method, childNames);
+        AnnotationValue value = ElementUtils.getAnnotationValue(mirror, "value");
+        TypeMirror type = null;
+        if (childNames == null || childNames.isEmpty()) {
+            cast.addError(value, "No value specified but required.");
+            return cast;
+        }
+
+        for (String childName : childNames) {
+            NodeChildData child = getNode().findChild(childName);
+            if (child == null) {
+                // error
+                cast.addError(value, "Specified child '%s' not found.", childName);
+                continue;
+            }
+            if (type == null) {
+                type = child.getNodeType();
+            } else if (!ElementUtils.typeEquals(type, child.getNodeType())) {
+                cast.addError(value, "All child nodes for a cast must have the same node type.");
+                continue;
+            }
+        }
+        return cast;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/FallbackParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class FallbackParser extends NodeMethodParser<SpecializationData> {
+
+    public FallbackParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        return createDefaultMethodSpec(method, mirror, true, null);
+    }
+
+    @Override
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec parameterSpec = super.createValueParameterSpec(execution);
+        parameterSpec.setAllowSubclasses(false);
+        return parameterSpec;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return new SpecializationData(getNode(), method, SpecializationKind.FALLBACK);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Fallback.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ImplicitCastParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ImplicitCastParser extends TypeSystemMethodParser<ImplicitCastData> {
+
+    public ImplicitCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ImplicitCast.class;
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = new MethodSpec(new ParameterSpec("target", getContext().getType(Object.class)));
+        spec.addRequired(new ParameterSpec("source", getContext().getType(Object.class))).setSignature(true);
+        return spec;
+    }
+
+    @Override
+    public ImplicitCastData create(TemplateMethod method, boolean invalid) {
+        if (invalid) {
+            return new ImplicitCastData(method, null, null);
+        }
+
+        Parameter target = method.findParameter("targetValue");
+        Parameter source = method.findParameter("sourceValue");
+
+        TypeMirror targetType = target.getType();
+        TypeMirror sourceType = source.getType();
+
+        if (ElementUtils.typeEquals(targetType, sourceType)) {
+            method.addError("Target type and source type of an @%s must not be the same type.", ImplicitCast.class.getSimpleName());
+        }
+
+        if (!method.getMethod().getModifiers().contains(Modifier.STATIC)) {
+            method.addError("@%s annotated method %s must be static.", ImplicitCast.class.getSimpleName(), method.getMethodName());
+        }
+
+        return new ImplicitCastData(method, sourceType, targetType);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public final class MethodSpecParser {
+
+    private boolean emitErrors = true;
+    private boolean useVarArgs = false;
+
+    private final Template template;
+
+    public MethodSpecParser(Template template) {
+        this.template = template;
+    }
+
+    public Template getTemplate() {
+        return template;
+    }
+
+    public boolean isEmitErrors() {
+        return emitErrors;
+    }
+
+    public boolean isUseVarArgs() {
+        return useVarArgs;
+    }
+
+    public void setEmitErrors(boolean emitErrors) {
+        this.emitErrors = emitErrors;
+    }
+
+    public void setUseVarArgs(boolean useVarArgs) {
+        this.useVarArgs = useVarArgs;
+    }
+
+    public TemplateMethod parse(MethodSpec methodSpecification, ExecutableElement method, AnnotationMirror annotation, int naturalOrder) {
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        methodSpecification.applyTypeDefinitions("types");
+
+        String id = method.getSimpleName().toString();
+        TypeMirror returnType = method.getReturnType();
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, method.getParameters());
+    }
+
+    public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
+                    List<? extends VariableElement> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, new CodeVariableElement(returnType, "returnType"), -1, -1);
+        if (returnTypeMirror == null) {
+            if (isEmitErrors() && method != null) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String expectedReturnType = returnTypeSpec.toSignatureString(true);
+                String actualReturnType = ElementUtils.getSimpleName(returnType);
+
+                String message = String.format("The provided return type \"%s\" does not match expected return type \"%s\".\nExpected signature: \n %s", actualReturnType, expectedReturnType,
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        List<Parameter> parameters = parseParameters(methodSpecification, parameterTypes, isUseVarArgs() && method != null ? method.isVarArgs() : false);
+        if (parameters == null) {
+            if (isEmitErrors() && method != null) {
+                TemplateMethod invalidMethod = new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList());
+                String message = String.format("Method signature %s does not match to the expected signature: \n%s", createActualSignature(method),
+                                methodSpecification.toSignatureString(method.getSimpleName().toString()));
+                invalidMethod.addError(message);
+                return invalidMethod;
+            } else {
+                return null;
+            }
+        }
+
+        return new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters);
+    }
+
+    private static String createActualSignature(ExecutableElement method) {
+        StringBuilder b = new StringBuilder("(");
+        String sep = "";
+        if (method != null) {
+            for (VariableElement var : method.getParameters()) {
+                b.append(sep);
+                b.append(ElementUtils.getSimpleName(var.asType()));
+                sep = ", ";
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    /*
+     * Parameter parsing tries to parse required arguments starting from offset 0 with increasing
+     * offset until it finds a signature end that matches the required specification. If there is no
+     * end matching the required arguments, parsing fails. Parameters prior to the parsed required
+     * ones are cut and used to parse the optional parameters.
+     */
+    private static List<Parameter> parseParameters(MethodSpec spec, List<? extends VariableElement> parameterTypes, boolean varArgs) {
+        List<Parameter> parsedRequired = null;
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<VariableElement> parameters = new ArrayList<>();
+            parameters.addAll(parameterTypes.subList(offset, parameterTypes.size()));
+            parsedRequired = parseParametersRequired(spec, parameters, varArgs);
+            if (parsedRequired != null) {
+                break;
+            }
+        }
+
+        if (parsedRequired == null) {
+            return null;
+        }
+
+        if (parsedRequired.isEmpty() && offset == 0) {
+            offset = parameterTypes.size();
+        }
+        List<? extends VariableElement> potentialOptionals = parameterTypes.subList(0, offset);
+        List<Parameter> parsedOptionals = parseParametersOptional(spec, potentialOptionals);
+        if (parsedOptionals == null) {
+            return null;
+        }
+
+        List<Parameter> finalParameters = new ArrayList<>();
+        finalParameters.addAll(parsedOptionals);
+        finalParameters.addAll(parsedRequired);
+        return finalParameters;
+    }
+
+    private static List<Parameter> parseParametersOptional(MethodSpec spec, List<? extends VariableElement> types) {
+        List<Parameter> parsedParams = new ArrayList<>();
+
+        int typeStartIndex = 0;
+        List<ParameterSpec> specifications = spec.getOptional();
+        outer: for (int specIndex = 0; specIndex < specifications.size(); specIndex++) {
+            ParameterSpec specification = specifications.get(specIndex);
+            for (int typeIndex = typeStartIndex; typeIndex < types.size(); typeIndex++) {
+                VariableElement variable = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, variable, -1, -1);
+                if (optionalParam != null) {
+                    parsedParams.add(optionalParam);
+                    typeStartIndex = typeIndex + 1;
+                    continue outer;
+                }
+            }
+        }
+
+        if (typeStartIndex < types.size()) {
+            // not enough types found
+            return null;
+        }
+        return parsedParams;
+    }
+
+    private static List<Parameter> parseParametersRequired(MethodSpec spec, List<VariableElement> types, boolean typeVarArgs) {
+        List<Parameter> parsedParams = new ArrayList<>();
+        List<ParameterSpec> specifications = spec.getRequired();
+        boolean specVarArgs = spec.isVariableRequiredParameters();
+        int typeIndex = 0;
+        int specificationIndex = 0;
+
+        ParameterSpec specification;
+        while ((specification = nextSpecification(specifications, specificationIndex, specVarArgs)) != null) {
+            VariableElement actualType = nextActualType(types, typeIndex, typeVarArgs);
+            if (actualType == null) {
+                if (spec.isIgnoreAdditionalSpecifications()) {
+                    break;
+                }
+                return null;
+            }
+
+            int typeVarArgsIndex = typeVarArgs ? typeIndex - types.size() + 1 : -1;
+            int specVarArgsIndex = specVarArgs ? specificationIndex - specifications.size() + 1 : -1;
+
+            if (typeVarArgsIndex >= 0 && specVarArgsIndex >= 0) {
+                // both specifications and types have a variable number of arguments
+                // we would get into an endless loop if we would continue
+                break;
+            }
+
+            Parameter resolvedParameter = matchParameter(specification, actualType, specVarArgsIndex, typeVarArgsIndex);
+            if (resolvedParameter == null) {
+                return null;
+            }
+            parsedParams.add(resolvedParameter);
+            typeIndex++;
+            specificationIndex++;
+        }
+
+        // consume randomly ordered annotated parameters
+        VariableElement variable;
+        while ((variable = nextActualType(types, typeIndex, typeVarArgs)) != null) {
+            Parameter matchedParamter = matchAnnotatedParameter(spec, variable);
+            if (matchedParamter == null) {
+                break;
+            }
+            parsedParams.add(matchedParamter);
+            typeIndex++;
+        }
+
+        if (typeIndex < types.size()) {
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
+            } else {
+                return null;
+            }
+        }
+
+        return parsedParams;
+    }
+
+    private static Parameter matchAnnotatedParameter(MethodSpec spec, VariableElement variable) {
+        for (ParameterSpec parameterSpec : spec.getAnnotations()) {
+            if (parameterSpec.matches(variable)) {
+                Parameter matchedParameter = matchParameter(parameterSpec, variable, -1, -1);
+                if (matchedParameter != null) {
+                    matchedParameter.setLocalName(variable.getSimpleName().toString());
+                    return matchedParameter;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static ParameterSpec nextSpecification(List<ParameterSpec> specifications, int specIndex, boolean varArgs) {
+        if (varArgs && specIndex >= specifications.size() - 1 && !specifications.isEmpty()) {
+            return specifications.get(specifications.size() - 1);
+        } else if (specIndex < specifications.size()) {
+            return specifications.get(specIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static VariableElement nextActualType(List<VariableElement> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            VariableElement actualType = types.get(types.size() - 1);
+            if (actualType.asType().getKind() == TypeKind.ARRAY) {
+                actualType = new CodeVariableElement(((ArrayType) actualType.asType()).getComponentType(), actualType.getSimpleName().toString());
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private static Parameter matchParameter(ParameterSpec specification, VariableElement variable, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = variable.asType();
+        if (hasError(resolvedType)) {
+            return null;
+        }
+
+        if (!specification.matches(variable)) {
+            return null;
+        }
+
+        return new Parameter(specification, variable, specificationIndex, varArgsIndex);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeMethodParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class NodeMethodParser<E extends TemplateMethod> extends TemplateMethodParser<NodeData, E> {
+
+    public NodeMethodParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+    }
+
+    public NodeData getNode() {
+        return template;
+    }
+
+    protected ParameterSpec createValueParameterSpec(NodeExecutionData execution) {
+        ParameterSpec spec = new ParameterSpec(execution.getName(), getPossibleParameterTypes(execution));
+        spec.setExecution(execution);
+        return spec;
+    }
+
+    protected Collection<TypeMirror> getPossibleParameterTypes(NodeExecutionData execution) {
+        return getNode().getGenericTypes(execution);
+    }
+
+    protected ParameterSpec createReturnParameterSpec() {
+        ParameterSpec returnValue = new ParameterSpec("returnValue", getPossibleReturnTypes());
+        returnValue.setExecution(getNode().getThisExecution());
+        return returnValue;
+    }
+
+    protected Collection<TypeMirror> getPossibleReturnTypes() {
+        return Arrays.asList(getNode().getGenericType(getNode().getThisExecution()));
+    }
+
+    @Override
+    public boolean isParsable(ExecutableElement method) {
+        if (getAnnotationType() != null) {
+            return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+        }
+
+        return true;
+    }
+
+    @SuppressWarnings("unused")
+    protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) {
+        MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec());
+
+        addDefaultFrame(methodSpec);
+        addDefaultFieldMethodSpec(methodSpec);
+        addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec);
+
+        return methodSpec;
+    }
+
+    private void addDefaultChildren(boolean shortCircuitsEnabled, String breakName, MethodSpec spec) {
+        if (getNode().getChildren() == null) {
+            // children are null when parsing executable types
+            return;
+        }
+
+        for (NodeExecutionData execution : getNode().getChildExecutions()) {
+            if (breakName != null && execution.getIndexedName().equals(breakName)) {
+                break;
+            }
+
+            if (execution.isShortCircuit() && shortCircuitsEnabled) {
+                spec.addRequired(new ParameterSpec(shortCircuitValueName(execution.getName()), getContext().getType(boolean.class)));
+            }
+            spec.addRequired(createValueParameterSpec(execution));
+        }
+    }
+
+    protected void addDefaultFrame(MethodSpec methodSpec) {
+        if (getNode().supportsFrame()) {
+            methodSpec.addOptional(new ParameterSpec("frame", getNode().getFrameType()));
+        }
+    }
+
+    protected void addDefaultFieldMethodSpec(MethodSpec methodSpec) {
+        for (NodeFieldData field : getNode().getFields()) {
+            if (field.getGetter() == null) {
+                ParameterSpec spec = new ParameterSpec(field.getName(), field.getType());
+                spec.setLocal(true);
+                methodSpec.addOptional(spec);
+            }
+        }
+    }
+
+    private static String shortCircuitValueName(String valueName) {
+        return "has" + ElementUtils.firstLetterUpperCase(valueName);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1680 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.expression.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.java.compiler.*;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.java.model.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+@DSLOptions
+public class NodeParser extends AbstractParser<NodeData> {
+
+    public static final List<Class<? extends Annotation>> ANNOTATIONS = Arrays.asList(Fallback.class, TypeSystemReference.class, ShortCircuit.class, Specialization.class, NodeChild.class,
+                    NodeChildren.class);
+
+    @Override
+    protected NodeData parse(Element element, AnnotationMirror mirror) {
+        NodeData node = parseRootType((TypeElement) element);
+        if (Log.isDebug() && node != null) {
+            String dump = node.dump();
+            log.message(Kind.ERROR, null, null, null, dump);
+        }
+        return node;
+    }
+
+    @Override
+    protected NodeData filterErrorElements(NodeData model) {
+        for (Iterator<NodeData> iterator = model.getEnclosingNodes().iterator(); iterator.hasNext();) {
+            NodeData node = filterErrorElements(iterator.next());
+            if (node == null) {
+                iterator.remove();
+            }
+        }
+        if (model.hasErrors()) {
+            return null;
+        }
+        return model;
+    }
+
+    @Override
+    public boolean isDelegateToRootDeclaredType() {
+        return true;
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    @Override
+    public List<Class<? extends Annotation>> getTypeDelegatedAnnotationTypes() {
+        return ANNOTATIONS;
+    }
+
+    private NodeData parseRootType(TypeElement rootType) {
+        List<NodeData> enclosedNodes = new ArrayList<>();
+        for (TypeElement enclosedType : ElementFilter.typesIn(rootType.getEnclosedElements())) {
+            NodeData enclosedChild = parseRootType(enclosedType);
+            if (enclosedChild != null) {
+                enclosedNodes.add(enclosedChild);
+            }
+        }
+        NodeData node;
+        try {
+            node = parseNode(rootType);
+        } catch (CompileErrorException e) {
+            throw e;
+        } catch (Throwable e) {
+            RuntimeException e2 = new RuntimeException(String.format("Parsing of Node %s failed.", ElementUtils.getQualifiedName(rootType)));
+            e2.addSuppressed(e);
+            throw e2;
+        }
+        if (node == null && !enclosedNodes.isEmpty()) {
+            node = new NodeData(context, rootType);
+        }
+
+        if (node != null) {
+            for (NodeData enclosedNode : enclosedNodes) {
+                node.addEnclosedNode(enclosedNode);
+            }
+        }
+        return node;
+    }
+
+    private NodeData parseNode(TypeElement originalTemplateType) {
+        // reloading the type elements is needed for ecj
+        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
+
+        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
+            // generated nodes should not get called again.
+            return null;
+        }
+
+        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
+            return null;
+        }
+
+        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
+        List<Element> members = loadMembers(templateType);
+        // ensure the processed element has at least one @Specialization annotation.
+        if (!containsSpecializations(members)) {
+            return null;
+        }
+
+        NodeData node = parseNodeData(templateType, lookupTypes);
+        if (node.hasErrors()) {
+            return node;
+        }
+
+        node.getFields().addAll(parseFields(lookupTypes, members));
+        node.getChildren().addAll(parseChildren(lookupTypes, members));
+        node.getChildExecutions().addAll(parseExecutions(node.getFields(), node.getChildren(), members));
+        node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, node.getSignatureSize(), context.getFrameTypes(), false));
+
+        initializeExecutableTypes(node);
+        initializeImportGuards(node, lookupTypes, members);
+        initializeChildren(node);
+
+        if (node.hasErrors()) {
+            return node; // error sync point
+        }
+
+        if (node.hasErrors()) {
+            return node; // error sync point
+        }
+
+        node.getSpecializations().addAll(new SpecializationMethodParser(context, node).parse(members));
+        node.getSpecializations().addAll(new FallbackParser(context, node).parse(members));
+        node.getCasts().addAll(new CreateCastParser(context, node).parse(members));
+        node.getShortCircuits().addAll(new ShortCircuitParser(context, node).parse(members));
+
+        if (node.hasErrors()) {
+            return node;  // error sync point
+        }
+        initializeSpecializations(members, node);
+        initializeExecutableTypeHierarchy(node);
+
+        verifySpecializationSameLength(node);
+        initializeShortCircuits(node); // requires specializations and polymorphic specializations
+
+        verifyVisibilities(node);
+        verifyMissingAbstractMethods(node, members);
+        verifyConstructors(node);
+        verifyNamingConvention(node.getShortCircuits(), "needs");
+        verifySpecializationThrows(node);
+        return node;
+    }
+
+    private static void initializeExecutableTypeHierarchy(NodeData node) {
+        SpecializationData polymorphic = node.getPolymorphicSpecialization();
+        if (polymorphic != null) {
+            boolean polymorphicSignatureFound = false;
+            List<TypeMirror> dynamicTypes = polymorphic.getDynamicTypes();
+            TypeMirror frame = null;
+            if (polymorphic.getFrame() != null) {
+                frame = dynamicTypes.remove(0);
+            }
+
+            ExecutableTypeData polymorphicType = new ExecutableTypeData(node, polymorphic.getReturnType().getType(), "execute", frame, dynamicTypes);
+            String genericName = ExecutableTypeData.createName(polymorphicType) + "_";
+            polymorphicType.setUniqueName(genericName);
+
+            for (ExecutableTypeData type : node.getExecutableTypes()) {
+                if (polymorphicType.sameSignature(type)) {
+                    polymorphicSignatureFound = true;
+                    break;
+                }
+            }
+
+            if (!polymorphicSignatureFound) {
+                node.getExecutableTypes().add(polymorphicType);
+            }
+        }
+
+        List<ExecutableTypeData> rootTypes = buildExecutableHierarchy(node);
+        List<ExecutableTypeData> additionalAbstractRootTypes = new ArrayList<>();
+        for (int i = 1; i < rootTypes.size(); i++) {
+            ExecutableTypeData rootType = rootTypes.get(i);
+            if (rootType.isAbstract()) {
+                // cannot implemement root
+                additionalAbstractRootTypes.add(rootType);
+            } else {
+                node.getExecutableTypes().remove(rootType);
+            }
+        }
+        if (!additionalAbstractRootTypes.isEmpty()) {
+            node.addError("Incompatible abstract execute methods found %s.", additionalAbstractRootTypes);
+        }
+
+        namesUnique(node.getExecutableTypes());
+
+    }
+
+    private static List<ExecutableTypeData> buildExecutableHierarchy(NodeData node) {
+        List<ExecutableTypeData> executes = node.getExecutableTypes();
+        if (executes.isEmpty()) {
+            return Collections.emptyList();
+        }
+        List<ExecutableTypeData> hierarchyExecutes = new ArrayList<>(executes);
+        Collections.sort(hierarchyExecutes);
+        ExecutableTypeData parent = hierarchyExecutes.get(0);
+        ListIterator<ExecutableTypeData> executesIterator = hierarchyExecutes.listIterator(1);
+        buildExecutableHierarchy(node, parent, executesIterator);
+        return hierarchyExecutes;
+    }
+
+    private static void buildExecutableHierarchy(NodeData node, ExecutableTypeData parent, ListIterator<ExecutableTypeData> executesIterator) {
+        while (executesIterator.hasNext()) {
+            ExecutableTypeData other = executesIterator.next();
+            if (other.canDelegateTo(parent)) {
+                parent.addDelegatedFrom(other);
+                executesIterator.remove();
+            }
+        }
+        for (int i = 1; i < parent.getDelegatedFrom().size(); i++) {
+            buildExecutableHierarchy(node, parent.getDelegatedFrom().get(i - 1), parent.getDelegatedFrom().listIterator(i));
+        }
+    }
+
+    private List<Element> loadMembers(TypeElement templateType) {
+        List<Element> members = new ArrayList<>(CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(context.getEnvironment(), templateType));
+
+        return members;
+    }
+
+    private boolean containsSpecializations(List<Element> elements) {
+        boolean foundSpecialization = false;
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            if (ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class) != null) {
+                foundSpecialization = true;
+                break;
+            }
+        }
+        return foundSpecialization;
+    }
+
+    private void initializeImportGuards(NodeData node, List<TypeElement> lookupTypes, List<Element> elements) {
+        for (TypeElement lookupType : lookupTypes) {
+            AnnotationMirror importAnnotation = ElementUtils.findAnnotationMirror(processingEnv, lookupType, ImportStatic.class);
+            if (importAnnotation == null) {
+                continue;
+            }
+            AnnotationValue importClassesValue = ElementUtils.getAnnotationValue(importAnnotation, "value");
+            List<TypeMirror> importClasses = ElementUtils.getAnnotationValueList(TypeMirror.class, importAnnotation, "value");
+            if (importClasses.isEmpty()) {
+                node.addError(importAnnotation, importClassesValue, "At least import guard classes must be specified.");
+                continue;
+            }
+            for (TypeMirror importGuardClass : importClasses) {
+                if (importGuardClass.getKind() != TypeKind.DECLARED) {
+                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' is not a declared type.", ElementUtils.getQualifiedName(importGuardClass));
+                    continue;
+                }
+
+                TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
+                if (typeElement.getEnclosingElement().getKind().isClass() && !typeElement.getModifiers().contains(Modifier.PUBLIC)) {
+                    node.addError(importAnnotation, importClassesValue, "The specified import guard class '%s' must be public.", ElementUtils.getQualifiedName(importGuardClass));
+                    continue;
+                }
+                elements.addAll(importPublicStaticMembers(typeElement, false));
+            }
+        }
+    }
+
+    private List<? extends Element> importPublicStaticMembers(TypeElement importGuardClass, boolean includeConstructors) {
+        // hack to reload type is necessary for incremental compiling in eclipse.
+        // otherwise methods inside of import guard types are just not found.
+        TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType()));
+
+        List<Element> members = new ArrayList<>();
+        for (Element importElement : processingEnv.getElementUtils().getAllMembers(typeElement)) {
+            if (!importElement.getModifiers().contains(Modifier.PUBLIC)) {
+                continue;
+            }
+
+            if (includeConstructors && importElement.getKind() == ElementKind.CONSTRUCTOR) {
+                members.add(importElement);
+            }
+
+            if (!importElement.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+
+            ElementKind kind = importElement.getKind();
+            if (kind.isField() || kind == ElementKind.METHOD) {
+                members.add(importElement);
+            }
+        }
+        return members;
+    }
+
+    private NodeData parseNodeData(TypeElement templateType, List<TypeElement> typeHierarchy) {
+        AnnotationMirror typeSystemMirror = findFirstAnnotation(typeHierarchy, TypeSystemReference.class);
+        TypeSystemData typeSystem = null;
+        if (typeSystemMirror != null) {
+            TypeMirror typeSystemType = ElementUtils.getAnnotationValue(TypeMirror.class, typeSystemMirror, "value");
+            typeSystem = (TypeSystemData) context.getTemplate(typeSystemType, true);
+            if (typeSystem == null) {
+                NodeData nodeData = new NodeData(context, templateType);
+                nodeData.addError("The used type system '%s' is invalid. Fix errors in the type system first.", ElementUtils.getQualifiedName(typeSystemType));
+                return nodeData;
+            }
+        } else {
+            // default dummy type system
+            typeSystem = new TypeSystemData(context, templateType, null, NodeParser.class.getAnnotation(DSLOptions.class), true);
+        }
+        AnnotationMirror nodeInfoMirror = findFirstAnnotation(typeHierarchy, NodeInfo.class);
+        String shortName = null;
+        if (nodeInfoMirror != null) {
+            shortName = ElementUtils.getAnnotationValue(String.class, nodeInfoMirror, "shortName");
+        }
+        boolean useNodeFactory = findFirstAnnotation(typeHierarchy, GenerateNodeFactory.class) != null;
+        return new NodeData(context, templateType, shortName, typeSystem, useNodeFactory);
+
+    }
+
+    private List<NodeFieldData> parseFields(List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> names = new HashSet<>();
+
+        List<NodeFieldData> fields = new ArrayList<>();
+        for (VariableElement field : ElementFilter.fieldsIn(elements)) {
+            if (field.getModifiers().contains(Modifier.STATIC)) {
+                continue;
+            }
+            if (field.getModifiers().contains(Modifier.PUBLIC) || field.getModifiers().contains(Modifier.PROTECTED)) {
+                String name = field.getSimpleName().toString();
+                fields.add(new NodeFieldData(field, null, field, false));
+                names.add(name);
+            }
+        }
+
+        List<TypeElement> reversedTypeHierarchy = new ArrayList<>(typeHierarchy);
+        Collections.reverse(reversedTypeHierarchy);
+        for (TypeElement typeElement : reversedTypeHierarchy) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, typeElement, NodeFields.class);
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", typeElement, NodeField.class);
+
+            for (AnnotationMirror mirror : children) {
+                String name = ElementUtils.firstLetterLowerCase(ElementUtils.getAnnotationValue(String.class, mirror, "name"));
+                TypeMirror type = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "type");
+
+                NodeFieldData field = new NodeFieldData(typeElement, mirror, new CodeVariableElement(type, name), true);
+                if (name.isEmpty()) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Field name cannot be empty.");
+                } else if (names.contains(name)) {
+                    field.addError(ElementUtils.getAnnotationValue(mirror, "name"), "Duplicate field name '%s'.", name);
+                }
+                names.add(name);
+
+                fields.add(field);
+            }
+        }
+
+        for (NodeFieldData nodeFieldData : fields) {
+            nodeFieldData.setGetter(findGetter(elements, nodeFieldData.getName(), nodeFieldData.getType()));
+        }
+
+        return fields;
+    }
+
+    private List<NodeChildData> parseChildren(final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
+        Set<String> shortCircuits = new HashSet<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+        Map<String, TypeMirror> castNodeTypes = new HashMap<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, CreateCast.class);
+            if (mirror != null) {
+                List<String> children = (ElementUtils.getAnnotationValueList(String.class, mirror, "value"));
+                if (children != null) {
+                    for (String child : children) {
+                        castNodeTypes.put(child, method.getReturnType());
+                    }
+                }
+            }
+        }
+
+        List<NodeChildData> parsedChildren = new ArrayList<>();
+        List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
+        Collections.reverse(typeHierarchyReversed);
+        for (TypeElement type : typeHierarchyReversed) {
+            AnnotationMirror nodeChildrenMirror = ElementUtils.findAnnotationMirror(processingEnv, type, NodeChildren.class);
+
+            TypeMirror nodeClassType = type.getSuperclass();
+            if (!ElementUtils.isAssignable(nodeClassType, context.getTruffleTypes().getNode())) {
+                nodeClassType = null;
+            }
+
+            List<AnnotationMirror> children = ElementUtils.collectAnnotations(context, nodeChildrenMirror, "value", type, NodeChild.class);
+            int index = 0;
+            for (AnnotationMirror childMirror : children) {
+                String name = ElementUtils.getAnnotationValue(String.class, childMirror, "value");
+                if (name.equals("")) {
+                    name = "child" + index;
+                }
+
+                Cardinality cardinality = Cardinality.ONE;
+
+                TypeMirror childType = inheritType(childMirror, "type", nodeClassType);
+                if (childType.getKind() == TypeKind.ARRAY) {
+                    cardinality = Cardinality.MANY;
+                }
+
+                TypeMirror originalChildType = childType;
+                TypeMirror castNodeType = castNodeTypes.get(name);
+                if (castNodeType != null) {
+                    childType = castNodeType;
+                }
+
+                Element getter = findGetter(elements, name, childType);
+                NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality);
+
+                parsedChildren.add(nodeChild);
+
+                if (nodeChild.getNodeType() == null) {
+                    nodeChild.addError("No valid node type could be resoleved.");
+                }
+                if (nodeChild.hasErrors()) {
+                    continue;
+                }
+
+                index++;
+            }
+        }
+
+        List<NodeChildData> filteredChildren = new ArrayList<>();
+        Set<String> encounteredNames = new HashSet<>();
+        for (int i = parsedChildren.size() - 1; i >= 0; i--) {
+            NodeChildData child = parsedChildren.get(i);
+            if (!encounteredNames.contains(child.getName())) {
+                filteredChildren.add(0, child);
+                encounteredNames.add(child.getName());
+            }
+        }
+
+        return filteredChildren;
+    }
+
+    private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
+        // pre-parse short circuits
+        Set<String> shortCircuits = new HashSet<>();
+        List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, ShortCircuit.class);
+            if (mirror != null) {
+                shortCircuits.add(ElementUtils.getAnnotationValue(String.class, mirror, "value"));
+            }
+        }
+
+        boolean hasVarArgs = false;
+        int maxSignatureSize = 0;
+        if (!children.isEmpty()) {
+            int lastIndex = children.size() - 1;
+            hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
+            if (hasVarArgs) {
+                maxSignatureSize = lastIndex;
+            } else {
+                maxSignatureSize = children.size();
+            }
+        }
+
+        List<NodeFieldData> nonGetterFields = new ArrayList<>();
+        for (NodeFieldData field : fields) {
+            if (field.getGetter() == null && field.isGenerated()) {
+                nonGetterFields.add(field);
+            }
+        }
+
+        TypeMirror cacheAnnotation = context.getType(Cached.class);
+        List<TypeMirror> frameTypes = context.getFrameTypes();
+        // pre-parse specializations to find signature size
+        for (ExecutableElement method : methods) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
+            if (mirror == null) {
+                continue;
+            }
+            int currentArgumentIndex = 0;
+            boolean skipShortCircuit = false;
+            parameter: for (VariableElement var : method.getParameters()) {
+                if (skipShortCircuit) {
+                    skipShortCircuit = false;
+                    continue parameter;
+                }
+
+                TypeMirror type = var.asType();
+                if (currentArgumentIndex == 0) {
+                    // skip optionals
+                    for (TypeMirror frameType : frameTypes) {
+                        if (ElementUtils.typeEquals(type, frameType)) {
+                            continue parameter;
+                        }
+                    }
+                }
+
+                if (currentArgumentIndex < nonGetterFields.size()) {
+                    for (NodeFieldData field : nonGetterFields) {
+                        if (ElementUtils.typeEquals(var.asType(), field.getType())) {
+                            continue parameter;
+                        }
+                    }
+                }
+
+                if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
+                    continue parameter;
+                }
+
+                int childIndex = currentArgumentIndex < children.size() ? currentArgumentIndex : children.size() - 1;
+                if (childIndex != -1) {
+                    NodeChildData child = children.get(childIndex);
+                    if (shortCircuits.contains(NodeExecutionData.createIndexedName(child, currentArgumentIndex - childIndex))) {
+                        skipShortCircuit = true;
+                    }
+                }
+
+                currentArgumentIndex++;
+            }
+            maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex);
+        }
+
+        List<NodeExecutionData> executions = new ArrayList<>();
+        for (int i = 0; i < maxSignatureSize; i++) {
+            boolean varArgParameter = false;
+            int childIndex = i;
+            if (i >= children.size() - 1) {
+                if (hasVarArgs) {
+                    varArgParameter = hasVarArgs;
+                    childIndex = Math.min(i, children.size() - 1);
+                } else if (i >= children.size()) {
+                    childIndex = -1;
+                }
+            }
+            int varArgsIndex = -1;
+            boolean shortCircuit = false;
+            NodeChildData child = null;
+            if (childIndex != -1) {
+                varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
+                child = children.get(childIndex);
+                shortCircuit = shortCircuits.contains(NodeExecutionData.createIndexedName(child, varArgsIndex));
+            }
+            executions.add(new NodeExecutionData(child, i, varArgsIndex, shortCircuit));
+        }
+        return executions;
+    }
+
+    private List<ExecutableTypeData> parseExecutableTypeData(NodeData node, List<? extends Element> elements, int signatureSize, List<TypeMirror> frameTypes, boolean includeFinals) {
+        List<ExecutableTypeData> typeData = new ArrayList<>();
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            Set<Modifier> modifiers = method.getModifiers();
+            if (modifiers.contains(Modifier.PRIVATE) || modifiers.contains(Modifier.STATIC)) {
+                continue;
+            }
+            if (!includeFinals && modifiers.contains(Modifier.FINAL)) {
+                continue;
+            }
+
+            if (!method.getSimpleName().toString().startsWith("execute")) {
+                continue;
+            }
+            if (ElementUtils.findAnnotationMirror(context.getEnvironment(), method, Specialization.class) != null) {
+                continue;
+            }
+
+            ExecutableTypeData executableType = new ExecutableTypeData(node, method, signatureSize, context.getFrameTypes());
+
+            if (executableType.getFrameParameter() != null) {
+                boolean supportedType = false;
+                for (TypeMirror type : frameTypes) {
+                    if (ElementUtils.isAssignable(type, executableType.getFrameParameter())) {
+                        supportedType = true;
+                        break;
+                    }
+                }
+                if (!supportedType) {
+                    continue;
+                }
+            }
+
+            typeData.add(executableType);
+        }
+
+        namesUnique(typeData);
+
+        return typeData;
+    }
+
+    private static void namesUnique(List<ExecutableTypeData> typeData) {
+        List<String> names = new ArrayList<>();
+        for (ExecutableTypeData type : typeData) {
+            names.add(type.getUniqueName());
+        }
+        while (renameDuplicateIds(names)) {
+            // fix point
+        }
+
+        for (int i = 0; i < typeData.size(); i++) {
+            typeData.get(i).setUniqueName(names.get(i));
+        }
+    }
+
+    private void initializeExecutableTypes(NodeData node) {
+        List<ExecutableTypeData> allExecutes = node.getExecutableTypes();
+
+        Set<String> inconsistentFrameTypes = new HashSet<>();
+        TypeMirror frameType = null;
+        for (ExecutableTypeData execute : allExecutes) {
+
+            TypeMirror frame = execute.getFrameParameter();
+            TypeMirror resolvedFrameType;
+            if (frame != null) {
+                resolvedFrameType = frame;
+                if (frameType == null) {
+                    frameType = resolvedFrameType;
+                } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
+                    // found inconsistent frame types
+                    inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType));
+                    inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType));
+                }
+            }
+        }
+        if (!inconsistentFrameTypes.isEmpty()) {
+            // ensure they are sorted somehow
+            List<String> inconsistentFrameTypesList = new ArrayList<>(inconsistentFrameTypes);
+            Collections.sort(inconsistentFrameTypesList);
+            node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList);
+        }
+        if (frameType == null) {
+            frameType = context.getType(void.class);
+        }
+
+        node.setFrameType(frameType);
+
+        boolean genericFound = false;
+        for (ExecutableTypeData type : node.getExecutableTypes()) {
+            if (!type.hasUnexpectedValue(context)) {
+                genericFound = true;
+                break;
+            }
+        }
+
+        // no generic executes
+        if (!genericFound) {
+            node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the "
+                            + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions.");
+        }
+
+        int nodeChildDeclarations = 0;
+        int nodeChildDeclarationsRequired = 0;
+        List<NodeExecutionData> executions = node.getChildExecutions();
+        for (NodeExecutionData execution : executions) {
+            if (execution.getChild() == null) {
+                nodeChildDeclarationsRequired = execution.getIndex() + 1;
+            } else {
+                nodeChildDeclarations++;
+            }
+        }
+
+        List<String> requireNodeChildDeclarations = new ArrayList<>();
+        for (ExecutableTypeData type : allExecutes) {
+            if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) {
+                requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod()));
+            }
+        }
+
+        if (!requireNodeChildDeclarations.isEmpty()) {
+            node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. "
+                            + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations);
+        }
+
+        if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) {
+            for (NodeChildData child : node.getChildren()) {
+                child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.");
+            }
+        }
+
+    }
+
+    private void initializeChildren(NodeData node) {
+        initializeExecuteWith(node);
+
+        for (NodeChildData child : node.getChildren()) {
+            TypeMirror nodeType = child.getNodeType();
+            NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType));
+
+            child.setNode(fieldNodeData);
+            if (fieldNodeData == null || fieldNodeData.hasErrors()) {
+                child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType));
+            } else {
+                List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
+                if (types.isEmpty()) {
+                    AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+                    child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(),
+                                    ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node)));
+                }
+            }
+        }
+    }
+
+    private static void initializeExecuteWith(NodeData node) {
+        for (NodeChildData child : node.getChildren()) {
+            List<String> executeWithStrings = ElementUtils.getAnnotationValueList(String.class, child.getMessageAnnotation(), "executeWith");
+            AnnotationValue executeWithValue = ElementUtils.getAnnotationValue(child.getMessageAnnotation(), "executeWith");
+            List<NodeExecutionData> executeWith = new ArrayList<>();
+            for (String executeWithString : executeWithStrings) {
+                if (child.getName().equals(executeWithString)) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with itself.", executeWithString);
+                    continue;
+                }
+                NodeExecutionData found = null;
+                boolean before = true;
+                for (NodeExecutionData resolveChild : node.getChildExecutions()) {
+                    if (resolveChild.getChild() == child) {
+                        before = false;
+                        continue;
+                    }
+                    if (resolveChild.getIndexedName().equals(executeWithString)) {
+                        found = resolveChild;
+                        break;
+                    }
+                }
+
+                if (found == null) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
+                    continue;
+                } else if (!before) {
+                    child.addError(executeWithValue, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString,
+                                    executeWithString);
+                    continue;
+                }
+                executeWith.add(found);
+            }
+            child.setExecuteWith(executeWith);
+        }
+    }
+
+    private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, TypeElement originalTemplateType) {
+        TypeElement templateType = ElementUtils.fromTypeMirror(context.reloadTypeElement(originalTemplateType));
+
+        if (ElementUtils.findAnnotationMirror(processingEnv, originalTemplateType, GeneratedBy.class) != null) {
+            // generated nodes should not get called again.
+            return null;
+        }
+
+        if (!ElementUtils.isAssignable(templateType.asType(), context.getTruffleTypes().getNode())) {
+            return null;
+        }
+
+        List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), templateType);
+
+        // Declaration order is not required for child nodes.
+        List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(templateType);
+        NodeData node = parseNodeData(templateType, lookupTypes);
+        if (node.hasErrors()) {
+            return node;
+        }
+        List<TypeMirror> frameTypes = Collections.emptyList();
+        if (parentNode.getFrameType() != null) {
+            frameTypes = Arrays.asList(parentNode.getFrameType());
+        }
+        node.getExecutableTypes().addAll(parseExecutableTypeData(node, members, child.getExecuteWith().size(), frameTypes, true));
+        node.setFrameType(parentNode.getFrameType());
+        return node;
+    }
+
+    private List<TypeMirror> createAllowedChildFrameTypes(NodeData parentNode) {
+        List<TypeMirror> allowedFrameTypes = new ArrayList<>();
+        for (TypeMirror frameType : context.getFrameTypes()) {
+            if (ElementUtils.isAssignable(parentNode.getFrameType(), frameType)) {
+                allowedFrameTypes.add(frameType);
+            }
+        }
+        return allowedFrameTypes;
+    }
+
+    private void initializeSpecializations(List<? extends Element> elements, final NodeData node) {
+        if (node.getSpecializations().isEmpty()) {
+            return;
+        }
+
+        initializeExpressions(elements, node);
+
+        if (node.hasErrors()) {
+            return;
+        }
+
+        initializeGeneric(node);
+        initializeUninitialized(node);
+        initializeOrder(node);
+        initializePolymorphism(node); // requires specializations
+        initializeReachability(node);
+        initializeContains(node);
+        resolveContains(node);
+
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (SpecializationData cur : specializations) {
+            for (SpecializationData contained : cur.getContains()) {
+                if (contained != cur) {
+                    contained.getExcludedBy().add(cur);
+                }
+            }
+        }
+
+        initializeSpecializationIdsWithMethodNames(node.getSpecializations());
+    }
+
+    private static void initializeOrder(NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        Collections.sort(specializations);
+
+        for (SpecializationData specialization : specializations) {
+            String searchName = specialization.getInsertBeforeName();
+            if (searchName == null || specialization.getMethod() == null) {
+                continue;
+            }
+            SpecializationData found = lookupSpecialization(node, searchName);
+            if (found == null || found.getMethod() == null) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "The referenced specialization '%s' could not be found.", searchName);
+                continue;
+            }
+
+            ExecutableElement currentMethod = specialization.getMethod();
+            ExecutableElement insertBeforeMethod = found.getMethod();
+
+            TypeMirror currentEnclosedType = currentMethod.getEnclosingElement().asType();
+            TypeMirror insertBeforeEnclosedType = insertBeforeMethod.getEnclosingElement().asType();
+
+            if (ElementUtils.typeEquals(currentEnclosedType, insertBeforeEnclosedType) || !ElementUtils.isSubtype(currentEnclosedType, insertBeforeEnclosedType)) {
+                AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "insertBefore");
+                specialization.addError(value, "Specializations can only be inserted before specializations in superclasses.", searchName);
+                continue;
+            }
+
+            specialization.setInsertBefore(found);
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            SpecializationData specialization = specializations.get(i);
+            SpecializationData insertBefore = specialization.getInsertBefore();
+            if (insertBefore != null) {
+                int insertIndex = specializations.indexOf(insertBefore);
+                if (insertIndex < i) {
+                    specializations.remove(i);
+                    specializations.add(insertIndex, specialization);
+                }
+            }
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            specializations.get(i).setIndex(i);
+        }
+    }
+
+    private static void initializeContains(NodeData node) {
+        for (SpecializationData specialization : node.getSpecializations()) {
+            Set<SpecializationData> resolvedSpecializations = specialization.getContains();
+            resolvedSpecializations.clear();
+            Set<String> includeNames = specialization.getContainsNames();
+            for (String includeName : includeNames) {
+                // TODO reduce complexity of this lookup.
+                SpecializationData foundSpecialization = lookupSpecialization(node, includeName);
+
+                if (foundSpecialization == null) {
+                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                    specialization.addError(value, "The referenced specialization '%s' could not be found.", includeName);
+                } else {
+                    if (foundSpecialization.compareTo(specialization) > 0) {
+                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                        if (foundSpecialization.compareTo(specialization) > 0) {
+                            specialization.addError(value, "The contained specialization '%s' must be declared before the containing specialization.", includeName);
+                        }
+
+                    }
+                    resolvedSpecializations.add(foundSpecialization);
+                }
+            }
+        }
+    }
+
+    private void resolveContains(NodeData node) {
+        // flatten transitive includes
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getContains().isEmpty()) {
+                continue;
+            }
+            Set<SpecializationData> foundSpecializations = new HashSet<>();
+            collectIncludes(specialization, foundSpecializations, new HashSet<SpecializationData>());
+            specialization.getContains().addAll(foundSpecializations);
+        }
+    }
+
+    private static SpecializationData lookupSpecialization(NodeData node, String includeName) {
+        SpecializationData foundSpecialization = null;
+        for (SpecializationData searchSpecialization : node.getSpecializations()) {
+            if (searchSpecialization.getMethodName().equals(includeName)) {
+                foundSpecialization = searchSpecialization;
+                break;
+            }
+        }
+        return foundSpecialization;
+    }
+
+    private void collectIncludes(SpecializationData specialization, Set<SpecializationData> found, Set<SpecializationData> visited) {
+        if (visited.contains(specialization)) {
+            // circle found
+            specialization.addError("Circular contained specialization '%s' found.", specialization.createReferenceName());
+            return;
+        }
+        visited.add(specialization);
+
+        for (SpecializationData included : specialization.getContains()) {
+            collectIncludes(included, found, new HashSet<>(visited));
+            found.add(included);
+        }
+    }
+
+    private static void initializeReachability(final NodeData node) {
+        List<SpecializationData> specializations = node.getSpecializations();
+        for (int i = specializations.size() - 1; i >= 0; i--) {
+            SpecializationData current = specializations.get(i);
+            if (current.isPolymorphic()) {
+                current.setReachable(true);
+                continue;
+            }
+
+            List<SpecializationData> shadowedBy = null;
+            for (int j = i - 1; j >= 0; j--) {
+                SpecializationData prev = specializations.get(j);
+                if (prev.isPolymorphic()) {
+                    continue;
+                }
+                if (!current.isReachableAfter(prev)) {
+                    if (shadowedBy == null) {
+                        shadowedBy = new ArrayList<>();
+                    }
+                    shadowedBy.add(prev);
+                }
+            }
+
+            if (shadowedBy != null) {
+                StringBuilder name = new StringBuilder();
+                String sep = "";
+                for (SpecializationData shadowSpecialization : shadowedBy) {
+                    name.append(sep);
+                    name.append(shadowSpecialization.createReferenceName());
+                    sep = ", ";
+                }
+                current.addError("%s is not reachable. It is shadowed by %s.", current.isFallback() ? "Generic" : "Specialization", name);
+            }
+            current.setReachable(shadowedBy == null);
+        }
+    }
+
+    private static void initializeSpecializationIdsWithMethodNames(List<SpecializationData> specializations) {
+        List<String> signatures = new ArrayList<>();
+        for (SpecializationData specialization : specializations) {
+            if (specialization.isFallback()) {
+                signatures.add("Fallback");
+            } else if (specialization.isUninitialized()) {
+                signatures.add("Uninitialized");
+            } else if (specialization.isPolymorphic()) {
+                signatures.add("Polymorphic");
+            } else {
+                String name = specialization.getMethodName();
+
+                // hack for name clashes with BaseNode.
+                if (name.equalsIgnoreCase("base")) {
+                    name = name + "0";
+                } else if (name.startsWith("do")) {
+                    String filteredDo = name.substring(2, name.length());
+                    if (!filteredDo.isEmpty() && Character.isJavaIdentifierStart(filteredDo.charAt(0))) {
+                        name = filteredDo;
+                    }
+                }
+                signatures.add(ElementUtils.firstLetterUpperCase(name));
+            }
+        }
+
+        while (renameDuplicateIds(signatures)) {
+            // fix point
+        }
+
+        for (int i = 0; i < specializations.size(); i++) {
+            specializations.get(i).setId(signatures.get(i));
+        }
+    }
+
+    private static boolean renameDuplicateIds(List<String> signatures) {
+        boolean changed = false;
+        Map<String, Integer> counts = new HashMap<>();
+        for (String s1 : signatures) {
+            Integer count = counts.get(s1.toLowerCase());
+            if (count == null) {
+                count = 0;
+            }
+            count++;
+            counts.put(s1.toLowerCase(), count);
+        }
+
+        for (String s : counts.keySet()) {
+            int count = counts.get(s);
+            if (count > 1) {
+                changed = true;
+                int number = 0;
+                for (ListIterator<String> iterator = signatures.listIterator(); iterator.hasNext();) {
+                    String s2 = iterator.next();
+                    if (s.equalsIgnoreCase(s2)) {
+                        iterator.set(s2 + number);
+                        number++;
+                    }
+                }
+            }
+        }
+        return changed;
+    }
+
+    private void initializeExpressions(List<? extends Element> elements, NodeData node) {
+        List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements);
+
+        List<VariableElement> fields = new ArrayList<>();
+        for (NodeFieldData field : node.getFields()) {
+            fields.add(field.getVariable());
+        }
+
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getMethod() == null) {
+                continue;
+            }
+
+            List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size());
+            for (Parameter p : specialization.getParameters()) {
+                specializationMembers.add(p.getVariableElement());
+            }
+            specializationMembers.addAll(fields);
+            specializationMembers.addAll(members);
+            DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers);
+
+            initializeCaches(specialization, resolver);
+            initializeGuards(specialization, resolver);
+            if (specialization.hasErrors()) {
+                continue;
+            }
+            initializeLimit(specialization, resolver);
+            initializeAssumptions(specialization, resolver);
+        }
+    }
+
+    private void initializeAssumptions(SpecializationData specialization, DSLExpressionResolver resolver) {
+        final DeclaredType assumptionType = context.getDeclaredType(Assumption.class);
+        final TypeMirror assumptionArrayType = new ArrayCodeTypeMirror(assumptionType);
+        final List<String> assumptionDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "assumptions");
+        List<AssumptionExpression> assumptionExpressions = new ArrayList<>();
+        int assumptionId = 0;
+        for (String assumption : assumptionDefinitions) {
+            AssumptionExpression assumptionExpression;
+            DSLExpression expression = null;
+            try {
+                expression = DSLExpression.parse(assumption);
+                expression.accept(resolver);
+                assumptionExpression = new AssumptionExpression(specialization, expression, "assumption" + assumptionId);
+                if (!ElementUtils.isAssignable(expression.getResolvedType(), assumptionType) && !ElementUtils.isAssignable(expression.getResolvedType(), assumptionArrayType)) {
+                    assumptionExpression.addError("Incompatible return type %s. Assumptions must be assignable to %s or %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
+                                    ElementUtils.getSimpleName(assumptionType), ElementUtils.getSimpleName(assumptionArrayType));
+                }
+                if (specialization.isDynamicParameterBound(expression)) {
+                    specialization.addError("Assumption expressions must not bind dynamic parameter values.");
+                }
+            } catch (InvalidExpressionException e) {
+                assumptionExpression = new AssumptionExpression(specialization, null, "assumption" + assumptionId);
+                assumptionExpression.addError("Error parsing expression '%s': %s", assumption, e.getMessage());
+            }
+            assumptionExpressions.add(assumptionExpression);
+        }
+        specialization.setAssumptionExpressions(assumptionExpressions);
+    }
+
+    private void initializeLimit(SpecializationData specialization, DSLExpressionResolver resolver) {
+        AnnotationValue annotationValue = ElementUtils.getAnnotationValue(specialization.getMessageAnnotation(), "limit");
+
+        String limitValue;
+        if (annotationValue == null) {
+            limitValue = "";
+        } else {
+            limitValue = (String) annotationValue.getValue();
+        }
+        if (limitValue.isEmpty()) {
+            limitValue = "3";
+        } else if (!specialization.hasMultipleInstances()) {
+            specialization.addWarning(annotationValue, "The limit expression has no effect. Multiple specialization instantiations are impossible for this specialization.");
+            return;
+        }
+
+        TypeMirror expectedType = context.getType(int.class);
+        try {
+            DSLExpression expression = DSLExpression.parse(limitValue);
+            expression.accept(resolver);
+            if (!ElementUtils.typeEquals(expression.getResolvedType(), expectedType)) {
+                specialization.addError(annotationValue, "Incompatible return type %s. Limit expressions must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
+                                ElementUtils.getSimpleName(expectedType));
+            }
+            if (specialization.isDynamicParameterBound(expression)) {
+                specialization.addError(annotationValue, "Limit expressions must not bind dynamic parameter values.");
+            }
+
+            specialization.setLimitExpression(expression);
+        } catch (InvalidExpressionException e) {
+            specialization.addError(annotationValue, "Error parsing expression '%s': %s", limitValue, e.getMessage());
+        }
+    }
+
+    private void initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) {
+        TypeMirror cacheMirror = context.getType(Cached.class);
+        List<CacheExpression> expressions = new ArrayList<>();
+        for (Parameter parameter : specialization.getParameters()) {
+            AnnotationMirror annotationMirror = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cacheMirror);
+            if (annotationMirror != null) {
+                String initializer = ElementUtils.getAnnotationValue(String.class, annotationMirror, "value");
+
+                TypeMirror parameterType = parameter.getType();
+
+                DSLExpressionResolver localResolver = resolver;
+                if (parameterType.getKind() == TypeKind.DECLARED) {
+                    localResolver = localResolver.copy(importPublicStaticMembers(ElementUtils.fromTypeMirror(parameterType), true));
+                }
+
+                CacheExpression cacheExpression;
+                DSLExpression expression = null;
+                try {
+                    expression = DSLExpression.parse(initializer);
+                    expression.accept(localResolver);
+                    cacheExpression = new CacheExpression(parameter, annotationMirror, expression);
+                    if (!ElementUtils.typeEquals(expression.getResolvedType(), parameter.getType())) {
+                        cacheExpression.addError("Incompatible return type %s. The expression type must be equal to the parameter type %s.", ElementUtils.getSimpleName(expression.getResolvedType()),
+                                        ElementUtils.getSimpleName(parameter.getType()));
+                    }
+                } catch (InvalidExpressionException e) {
+                    cacheExpression = new CacheExpression(parameter, annotationMirror, null);
+                    cacheExpression.addError("Error parsing expression '%s': %s", initializer, e.getMessage());
+                }
+                expressions.add(cacheExpression);
+            }
+        }
+        specialization.setCaches(expressions);
+
+        if (specialization.hasErrors()) {
+            return;
+        }
+
+        // verify that cache expressions are bound in the correct order.
+        for (int i = 0; i < expressions.size(); i++) {
+            CacheExpression currentExpression = expressions.get(i);
+            Set<VariableElement> boundVariables = currentExpression.getExpression().findBoundVariableElements();
+            for (int j = i + 1; j < expressions.size(); j++) {
+                CacheExpression boundExpression = expressions.get(j);
+                if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) {
+                    currentExpression.addError("The initializer expression of parameter '%s' binds unitialized parameter '%s. Reorder the parameters to resolve the problem.",
+                                    currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName());
+                    break;
+                }
+            }
+        }
+    }
+
+    private void initializeGuards(SpecializationData specialization, DSLExpressionResolver resolver) {
+        final TypeMirror booleanType = context.getType(boolean.class);
+        List<String> guardDefinitions = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
+        List<GuardExpression> guardExpressions = new ArrayList<>();
+        for (String guard : guardDefinitions) {
+            GuardExpression guardExpression;
+            DSLExpression expression = null;
+            try {
+                expression = DSLExpression.parse(guard);
+                expression.accept(resolver);
+                guardExpression = new GuardExpression(specialization, expression);
+                if (!ElementUtils.typeEquals(expression.getResolvedType(), booleanType)) {
+                    guardExpression.addError("Incompatible return type %s. Guards must return %s.", ElementUtils.getSimpleName(expression.getResolvedType()), ElementUtils.getSimpleName(booleanType));
+                }
+            } catch (InvalidExpressionException e) {
+                guardExpression = new GuardExpression(specialization, null);
+                guardExpression.addError("Error parsing expression '%s': %s", guard, e.getMessage());
+            }
+            guardExpressions.add(guardExpression);
+        }
+        specialization.setGuards(guardExpressions);
+    }
+
+    private static List<Element> filterNotAccessibleElements(TypeElement templateType, List<? extends Element> elements) {
+        String packageName = ElementUtils.getPackageName(templateType);
+        List<Element> filteredElements = new ArrayList<>(elements);
+        for (Element element : elements) {
+            Modifier visibility = ElementUtils.getVisibility(element.getModifiers());
+            if (visibility == Modifier.PRIVATE) {
+                continue;
+            } else if (visibility == null) {
+                String elementPackageName = ElementUtils.getPackageName(element.getEnclosingElement().asType());
+                if (!Objects.equals(packageName, elementPackageName) && !elementPackageName.equals("java.lang")) {
+                    continue;
+                }
+            }
+
+            filteredElements.add(element);
+        }
+        return filteredElements;
+    }
+
+    private void initializeGeneric(final NodeData node) {
+        List<SpecializationData> generics = new ArrayList<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            if (spec.isFallback()) {
+                generics.add(spec);
+            }
+        }
+
+        if (generics.size() == 1 && node.getSpecializations().size() == 1) {
+            // TODO this limitation should be lifted
+            for (SpecializationData generic : generics) {
+                generic.addError("@%s defined but no @%s.", Fallback.class.getSimpleName(), Specialization.class.getSimpleName());
+            }
+        }
+
+        if (generics.isEmpty()) {
+            node.getSpecializations().add(createGenericSpecialization(node));
+        } else {
+            if (generics.size() > 1) {
+                for (SpecializationData generic : generics) {
+                    generic.addError("Only one @%s is allowed per operation.", Fallback.class.getSimpleName());
+                }
+            }
+        }
+    }
+
+    private SpecializationData createGenericSpecialization(final NodeData node) {
+        FallbackParser parser = new FallbackParser(context, node);
+        MethodSpec specification = parser.createDefaultMethodSpec(node.getSpecializations().iterator().next().getMethod(), null, true, null);
+
+        List<VariableElement> parameterTypes = new ArrayList<>();
+        int signatureIndex = 1;
+        for (ParameterSpec spec : specification.getRequired()) {
+            parameterTypes.add(new CodeVariableElement(createGenericType(node, spec), "arg" + signatureIndex));
+            if (spec.isSignature()) {
+                signatureIndex++;
+            }
+        }
+
+        TypeMirror returnType = createGenericType(node, specification.getReturnType());
+        SpecializationData generic = parser.create("Generic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, parameterTypes);
+        if (generic == null) {
+            throw new RuntimeException("Unable to create generic signature for node " + node.getNodeId() + " with " + parameterTypes + ". Specification " + specification + ".");
+        }
+
+        return generic;
+    }
+
+    private TypeMirror createGenericType(NodeData node, ParameterSpec spec) {
+        NodeExecutionData execution = spec.getExecution();
+        Collection<TypeMirror> allowedTypes;
+        if (execution == null) {
+            allowedTypes = spec.getAllowedTypes();
+        } else {
+            allowedTypes = Arrays.asList(node.getGenericType(execution));
+        }
+        if (allowedTypes.size() == 1) {
+            return allowedTypes.iterator().next();
+        } else {
+            return ElementUtils.getCommonSuperType(context, allowedTypes);
+        }
+    }
+
+    private static void initializeUninitialized(final NodeData node) {
+        SpecializationData generic = node.getGenericSpecialization();
+        if (generic == null) {
+            return;
+        }
+        TemplateMethod uninializedMethod = new TemplateMethod("Uninitialized", -1, node, generic.getSpecification(), null, null, generic.getReturnType(), generic.getParameters());
+        // should not use messages from generic specialization
+        uninializedMethod.getMessages().clear();
+        node.getSpecializations().add(new SpecializationData(node, uninializedMethod, SpecializationKind.UNINITIALIZED));
+    }
+
+    private void initializePolymorphism(NodeData node) {
+        if (!node.needsRewrites(context)) {
+            return;
+        }
+
+        SpecializationData generic = node.getGenericSpecialization();
+        List<VariableElement> types = new ArrayList<>();
+
+        Collection<TypeMirror> frameTypes = new HashSet<>();
+        for (SpecializationData specialization : node.getSpecializations()) {
+            if (specialization.getFrame() != null) {
+                frameTypes.add(specialization.getFrame().getType());
+            }
+        }
+        if (node.supportsFrame()) {
+            frameTypes.add(node.getFrameType());
+        }
+
+        if (!frameTypes.isEmpty()) {
+            frameTypes = ElementUtils.uniqueSortedTypes(frameTypes, false);
+            TypeMirror frameType;
+            if (frameTypes.size() == 1) {
+                frameType = frameTypes.iterator().next();
+            } else {
+                frameType = context.getType(Frame.class);
+            }
+            types.add(new CodeVariableElement(frameType, TemplateMethod.FRAME_NAME));
+        }
+
+        TypeMirror returnType = null;
+        int index = 0;
+        for (Parameter genericParameter : generic.getReturnTypeAndParameters()) {
+            TypeMirror polymorphicType;
+            if (genericParameter.getLocalName().equals(TemplateMethod.FRAME_NAME)) {
+                continue;
+            }
+            boolean isReturnParameter = genericParameter == generic.getReturnType();
+            if (!genericParameter.getSpecification().isSignature()) {
+                polymorphicType = genericParameter.getType();
+            } else {
+                Collection<TypeMirror> usedTypes = new HashSet<>();
+                for (SpecializationData specialization : node.getSpecializations()) {
+                    if (specialization.isUninitialized()) {
+                        continue;
+                    }
+                    Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
+                    if (parameter == specialization.getReturnType() && specialization.isFallback() && specialization.getMethod() == null) {
+                        continue;
+                    }
+                    if (parameter == null) {
+                        throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
+                    }
+                    usedTypes.add(parameter.getType());
+                }
+                usedTypes = ElementUtils.uniqueSortedTypes(usedTypes, false);
+
+                if (usedTypes.size() == 1) {
+                    polymorphicType = usedTypes.iterator().next();
+                } else {
+                    polymorphicType = ElementUtils.getCommonSuperType(context, usedTypes);
+                }
+
+                NodeExecutionData execution = genericParameter.getSpecification().getExecution();
+                if (execution != null && !ElementUtils.isSubtypeBoxed(context, polymorphicType, node.getGenericType(execution))) {
+                    throw new AssertionError(String.format("Polymorphic types %s not compatible to generic type %s.", polymorphicType, node.getGenericType(execution)));
+                }
+
+            }
+            if (isReturnParameter) {
+                returnType = polymorphicType;
+            } else {
+                types.add(new CodeVariableElement(polymorphicType, "param" + index));
+            }
+            index++;
+        }
+
+        SpecializationMethodParser parser = new SpecializationMethodParser(context, node);
+        SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types);
+        if (polymorphic == null) {
+            throw new AssertionError("Failed to parse polymorphic signature. " + parser.createDefaultMethodSpec(null, null, false, null) + " Types: " + returnType + " - " + types);
+        }
+
+        polymorphic.setKind(SpecializationKind.POLYMORPHIC);
+        node.getSpecializations().add(polymorphic);
+    }
+
+    private void initializeShortCircuits(NodeData node) {
+        Map<String, List<ShortCircuitData>> groupedShortCircuits = groupShortCircuits(node.getShortCircuits());
+
+        boolean valid = true;
+        List<NodeExecutionData> shortCircuitExecutions = new ArrayList<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (!execution.isShortCircuit()) {
+                continue;
+            }
+            shortCircuitExecutions.add(execution);
+            String valueName = execution.getIndexedName();
+            List<ShortCircuitData> availableCircuits = groupedShortCircuits.get(valueName);
+
+            if (availableCircuits == null || availableCircuits.isEmpty()) {
+                node.addError("@%s method for short cut value '%s' required.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            boolean sameMethodName = true;
+            String methodName = availableCircuits.get(0).getMethodName();
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (!circuit.getMethodName().equals(methodName)) {
+                    sameMethodName = false;
+                }
+            }
+
+            if (!sameMethodName) {
+                for (ShortCircuitData circuit : availableCircuits) {
+                    circuit.addError("All short circuits for short cut value '%s' must have the same method name.", valueName);
+                }
+                valid = false;
+                continue;
+            }
+
+            ShortCircuitData genericCircuit = null;
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (isGenericShortCutMethod(circuit)) {
+                    genericCircuit = circuit;
+                    break;
+                }
+            }
+
+            if (genericCircuit == null) {
+                node.addError("No generic @%s method available for short cut value '%s'.", ShortCircuit.class.getSimpleName(), valueName);
+                valid = false;
+                continue;
+            }
+
+            for (ShortCircuitData circuit : availableCircuits) {
+                if (circuit != genericCircuit) {
+                    circuit.setGenericShortCircuitMethod(genericCircuit);
+                }
+            }
+        }
+
+        if (!valid) {
+            return;
+        }
+
+        List<SpecializationData> specializations = new ArrayList<>();
+        specializations.addAll(node.getSpecializations());
+        for (SpecializationData specialization : specializations) {
+            List<ShortCircuitData> assignedShortCuts = new ArrayList<>(shortCircuitExecutions.size());
+
+            for (NodeExecutionData shortCircuit : shortCircuitExecutions) {
+                List<ShortCircuitData> availableShortCuts = groupedShortCircuits.get(shortCircuit.getIndexedName());
+
+                ShortCircuitData genericShortCircuit = null;
+                ShortCircuitData compatibleShortCircuit = null;
+                for (ShortCircuitData circuit : availableShortCuts) {
+                    if (circuit.isGeneric()) {
+                        genericShortCircuit = circuit;
+                    } else if (circuit.isCompatibleTo(specialization)) {
+                        compatibleShortCircuit = circuit;
+                    }
+                }
+
+                if (compatibleShortCircuit == null) {
+                    compatibleShortCircuit = genericShortCircuit;
+                }
+                assignedShortCuts.add(compatibleShortCircuit);
+            }
+            specialization.setShortCircuits(assignedShortCuts);
+        }
+    }
+
+    private boolean isGenericShortCutMethod(ShortCircuitData method) {
+        for (Parameter parameter : method.getParameters()) {
+            NodeExecutionData execution = parameter.getSpecification().getExecution();
+            if (execution == null) {
+                continue;
+            }
+            ExecutableTypeData found = null;
+            List<ExecutableTypeData> executableElements = execution.getChild().findGenericExecutableTypes(context);
+            for (ExecutableTypeData executable : executableElements) {
+                if (ElementUtils.typeEquals(executable.getReturnType(), parameter.getType())) {
+                    found = executable;
+                    break;
+                }
+            }
+            if (found == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static Map<String, List<ShortCircuitData>> groupShortCircuits(List<ShortCircuitData> shortCircuits) {
+        Map<String, List<ShortCircuitData>> group = new HashMap<>();
+        for (ShortCircuitData shortCircuit : shortCircuits) {
+            List<ShortCircuitData> circuits = group.get(shortCircuit.getValueName());
+            if (circuits == null) {
+                circuits = new ArrayList<>();
+                group.put(shortCircuit.getValueName(), circuits);
+            }
+            circuits.add(shortCircuit);
+        }
+        return group;
+    }
+
+    private static boolean verifySpecializationSameLength(NodeData nodeData) {
+        int lastArgs = -1;
+        for (SpecializationData specializationData : nodeData.getSpecializations()) {
+            int signatureArgs = specializationData.getSignatureSize();
+            if (lastArgs == signatureArgs) {
+                continue;
+            }
+            if (lastArgs != -1) {
+                for (SpecializationData specialization : nodeData.getSpecializations()) {
+                    specialization.addError("All specializations must have the same number of arguments.");
+                }
+                return false;
+            } else {
+                lastArgs = signatureArgs;
+            }
+        }
+        return true;
+    }
+
+    private static void verifyVisibilities(NodeData node) {
+        if (node.getTemplateType().getModifiers().contains(Modifier.PRIVATE) && node.getSpecializations().size() > 0) {
+            node.addError("Classes containing a @%s annotation must not be private.", Specialization.class.getSimpleName());
+        }
+    }
+
+    private static void verifyMissingAbstractMethods(NodeData nodeData, List<? extends Element> originalElements) {
+        if (!nodeData.needsFactory()) {
+            // missing abstract methods only needs to be implemented
+            // if we need go generate factory for it.
+            return;
+        }
+
+        List<Element> elements = new ArrayList<>(originalElements);
+        Set<Element> unusedElements = new HashSet<>(elements);
+        for (ExecutableElement method : nodeData.getAllTemplateMethods()) {
+            unusedElements.remove(method);
+        }
+
+        for (NodeFieldData field : nodeData.getFields()) {
+            if (field.getGetter() != null) {
+                unusedElements.remove(field.getGetter());
+            }
+        }
+
+        for (NodeChildData child : nodeData.getChildren()) {
+            if (child.getAccessElement() != null) {
+                unusedElements.remove(child.getAccessElement());
+            }
+        }
+
+        for (ExecutableElement unusedMethod : ElementFilter.methodsIn(unusedElements)) {
+            if (unusedMethod.getModifiers().contains(Modifier.ABSTRACT)) {
+                nodeData.addError("The type %s must implement the inherited abstract method %s.", ElementUtils.getSimpleName(nodeData.getTemplateType()),
+                                ElementUtils.getReadableSignature(unusedMethod));
+            }
+        }
+    }
+
+    private static void verifyNamingConvention(List<? extends TemplateMethod> methods, String prefix) {
+        for (int i = 0; i < methods.size(); i++) {
+            TemplateMethod m1 = methods.get(i);
+            if (m1.getMethodName().length() < 3 || !m1.getMethodName().startsWith(prefix)) {
+                m1.addError("Naming convention: method name must start with '%s'.", prefix);
+            }
+        }
+    }
+
+    private static void verifySpecializationThrows(NodeData node) {
+        Map<String, SpecializationData> specializationMap = new HashMap<>();
+        for (SpecializationData spec : node.getSpecializations()) {
+            specializationMap.put(spec.getMethodName(), spec);
+        }
+        for (SpecializationData sourceSpecialization : node.getSpecializations()) {
+            if (sourceSpecialization.getExceptions() != null) {
+                for (SpecializationThrowsData throwsData : sourceSpecialization.getExceptions()) {
+                    for (SpecializationThrowsData otherThrowsData : sourceSpecialization.getExceptions()) {
+                        if (otherThrowsData != throwsData && ElementUtils.typeEquals(otherThrowsData.getJavaClass(), throwsData.getJavaClass())) {
+                            throwsData.addError("Duplicate exception type.");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static void verifyConstructors(NodeData nodeData) {
+        List<ExecutableElement> constructors = ElementFilter.constructorsIn(nodeData.getTemplateType().getEnclosedElements());
+        if (constructors.isEmpty()) {
+            return;
+        }
+
+        boolean oneNonPrivate = false;
+        for (ExecutableElement constructor : constructors) {
+            if (ElementUtils.getVisibility(constructor.getModifiers()) != Modifier.PRIVATE) {
+                oneNonPrivate = true;
+                break;
+            }
+        }
+        if (!oneNonPrivate && !nodeData.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) {
+            nodeData.addError("At least one constructor must be non-private.");
+        }
+    }
+
+    private AnnotationMirror findFirstAnnotation(List<? extends Element> elements, Class<? extends Annotation> annotation) {
+        for (Element element : elements) {
+            AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, element, annotation);
+            if (mirror != null) {
+                return mirror;
+            }
+        }
+        return null;
+    }
+
+    private TypeMirror inheritType(AnnotationMirror annotation, String valueName, TypeMirror parentType) {
+        TypeMirror inhertNodeType = context.getTruffleTypes().getNode();
+        TypeMirror value = ElementUtils.getAnnotationValue(TypeMirror.class, annotation, valueName);
+        if (ElementUtils.typeEquals(inhertNodeType, value)) {
+            return parentType;
+        } else {
+            return value;
+        }
+    }
+
+    private ExecutableElement findGetter(List<? extends Element> elements, String variableName, TypeMirror type) {
+        if (type == null) {
+            return null;
+        }
+        String methodName;
+        if (ElementUtils.typeEquals(type, context.getType(boolean.class))) {
+            methodName = "is" + ElementUtils.firstLetterUpperCase(variableName);
+        } else {
+            methodName = "get" + ElementUtils.firstLetterUpperCase(variableName);
+        }
+
+        for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
+            if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && ElementUtils.isAssignable(type, method.getReturnType())) {
+                return method;
+            }
+        }
+        return null;
+    }
+
+    private static List<TypeElement> collectSuperClasses(List<TypeElement> collection, TypeElement element) {
+        if (element != null) {
+            collection.add(element);
+            if (element.getSuperclass() != null) {
+                collectSuperClasses(collection, ElementUtils.fromTypeMirror(element.getSuperclass()));
+            }
+        }
+        return collection;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ShortCircuitParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public class ShortCircuitParser extends NodeMethodParser<ShortCircuitData> {
+
+    private final Set<String> shortCircuitValues;
+
+    public ShortCircuitParser(ProcessorContext context, NodeData node) {
+        super(context, node);
+
+        shortCircuitValues = new HashSet<>();
+        for (NodeExecutionData execution : node.getChildExecutions()) {
+            if (execution.isShortCircuit()) {
+                shortCircuitValues.add(execution.getIndexedName());
+            }
+        }
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, mirror, "value");
+
+        return createDefaultMethodSpec(method, mirror, true, shortCircuitValue);
+    }
+
+    @Override
+    protected ParameterSpec createReturnParameterSpec() {
+        return new ParameterSpec("has", getContext().getType(boolean.class));
+    }
+
+    @Override
+    public ShortCircuitData create(TemplateMethod method, boolean invalid) {
+        String shortCircuitValue = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "value");
+
+        if (!shortCircuitValues.contains(shortCircuitValue)) {
+            method.addError("Invalid short circuit value %s.", shortCircuitValue);
+        }
+
+        return new ShortCircuitData(method, shortCircuitValue);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return ShortCircuit.class;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.util.*;
+
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
+
+/**
+ * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
+ * and generic execute methods.
+ */
+public final class SpecializationGroup {
+
+    private final List<TypeGuard> typeGuards;
+    private final List<GuardExpression> guards;
+
+    private final NodeData node;
+    private final SpecializationData specialization;
+    private final List<SpecializationGroup> children = new ArrayList<>();
+
+    private SpecializationGroup parent;
+
+    private SpecializationGroup(SpecializationData data) {
+        this.node = data.getNode();
+        this.typeGuards = new ArrayList<>();
+        this.guards = new ArrayList<>();
+        this.specialization = data;
+
+        TypeSignature sig = data.getTypeSignature();
+        for (int i = 1; i < sig.size(); i++) {
+            typeGuards.add(new TypeGuard(sig.get(i), i - 1));
+        }
+        this.guards.addAll(data.getGuards());
+    }
+
+    public SpecializationGroup(List<SpecializationGroup> children, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
+        assert !children.isEmpty() : "children must not be empty";
+        this.typeGuards = typeGuardsMatches;
+        this.guards = guardMatches;
+        this.node = children.get(0).node;
+        this.specialization = null;
+        updateChildren(children);
+    }
+
+    public List<TypeGuard> getAllGuards() {
+        List<TypeGuard> collectedGuards = new ArrayList<>();
+        collectedGuards.addAll(typeGuards);
+        if (parent != null) {
+            collectedGuards.addAll(parent.getAllGuards());
+        }
+        return collectedGuards;
+    }
+
+    public List<GuardExpression> findElseConnectableGuards() {
+        if (!getTypeGuards().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        if (getGuards().isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<GuardExpression> elseConnectableGuards = new ArrayList<>();
+        int guardIndex = 0;
+        while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
+            elseConnectableGuards.add(getGuards().get(guardIndex));
+            guardIndex++;
+        }
+
+        return elseConnectableGuards;
+    }
+
+    private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
+        SpecializationGroup previous = this.getPreviousGroup();
+        if (previous == null) {
+            return null;
+        }
+        List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
+
+        if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
+            return null;
+        }
+
+        /* Guard is else branch can be connected in previous specialization. */
+        if (elseConnectedGuards.contains(guard)) {
+            return guard;
+        }
+
+        GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
+        if (guard.equalsNegated(previousGuard)) {
+            return guard;
+        }
+        return null;
+    }
+
+    private void updateChildren(List<SpecializationGroup> childs) {
+        if (!children.isEmpty()) {
+            children.clear();
+        }
+        this.children.addAll(childs);
+        for (SpecializationGroup child : childs) {
+            child.parent = this;
+        }
+    }
+
+    public SpecializationGroup getParent() {
+        return parent;
+    }
+
+    public List<TypeGuard> getTypeGuards() {
+        return typeGuards;
+    }
+
+    public List<GuardExpression> getGuards() {
+        return guards;
+    }
+
+    public List<SpecializationGroup> getChildren() {
+        return children;
+    }
+
+    public SpecializationData getSpecialization() {
+        return specialization;
+    }
+
+    private static SpecializationGroup combine(List<SpecializationGroup> groups) {
+        if (groups.isEmpty()) {
+            throw new IllegalArgumentException("empty combinations");
+        }
+        if (groups.size() == 1) {
+            return null;
+        }
+
+        List<TypeGuard> typeGuardsMatches = new ArrayList<>();
+        List<GuardExpression> guardMatches = new ArrayList<>();
+
+        SpecializationGroup first = groups.get(0);
+        List<SpecializationGroup> others = groups.subList(1, groups.size());
+
+        outer: for (TypeGuard typeGuard : first.typeGuards) {
+            for (SpecializationGroup other : others) {
+                if (!other.typeGuards.contains(typeGuard)) {
+                    // type guards can be combined unordered
+                    continue outer;
+                }
+            }
+            typeGuardsMatches.add(typeGuard);
+        }
+
+        outer: for (GuardExpression guard : first.guards) {
+            for (SpecializationGroup other : others) {
+                if (!other.guards.contains(guard)) {
+                    // we must break here. One guard may depend on the other.
+                    break outer;
+                }
+            }
+            guardMatches.add(guard);
+        }
+
+        // check for guards for required type casts
+        for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
+            GuardExpression guardMatch = iterator.next();
+            if (!guardMatch.getExpression().findBoundVariables().isEmpty()) {
+                iterator.remove();
+            }
+            // TODO we need to be smarter here with bound parameters.
+        }
+
+        if (typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
+            return null;
+        }
+
+        for (SpecializationGroup group : groups) {
+            group.typeGuards.removeAll(typeGuardsMatches);
+            group.guards.removeAll(guardMatches);
+        }
+
+        List<SpecializationGroup> newChildren = new ArrayList<>(groups);
+        return new SpecializationGroup(newChildren, typeGuardsMatches, guardMatches);
+    }
+
+    public static SpecializationGroup create(SpecializationData specialization) {
+        return new SpecializationGroup(specialization);
+    }
+
+    public static SpecializationGroup create(List<SpecializationData> specializations) {
+        List<SpecializationGroup> groups = new ArrayList<>();
+        for (SpecializationData specialization : specializations) {
+            groups.add(new SpecializationGroup(specialization));
+        }
+        return new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
+    }
+
+    @Override
+    public String toString() {
+        return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]";
+    }
+
+    private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
+        if (groups.size() <= 1) {
+            return groups;
+        }
+        List<SpecializationGroup> newGroups = new ArrayList<>();
+
+        int i = 0;
+        for (i = 0; i < groups.size();) {
+            SpecializationGroup combined = null;
+            for (int j = groups.size(); j > i + 1; j--) {
+                combined = combine(groups.subList(i, j));
+                if (combined != null) {
+                    break;
+                }
+            }
+            SpecializationGroup newGroup;
+            if (combined == null) {
+                newGroup = groups.get(i);
+                i++;
+            } else {
+                newGroup = combined;
+                List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
+                combined.updateChildren(createCombinationalGroups(originalGroups));
+                i += originalGroups.size();
+            }
+
+            newGroups.add(newGroup);
+
+        }
+
+        return newGroups;
+    }
+
+    public SpecializationGroup getPreviousGroup() {
+        if (parent == null || parent.children.isEmpty()) {
+            return null;
+        }
+        int index = parent.children.indexOf(this);
+        if (index <= 0) {
+            return null;
+        }
+        return parent.children.get(index - 1);
+    }
+
+    public int getUncheckedSpecializationIndex() {
+        int groupMaxIndex = getMaxSpecializationIndex();
+
+        int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
+        if (groupMaxIndex >= genericIndex) {
+            // no minimum state check for an generic index
+            groupMaxIndex = -1;
+        }
+
+        if (groupMaxIndex > -1) {
+            // no minimum state check if already checked by parent group
+            int parentMaxIndex = -1;
+            if (getParent() != null) {
+                parentMaxIndex = getParent().getMaxSpecializationIndex();
+            }
+            if (groupMaxIndex == parentMaxIndex) {
+                groupMaxIndex = -1;
+            }
+        }
+        return groupMaxIndex;
+    }
+
+    public int getMaxSpecializationIndex() {
+        if (specialization != null) {
+            return specialization.getNode().getSpecializations().indexOf(specialization);
+        } else {
+            int max = Integer.MIN_VALUE;
+            for (SpecializationGroup childGroup : getChildren()) {
+                max = Math.max(max, childGroup.getMaxSpecializationIndex());
+            }
+            return max;
+        }
+    }
+
+    public static final class TypeGuard {
+
+        private final int signatureIndex;
+        private final TypeMirror type;
+
+        public TypeGuard(TypeMirror type, int signatureIndex) {
+            this.type = type;
+            this.signatureIndex = signatureIndex;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + signatureIndex;
+            result = prime * result + type.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            } else if (obj == null) {
+                return false;
+            } else if (getClass() != obj.getClass()) {
+                return false;
+            }
+
+            TypeGuard other = (TypeGuard) obj;
+            if (signatureIndex != other.signatureIndex) {
+                return false;
+            } else if (!type.equals(other.type)) {
+                return false;
+            }
+            return true;
+        }
+
+        public int getSignatureIndex() {
+            return signatureIndex;
+        }
+
+        public TypeMirror getType() {
+            return type;
+        }
+    }
+
+    public SpecializationGroup getPrevious() {
+        if (getParent() == null) {
+            return null;
+        }
+
+        List<SpecializationGroup> parentChildren = getParent().getChildren();
+        int index = parentChildren.indexOf(this);
+        if (index <= 0) {
+            return null;
+        }
+        return parentChildren.get(index - 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+import com.oracle.truffle.dsl.processor.model.SpecializationData.SpecializationKind;
+
+public class SpecializationMethodParser extends NodeMethodParser<SpecializationData> {
+
+    public SpecializationMethodParser(ProcessorContext context, NodeData operation) {
+        super(context, operation);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
+        spec.getAnnotations().add(new AnnotatedParameterSpec(getContext().getDeclaredType(Cached.class)));
+        return spec;
+    }
+
+    @Override
+    public SpecializationData create(TemplateMethod method, boolean invalid) {
+        return parseSpecialization(method);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return Specialization.class;
+    }
+
+    private SpecializationData parseSpecialization(TemplateMethod method) {
+        List<SpecializationThrowsData> exceptionData = new ArrayList<>();
+        if (method.getMethod() != null) {
+            AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
+            List<TypeMirror> exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
+            List<TypeMirror> rewriteOnTypes = new ArrayList<>();
+            for (TypeMirror exceptionType : exceptionTypes) {
+                SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
+                if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
+                    method.addError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @%s method must specify a throws clause with the exception type '%s'.",
+                                    Specialization.class.getSimpleName(), ElementUtils.getQualifiedName(exceptionType));
+                }
+                rewriteOnTypes.add(throwsData.getJavaClass());
+                exceptionData.add(throwsData);
+            }
+
+            for (TypeMirror typeMirror : method.getMethod().getThrownTypes()) {
+                if (!ElementUtils.canThrowType(rewriteOnTypes, typeMirror)) {
+                    method.addError(rewriteValue, "A checked exception '%s' is thrown but is not specified using the rewriteOn property. "
+                                    + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.",
+                                    ElementUtils.getQualifiedName(typeMirror));
+                }
+            }
+
+            Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {
+
+                @Override
+                public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
+                    return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
+                }
+            });
+        }
+        SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData);
+
+        if (method.getMethod() != null) {
+            String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
+            if (!insertBeforeName.equals("")) {
+                specialization.setInsertBeforeName(insertBeforeName);
+            }
+
+            List<String> containsDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains");
+            Set<String> containsNames = specialization.getContainsNames();
+            containsNames.clear();
+            if (containsDefs != null) {
+                for (String include : containsDefs) {
+                    if (!containsNames.contains(include)) {
+                        specialization.getContainsNames().add(include);
+                    } else {
+                        AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
+                        specialization.addError(value, "Duplicate contains declaration '%s'.", include);
+                    }
+                }
+
+            }
+        }
+
+        return specialization;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
+
+    protected final T template;
+    private final ProcessorContext context;
+    private final MethodSpecParser parser;
+
+    private boolean parseNullOnError;
+
+    public TemplateMethodParser(ProcessorContext context, T template) {
+        this.template = template;
+        this.context = context;
+        this.parser = new MethodSpecParser(template);
+    }
+
+    public void setParseNullOnError(boolean parseNullOnError) {
+        this.parseNullOnError = parseNullOnError;
+    }
+
+    public boolean isParseNullOnError() {
+        return parseNullOnError;
+    }
+
+    public MethodSpecParser getParser() {
+        return parser;
+    }
+
+    public ProcessorContext getContext() {
+        return context;
+    }
+
+    public TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    public abstract MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror);
+
+    public abstract E create(TemplateMethod method, boolean invalid);
+
+    public abstract boolean isParsable(ExecutableElement method);
+
+    public Class<? extends Annotation> getAnnotationType() {
+        return null;
+    }
+
+    public final List<E> parse(List<? extends Element> elements) {
+        List<ExecutableElement> methods = new ArrayList<>();
+        methods.addAll(ElementFilter.methodsIn(elements));
+
+        List<E> parsedMethods = new ArrayList<>();
+        boolean valid = true;
+        int naturalOrder = 0;
+        for (ExecutableElement method : methods) {
+            if (!isParsable(method)) {
+                continue;
+            }
+
+            Class<? extends Annotation> annotationType = getAnnotationType();
+            AnnotationMirror mirror = null;
+            if (annotationType != null) {
+                mirror = ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, annotationType);
+            }
+
+            E parsedMethod = parse(naturalOrder, method, mirror);
+
+            if (method.getModifiers().contains(Modifier.PRIVATE) && parser.isEmitErrors()) {
+                parsedMethod.addError("Method annotated with @%s must not be private.", getAnnotationType().getSimpleName());
+                parsedMethods.add(parsedMethod);
+                valid = false;
+                continue;
+            }
+
+            if (parsedMethod != null) {
+                parsedMethods.add(parsedMethod);
+            } else {
+                valid = false;
+            }
+            naturalOrder++;
+        }
+        Collections.sort(parsedMethods);
+
+        if (!valid && isParseNullOnError()) {
+            return null;
+        }
+        return parsedMethods;
+    }
+
+    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
+        MethodSpec methodSpecification = createSpecification(method, annotation);
+        if (methodSpecification == null) {
+            return null;
+        }
+
+        TemplateMethod templateMethod = parser.parse(methodSpecification, method, annotation, naturalOrder);
+        if (templateMethod != null) {
+            return create(templateMethod, templateMethod.hasErrors());
+        }
+        return null;
+    }
+
+    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<VariableElement> parameterTypes) {
+        TemplateMethod method = parser.parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
+        if (method != null) {
+            return create(method, method.hasErrors());
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCastParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCastParser extends TypeSystemMethodParser<TypeCastData> {
+
+    public TypeCastParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, mirror, "value");
+        ParameterSpec returnTypeSpec = new ParameterSpec("returnType", targetTypeMirror);
+        returnTypeSpec.setAllowSubclasses(false);
+        MethodSpec spec = new MethodSpec(returnTypeSpec);
+        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
+        return spec;
+    }
+
+    @Override
+    public TypeCastData create(TemplateMethod method, boolean invalid) {
+        TypeMirror targetType = resolveCastOrCheck(method);
+        TypeMirror sourceType = getContext().getType(Object.class);
+        return new TypeCastData(method, sourceType, targetType);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCast.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeCheckParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+class TypeCheckParser extends TypeSystemMethodParser<TypeCheckData> {
+
+    public TypeCheckParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
+        MethodSpec spec = new MethodSpec(new ParameterSpec("returnType", getContext().getType(boolean.class)));
+        spec.addRequired(new ParameterSpec("value", getContext().getType(Object.class)));
+        return spec;
+    }
+
+    @Override
+    public TypeCheckData create(TemplateMethod method, boolean invalid) {
+        TypeMirror targetType = resolveCastOrCheck(method);
+        return new TypeCheckData(method, targetType, targetType);
+    }
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeCheck.class;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemMethodParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+import com.oracle.truffle.dsl.processor.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+abstract class TypeSystemMethodParser<E extends TemplateMethod> extends TemplateMethodParser<TypeSystemData, E> {
+
+    public TypeSystemMethodParser(ProcessorContext context, TypeSystemData typeSystem) {
+        super(context, typeSystem);
+    }
+
+    @Override
+    public final boolean isParsable(ExecutableElement method) {
+        return ElementUtils.findAnnotationMirror(getContext().getEnvironment(), method, getAnnotationType()) != null;
+    }
+
+    protected final TypeMirror resolveCastOrCheck(TemplateMethod method) {
+        Class<?> annotationType = getAnnotationType();
+        TypeMirror targetTypeMirror = ElementUtils.getAnnotationValue(TypeMirror.class, method.getMessageAnnotation(), "value");
+        if (!method.getMethod().getModifiers().contains(Modifier.PUBLIC) || !method.getMethod().getModifiers().contains(Modifier.STATIC)) {
+            method.addError("@%s annotated method %s must be public and static.", annotationType.getSimpleName(), method.getMethodName());
+        }
+        return targetTypeMirror;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.parser;
+
+import java.lang.annotation.*;
+import java.util.*;
+
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.dsl.processor.java.*;
+import com.oracle.truffle.dsl.processor.model.*;
+
+@DSLOptions
+public class TypeSystemParser extends AbstractParser<TypeSystemData> {
+
+    public static final List<Class<TypeSystem>> ANNOTATIONS = Arrays.asList(TypeSystem.class);
+
+    @Override
+    public Class<? extends Annotation> getAnnotationType() {
+        return TypeSystem.class;
+    }
+
+    @Override
+    protected TypeSystemData parse(Element element, AnnotationMirror mirror) {
+        TypeElement templateType = (TypeElement) element;
+        AnnotationMirror templateTypeAnnotation = mirror;
+        DSLOptions options = element.getAnnotation(DSLOptions.class);
+        if (options == null) {
+            options = TypeSystemParser.class.getAnnotation(DSLOptions.class);
+        }
+        assert options != null;
+
+        TypeSystemData typeSystem = new TypeSystemData(context, templateType, templateTypeAnnotation, options, false);
+
+        // annotation type on class path!?
+        TypeElement annotationTypeElement = processingEnv.getElementUtils().getTypeElement(getAnnotationType().getCanonicalName());
+        if (annotationTypeElement == null) {
+            typeSystem.addError("Required class %s is not on the classpath.", getAnnotationType().getName());
+        }
+        if (templateType.getModifiers().contains(Modifier.PRIVATE)) {
+            typeSystem.addError("A @%s must have at least package protected visibility.", getAnnotationType().getName());
+        }
+
+        if (templateType.getModifiers().contains(Modifier.FINAL)) {
+            typeSystem.addError("The @%s must not be final.", getAnnotationType().getName());
+        }
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+
+        verifyExclusiveMethodAnnotation(typeSystem, TypeCast.class, TypeCheck.class);
+
+        List<Element> elements = new ArrayList<>(context.getEnvironment().getElementUtils().getAllMembers(templateType));
+        List<ImplicitCastData> implicitCasts = new ImplicitCastParser(context, typeSystem).parse(elements);
+        List<TypeCastData> casts = new TypeCastParser(context, typeSystem).parse(elements);
+        List<TypeCheckData> checks = new TypeCheckParser(context, typeSystem).parse(elements);
+
+        if (casts == null || checks == null || implicitCasts == null) {
+            return typeSystem;
+        }
+
+        List<TypeMirror> legacyTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, typeSystem.getTemplateTypeAnnotation(), "value");
+        for (int i = 0; i < legacyTypes.size(); i++) {
+            legacyTypes.set(i, ElementUtils.fillInGenericWildcards(legacyTypes.get(i)));
+        }
+
+        typeSystem.getLegacyTypes().addAll(legacyTypes);
+        verifyTypes(typeSystem);
+        typeSystem.getLegacyTypes().add(context.getType(Object.class));
+        typeSystem.getLegacyTypes().add(context.getType(void.class));
+        verifyNamesUnique(typeSystem);
+
+        typeSystem.getImplicitCasts().addAll(implicitCasts);
+        typeSystem.getCasts().addAll(casts);
+        typeSystem.getChecks().addAll(checks);
+
+        if (typeSystem.hasErrors()) {
+            return typeSystem;
+        }
+        return typeSystem;
+    }
+
+    private void verifyExclusiveMethodAnnotation(Template template, Class<?>... annotationTypes) {
+        List<ExecutableElement> methods = ElementFilter.methodsIn(template.getTemplateType().getEnclosedElements());
+        for (ExecutableElement method : methods) {
+            List<AnnotationMirror> foundAnnotations = new ArrayList<>();
+            for (int i = 0; i < annotationTypes.length; i++) {
+                Class<?> annotationType = annotationTypes[i];
+                AnnotationMirror mirror = ElementUtils.findAnnotationMirror(context.getEnvironment(), method, annotationType);
+                if (mirror != null) {
+                    foundAnnotations.add(mirror);
+                }
+            }
+            if (foundAnnotations.size() > 1) {
+                List<String> annotationNames = new ArrayList<>();
+                for (AnnotationMirror mirror : foundAnnotations) {
+                    annotationNames.add("@" + ElementUtils.getSimpleName(mirror.getAnnotationType()));
+                }
+
+                template.addError("Non exclusive usage of annotations %s.", annotationNames);
+            }
+        }
+    }
+
+    private void verifyTypes(TypeSystemData typeSystem) {
+        for (TypeMirror type : typeSystem.getLegacyTypes()) {
+            if (isPrimitiveWrapper(type)) {
+                typeSystem.addError("Types must not contain primitive wrapper types.");
+            }
+
+            if (ElementUtils.typeEquals(type, context.getType(Object.class))) {
+                typeSystem.addError("Types must not contain the generic type java.lang.Object.");
+            }
+        }
+
+        verifyTypeOrder(typeSystem);
+    }
+
+    private static void verifyTypeOrder(TypeSystemData typeSystem) {
+        Map<String, List<String>> invalidTypes = new HashMap<>();
+
+        for (int i = typeSystem.getLegacyTypes().size() - 1; i >= 0; i--) {
+            TypeMirror typeData = typeSystem.getLegacyTypes().get(i);
+            TypeMirror type = typeSystem.boxType(typeData);
+            if (invalidTypes.containsKey(ElementUtils.getQualifiedName(type))) {
+                typeSystem.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)),
+                                ElementUtils.getQualifiedName(type));
+            }
+            TypeElement element = ElementUtils.fromTypeMirror(type);
+            List<String> nextInvalidTypes = new ArrayList<>();
+            if (element != null) {
+                nextInvalidTypes.addAll(ElementUtils.getQualifiedSuperTypeNames(element));
+            }
+            nextInvalidTypes.add(ElementUtils.getQualifiedName(type));
+
+            for (String qualifiedName : nextInvalidTypes) {
+                List<String> inheritedTypes = invalidTypes.get(qualifiedName);
+                if (inheritedTypes == null) {
+                    inheritedTypes = new ArrayList<>();
+                    invalidTypes.put(qualifiedName, inheritedTypes);
+                }
+                inheritedTypes.add(ElementUtils.getQualifiedName(typeSystem.boxType(typeData)));
+            }
+        }
+    }
+
+    private boolean isPrimitiveWrapper(TypeMirror type) {
+        Types types = context.getEnvironment().getTypeUtils();
+        for (TypeKind kind : TypeKind.values()) {
+            if (!kind.isPrimitive()) {
+                continue;
+            }
+            if (ElementUtils.typeEquals(type, types.boxedClass(types.getPrimitiveType(kind)).asType())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static void verifyNamesUnique(TypeSystemData typeSystem) {
+        Set<String> usedNames = new HashSet<>();
+        for (TypeMirror type : typeSystem.getLegacyTypes()) {
+            String boxedName = ElementUtils.getSimpleName(typeSystem.boxType(type));
+            String primitiveName = ElementUtils.getSimpleName(type);
+            if (usedNames.contains(boxedName)) {
+                typeSystem.addError("Two types result in the same boxed name: %s.", boxedName);
+            } else if (usedNames.contains(primitiveName)) {
+                typeSystem.addError("Two types result in the same primitive name: %s.", primitiveName);
+            }
+            usedNames.add(boxedName);
+            usedNames.add(primitiveName);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Filterator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+import java.util.*;
+
+public class Filterator<T> implements Iterator<T> {
+
+    private final Predicate<T> includePredicate;
+    private final Iterator<T> elements;
+
+    private boolean hasCached;
+    private T cached;
+
+    public Filterator(Iterator<T> elements, Predicate<T> includePredicate) {
+        this.elements = elements;
+        this.includePredicate = includePredicate;
+    }
+
+    public boolean hasNext() {
+        if (hasCached) {
+            return true;
+        }
+        nextValue();
+        return hasCached;
+    }
+
+    private void nextValue() {
+        while (!hasCached && elements.hasNext()) {
+            T element = elements.next();
+            if (includePredicate.evaluate(element)) {
+                cached = element;
+                hasCached = true;
+            }
+        }
+    }
+
+    public T next() {
+        T foundCached = getCached();
+        if (foundCached != null) {
+            return foundCached;
+        } else {
+            nextValue();
+            if (!hasCached) {
+                throw new NoSuchElementException();
+            }
+            return getCached();
+        }
+    }
+
+    private T getCached() {
+        if (hasCached) {
+            hasCached = false;
+            T value = cached;
+            cached = null;
+            return value;
+        }
+        return null;
+    }
+
+    @Override
+    public void remove() {
+        elements.remove();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/FilteredIterable.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+import java.util.*;
+
+public class FilteredIterable<E> implements Iterable<E> {
+
+    private final Iterable<E> delegate;
+    private final Predicate<E> containedPredicate;
+
+    public FilteredIterable(Iterable<E> delegate, Predicate<E> containedPredicate) {
+        this.delegate = delegate;
+        this.containedPredicate = containedPredicate;
+    }
+
+    public Iterator<E> iterator() {
+        return new Filterator<>(delegate.iterator(), containedPredicate);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/util/Predicate.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.util;
+
+public interface Predicate<T> {
+
+    boolean evaluate(T value);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/verify/VerifyTruffleProcessor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.dsl.processor.verify;
+
+import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
+import static java.util.Collections.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.annotation.processing.*;
+import javax.lang.model.*;
+import javax.lang.model.element.*;
+import javax.tools.Diagnostic.Kind;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.dsl.processor.*;
+
+@SupportedAnnotationTypes({"com.oracle.truffle.api.CompilerDirectives.TruffleBoundary", "com.oracle.truffle.api.nodes.Node.Child"})
+public class VerifyTruffleProcessor extends AbstractProcessor {
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    /**
+     * Node class currently being processed.
+     */
+    private Element scope;
+
+    public static boolean isEnclosedIn(Element e, Element scopeElement) {
+        List<Element> elementHierarchy = getElementHierarchy(e);
+        return elementHierarchy.contains(scopeElement);
+    }
+
+    void errorMessage(Element element, String format, Object... args) {
+        message(Kind.ERROR, element, format, args);
+    }
+
+    void message(Kind kind, Element element, String format, Object... args) {
+        if (scope != null && !isEnclosedIn(element, scope)) {
+            // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=428357#c1
+            List<Element> elementHierarchy = getElementHierarchy(element);
+            reverse(elementHierarchy);
+
+            StringBuilder str = new StringBuilder();
+            for (Element e : elementHierarchy) {
+                if (e.getKind() != ElementKind.PACKAGE) {
+                    str.append(str.length() == 0 ? "" : ".");
+                    str.append(e);
+                }
+            }
+            processingEnv.getMessager().printMessage(kind, String.format(str + ": " + format, args), scope);
+        } else {
+            processingEnv.getMessager().printMessage(kind, String.format(format, args), element);
+        }
+    }
+
+    /**
+     * Bugs in an annotation processor can cause silent failure so try to report any exception
+     * throws as errors.
+     */
+    private void reportException(Kind kind, Element element, Throwable t) {
+        StringWriter buf = new StringWriter();
+        t.printStackTrace(new PrintWriter(buf));
+        buf.toString();
+        message(kind, element, "Exception thrown during processing: %s", buf.toString());
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return false;
+        }
+
+        TypeElement virtualFrameType = processingEnv.getElementUtils().getTypeElement("com.oracle.truffle.api.frame.VirtualFrame");
+
+        for (Element element : roundEnv.getElementsAnnotatedWith(TruffleBoundary.class)) {
+            scope = element;
+            try {
+                ExecutableElement method = (ExecutableElement) element;
+
+                for (VariableElement parameter : method.getParameters()) {
+                    Element paramType = processingEnv.getTypeUtils().asElement(parameter.asType());
+                    if (paramType != null && paramType.equals(virtualFrameType)) {
+                        errorMessage(element, "Method %s cannot be annotated with @%s and have a parameter of type %s", method.getSimpleName(), TruffleBoundary.class.getSimpleName(),
+                                        paramType.getSimpleName());
+                    }
+                }
+            } catch (Throwable t) {
+                reportException(isBug367599(t) ? Kind.NOTE : Kind.ERROR, element, t);
+            } finally {
+                scope = null;
+            }
+        }
+
+        for (Element e : roundEnv.getElementsAnnotatedWith(Child.class)) {
+            if (e.getModifiers().contains(Modifier.FINAL)) {
+                emitError("@Child field cannot be final", e);
+                continue;
+            }
+            assertNoErrorExpected(e);
+        }
+        return false;
+    }
+
+    void assertNoErrorExpected(Element element) {
+        ExpectError.assertNoErrorExpected(processingEnv, element);
+    }
+
+    void emitError(String message, Element element) {
+        if (ExpectError.isExpectedError(processingEnv, element, message)) {
+            return;
+        }
+        processingEnv.getMessager().printMessage(Kind.ERROR, message, element);
+    }
+
+    /**
+     * Determines if a given exception is (most likely) caused by <a
+     * href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599">Bug 367599</a>.
+     */
+    public static boolean isBug367599(Throwable t) {
+        if (t instanceof FilerException) {
+            for (StackTraceElement ste : t.getStackTrace()) {
+                if (ste.toString().contains("org.eclipse.jdt.internal.apt.pluggable.core.filer.IdeFilerImpl.create")) {
+                    // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367599
+                    return true;
+                }
+            }
+        }
+        if (t.getCause() != null) {
+            return isBug367599(t.getCause());
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/META-INF/services/com.oracle.truffle.api.object.LayoutFactory	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+com.oracle.truffle.object.basic.DefaultLayoutFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicAllocator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import static com.oracle.truffle.object.basic.BasicLocations.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
+import com.oracle.truffle.object.Locations.ConstantLocation;
+import com.oracle.truffle.object.Locations.DeclaredDualLocation;
+import com.oracle.truffle.object.Locations.DualLocation;
+import com.oracle.truffle.object.Locations.ValueLocation;
+import com.oracle.truffle.object.basic.BasicLocations.BooleanLocationDecorator;
+import com.oracle.truffle.object.basic.BasicLocations.DoubleLocationDecorator;
+import com.oracle.truffle.object.basic.BasicLocations.IntLocationDecorator;
+import com.oracle.truffle.object.basic.BasicLocations.LongArrayLocation;
+import com.oracle.truffle.object.basic.BasicLocations.LongFieldLocation;
+import com.oracle.truffle.object.basic.BasicLocations.ObjectArrayLocation;
+
+public abstract class BasicAllocator extends ShapeImpl.BaseAllocator {
+
+    public BasicAllocator(LayoutImpl layout) {
+        super(layout);
+        advance(((BasicLayout) layout).getPrimitiveArrayLocation());
+    }
+
+    public BasicAllocator(ShapeImpl shape) {
+        super(shape);
+    }
+
+    private BasicLayout getLayout() {
+        return (BasicLayout) layout;
+    }
+
+    @Override
+    protected Location moveLocation(Location oldLocation) {
+        if (oldLocation instanceof DeclaredDualLocation) {
+            return advance(newDeclaredDualLocation(((DeclaredDualLocation) oldLocation).get(null, false)));
+        } else if (oldLocation instanceof DualLocation) {
+            return advance(newDualLocation(((DualLocation) oldLocation).getType()));
+        } else if (oldLocation instanceof LongLocation) {
+            return newLongLocation(oldLocation.isFinal());
+        } else if (oldLocation instanceof IntLocation) {
+            return newIntLocation(oldLocation.isFinal());
+        } else if (oldLocation instanceof DoubleLocation) {
+            return newDoubleLocation(oldLocation.isFinal());
+        } else if (oldLocation instanceof BooleanLocation) {
+            return newBooleanLocation(oldLocation.isFinal());
+        } else if (oldLocation instanceof ObjectLocation) {
+            return newObjectLocation(oldLocation.isFinal(), ((ObjectLocation) oldLocation).isNonNull());
+        } else {
+            assert oldLocation instanceof ValueLocation;
+            return advance(oldLocation);
+        }
+    }
+
+    @Override
+    public Location newObjectLocation(boolean useFinal, boolean nonNull) {
+        if (ObjectStorageOptions.InObjectFields) {
+            int insertPos = objectFieldSize;
+            while (insertPos + OBJECT_SIZE <= getLayout().getObjectFieldCount()) {
+                return advance((Location) getLayout().getObjectFieldLocation(insertPos));
+            }
+        }
+        return newObjectArrayLocation(useFinal, nonNull);
+    }
+
+    @SuppressWarnings("unused")
+    private Location newObjectArrayLocation(boolean useFinal, boolean nonNull) {
+        return advance(new ObjectArrayLocation(objectArraySize, getLayout().getObjectArrayLocation()));
+    }
+
+    @Override
+    public Location newTypedObjectLocation(boolean useFinal, Class<?> type, boolean nonNull) {
+        return newObjectLocation(useFinal, nonNull);
+    }
+
+    @Override
+    public Location newIntLocation(boolean useFinal) {
+        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.IntegerLocations) {
+            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
+                return advance(new IntLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize)));
+            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
+                return advance(new IntLocationDecorator(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation())));
+            }
+        }
+        return newObjectLocation(useFinal, true);
+    }
+
+    @Override
+    public Location newDoubleLocation(boolean useFinal) {
+        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.DoubleLocations) {
+            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
+                return advance(new DoubleLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize), getLayout().isAllowedIntToDouble()));
+            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
+                return advance(new DoubleLocationDecorator(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation()), getLayout().isAllowedIntToDouble()));
+            }
+        }
+        return newObjectLocation(useFinal, true);
+    }
+
+    @Override
+    public Location newLongLocation(boolean useFinal) {
+        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.LongLocations) {
+            if (ObjectStorageOptions.InObjectFields && primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
+                return advance((Location) LongFieldLocation.create(getLayout().getPrimitiveFieldLocation(primitiveFieldSize), getLayout().isAllowedIntToLong()));
+            } else if (getLayout().hasPrimitiveExtensionArray() && isPrimitiveExtensionArrayAvailable()) {
+                return advance(new LongArrayLocation(primitiveArraySize, getLayout().getPrimitiveArrayLocation(), getLayout().isAllowedIntToLong()));
+            }
+        }
+        return newObjectLocation(useFinal, true);
+    }
+
+    @Override
+    public Location newBooleanLocation(boolean useFinal) {
+        if (ObjectStorageOptions.PrimitiveLocations && ObjectStorageOptions.BooleanLocations) {
+            if (primitiveFieldSize + LONG_SIZE <= getLayout().getPrimitiveFieldCount()) {
+                return advance(new BooleanLocationDecorator(getLayout().getPrimitiveFieldLocation(primitiveFieldSize)));
+            }
+        }
+        return newObjectLocation(useFinal, true);
+    }
+
+    private boolean isPrimitiveExtensionArrayAvailable() {
+        return hasPrimitiveArray;
+    }
+
+    @Override
+    protected Location locationForValueUpcast(Object value, Location oldLocation) {
+        assert !(value instanceof Class);
+        if (oldLocation instanceof DualLocation) {
+            DualLocation dualLocation = (DualLocation) oldLocation;
+            if (dualLocation.getType() == null) {
+                if (value instanceof Integer) {
+                    return dualLocation.changeType(int.class);
+                } else if (value instanceof Double) {
+                    return dualLocation.changeType(double.class);
+                } else if (value instanceof Long) {
+                    return dualLocation.changeType(long.class);
+                } else if (value instanceof Boolean) {
+                    return dualLocation.changeType(boolean.class);
+                } else {
+                    return dualLocation.changeType(Object.class);
+                }
+            } else if (dualLocation.getType().isPrimitive()) {
+                return dualLocation.changeType(Object.class);
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        } else if (oldLocation instanceof ConstantLocation) {
+            return constantLocation(value);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    protected DeclaredDualLocation newDeclaredDualLocation(Object value) {
+        return new DeclaredDualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), value, layout);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLayout.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.api.object.Shape.Allocator;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
+import com.oracle.truffle.object.Locations.DualLocation;
+import com.oracle.truffle.object.basic.BasicLocations.ObjectFieldLocation;
+import com.oracle.truffle.object.basic.BasicLocations.SimpleObjectFieldLocation;
+
+public class BasicLayout extends LayoutImpl {
+    private final ObjectLocation[] objectFields;
+    private final InternalLongLocation[] primitiveFields;
+    private final Location objectArrayLocation;
+    private final Location primitiveArrayLocation;
+
+    BasicLayout(EnumSet<ImplicitCast> allowedImplicitCasts, LayoutStrategy strategy) {
+        super(allowedImplicitCasts, DynamicObjectBasic.class, strategy);
+        this.objectFields = DynamicObjectBasic.OBJECT_FIELD_LOCATIONS;
+        this.primitiveFields = DynamicObjectBasic.PRIMITIVE_FIELD_LOCATIONS;
+        this.primitiveArrayLocation = DynamicObjectBasic.PRIMITIVE_ARRAY_LOCATION;
+        this.objectArrayLocation = DynamicObjectBasic.OBJECT_ARRAY_LOCATION;
+    }
+
+    static LayoutImpl createLayoutImpl(EnumSet<ImplicitCast> allowedImplicitCasts, LayoutStrategy strategy) {
+        return new BasicLayout(allowedImplicitCasts, strategy);
+    }
+
+    @Override
+    public DynamicObject newInstance(Shape shape) {
+        return new DynamicObjectBasic(shape);
+    }
+
+    @Override
+    public Shape createShape(ObjectType operations, Object sharedData, int id) {
+        return new ShapeBasic(this, sharedData, operations, id);
+    }
+
+    @Override
+    protected boolean hasObjectExtensionArray() {
+        return true;
+    }
+
+    @Override
+    protected boolean hasPrimitiveExtensionArray() {
+        return true;
+    }
+
+    @Override
+    protected int getObjectFieldCount() {
+        return objectFields.length;
+    }
+
+    @Override
+    protected int getPrimitiveFieldCount() {
+        return primitiveFields.length;
+    }
+
+    @Override
+    protected Location getObjectArrayLocation() {
+        return objectArrayLocation;
+    }
+
+    @Override
+    protected Location getPrimitiveArrayLocation() {
+        return primitiveArrayLocation;
+    }
+
+    protected ObjectLocation getObjectFieldLocation(int index) {
+        return objectFields[index];
+    }
+
+    protected InternalLongLocation getPrimitiveFieldLocation(int index) {
+        return primitiveFields[index];
+    }
+
+    @Override
+    public Allocator createAllocator() {
+        LayoutImpl layout = this;
+        Allocator allocator = getStrategy().createAllocator(layout);
+        return allocator;
+    }
+
+    @Override
+    protected int objectFieldIndex(Location location) {
+        if (location instanceof DualLocation) {
+            return objectFieldIndex((Location) ((DualLocation) location).getObjectLocation());
+        } else if (location instanceof ObjectFieldLocation) {
+            return ((ObjectFieldLocation) location).getIndex();
+        } else if (location instanceof SimpleObjectFieldLocation) {
+            return ((SimpleObjectFieldLocation) location).getIndex();
+        } else {
+            return 0;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/BasicLocations.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import java.lang.invoke.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
+
+/**
+ * Property location.
+ *
+ * @see Shape
+ * @see Property
+ * @see DynamicObject
+ */
+public abstract class BasicLocations {
+    static final int LONG_SIZE = 1;
+    static final int OBJECT_SIZE = 1;
+
+    public abstract static class ArrayLocation extends LocationImpl {
+        protected final int index;
+        protected final Location arrayLocation;
+
+        public ArrayLocation(int index, Location arrayLocation) {
+            this.index = index;
+            this.arrayLocation = arrayLocation;
+        }
+
+        protected final Object getArray(DynamicObject store, boolean condition) {
+            // non-null cast
+            return arrayLocation.get(store, condition);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + index;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!super.equals(obj)) {
+                return false;
+            }
+            ArrayLocation other = (ArrayLocation) obj;
+            if (index != other.index) {
+                return false;
+            }
+            return true;
+        }
+
+        public final int getIndex() {
+            return index;
+        }
+
+        @Override
+        protected String getWhereString() {
+            return "[" + index + "]";
+        }
+    }
+
+    public abstract static class FieldLocation extends LocationImpl {
+        private final int index;
+
+        public FieldLocation(int index) {
+            this.index = index;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + index;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!super.equals(obj)) {
+                return false;
+            }
+            FieldLocation other = (FieldLocation) obj;
+            if (index != other.index) {
+                return false;
+            }
+            return true;
+        }
+
+        public final int getIndex() {
+            return index;
+        }
+
+        @Override
+        protected String getWhereString() {
+            return "@" + index;
+        }
+    }
+
+    public abstract static class MethodHandleFieldLocation extends FieldLocation {
+        protected final MethodHandle getter;
+        protected final MethodHandle setter;
+
+        public MethodHandleFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
+            super(index);
+            this.getter = getter;
+            this.setter = setter;
+        }
+    }
+
+    public static class ObjectArrayLocation extends ArrayLocation implements ObjectLocation {
+        public ObjectArrayLocation(int index, Location arrayLocation) {
+            super(index, arrayLocation);
+        }
+
+        @Override
+        public Object get(DynamicObject store, boolean condition) {
+            return ((Object[]) getArray(store, condition))[index];
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            ((Object[]) getArray(store, false))[index] = value;
+        }
+
+        @Override
+        public boolean canStore(Object value) {
+            return true;
+        }
+
+        public Class<? extends Object> getType() {
+            return Object.class;
+        }
+
+        public final boolean isNonNull() {
+            return false;
+        }
+
+        @Override
+        public int objectArrayCount() {
+            return OBJECT_SIZE;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitObjectArray(index, OBJECT_SIZE);
+        }
+    }
+
+    public static class ObjectFieldLocation extends MethodHandleFieldLocation implements ObjectLocation {
+
+        public ObjectFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
+            super(index, getter, setter);
+        }
+
+        @Override
+        public Object get(DynamicObject store, boolean condition) {
+            try {
+                return getter.invokeExact(store);
+            } catch (Throwable e) {
+                CompilerDirectives.transferToInterpreter();
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            try {
+                setter.invokeExact(store, value);
+            } catch (Throwable e) {
+                CompilerDirectives.transferToInterpreter();
+                throw new IllegalStateException(e);
+            }
+        }
+
+        @Override
+        public boolean canStore(Object value) {
+            return true;
+        }
+
+        public Class<? extends Object> getType() {
+            return Object.class;
+        }
+
+        public boolean isNonNull() {
+            return false;
+        }
+
+        @Override
+        public int objectFieldCount() {
+            return OBJECT_SIZE;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitObjectField(getIndex(), OBJECT_SIZE);
+        }
+    }
+
+    public abstract static class SimpleObjectFieldLocation extends FieldLocation implements ObjectLocation {
+
+        public SimpleObjectFieldLocation(int index) {
+            super(index);
+        }
+
+        @Override
+        public abstract Object get(DynamicObject store, boolean condition);
+
+        @Override
+        public abstract void setInternal(DynamicObject store, Object value);
+
+        @Override
+        public boolean canStore(Object value) {
+            return true;
+        }
+
+        public Class<? extends Object> getType() {
+            return Object.class;
+        }
+
+        public boolean isNonNull() {
+            return false;
+        }
+
+        @Override
+        public int objectFieldCount() {
+            return OBJECT_SIZE;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitObjectField(getIndex(), OBJECT_SIZE);
+        }
+    }
+
+    public static class LongArrayLocation extends ArrayLocation implements InternalLongLocation {
+        protected final boolean allowInt;
+
+        public LongArrayLocation(int index, Location arrayLocation, boolean allowInt) {
+            super(index, arrayLocation);
+            this.allowInt = allowInt;
+        }
+
+        public LongArrayLocation(int index, Location arrayLocation) {
+            this(index, arrayLocation, false);
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getLong(store, condition);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setLongInternal(store, ((Number) value).longValue());
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        @Override
+        public long getLong(DynamicObject store, boolean condition) {
+            return ((long[]) getArray(store, condition))[index];
+        }
+
+        public final void setLongInternal(DynamicObject store, long value) {
+            ((long[]) getArray(store, false))[index] = value;
+        }
+
+        @Override
+        public void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException {
+            setLongInternal(store, value);
+        }
+
+        @Override
+        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setLongInternal(store, value);
+        }
+
+        @Override
+        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
+            setLong(store, value, null);
+        }
+
+        public final long getLong(DynamicObject store, Shape shape) {
+            return getLong(store, checkShape(store, shape));
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Long || (allowInt && value instanceof Integer);
+        }
+
+        public final Class<Long> getType() {
+            return long.class;
+        }
+
+        @Override
+        public int primitiveArrayCount() {
+            return LONG_SIZE;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitPrimitiveArray(getIndex(), LONG_SIZE);
+        }
+    }
+
+    public static class LongFieldLocation extends MethodHandleFieldLocation implements InternalLongLocation {
+        public LongFieldLocation(int index, MethodHandle getter, MethodHandle setter) {
+            super(index, getter, setter);
+        }
+
+        public static LongLocation create(InternalLongLocation longLocation, boolean allowInt) {
+            if ((!allowInt && (longLocation instanceof LongLocationDecorator)) || (longLocation instanceof LongLocationDecorator && ((LongLocationDecorator) longLocation).allowInt == allowInt)) {
+                return longLocation;
+            } else {
+                return new LongLocationDecorator(longLocation, allowInt);
+            }
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getLong(store, condition);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setLongInternal(store, (long) value);
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Long;
+        }
+
+        @Override
+        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setLongInternal(store, value);
+        }
+
+        public long getLong(DynamicObject store, boolean condition) {
+            try {
+                return (long) getter.invokeExact(store);
+            } catch (Throwable e) {
+                CompilerDirectives.transferToInterpreter();
+                throw new IllegalStateException(e);
+            }
+        }
+
+        public void setLong(DynamicObject store, long value, Shape shape) {
+            setLongInternal(store, value);
+        }
+
+        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
+            setLong(store, value, null);
+        }
+
+        public final void setLongInternal(DynamicObject store, long value) {
+            try {
+                setter.invokeExact(store, value);
+            } catch (Throwable e) {
+                CompilerDirectives.transferToInterpreter();
+                throw new IllegalStateException(e);
+            }
+        }
+
+        public final long getLong(DynamicObject store, Shape shape) {
+            return getLong(store, checkShape(store, shape));
+        }
+
+        @Override
+        public final int primitiveFieldCount() {
+            return LONG_SIZE;
+        }
+
+        public final Class<Long> getType() {
+            return long.class;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitPrimitiveField(getIndex(), LONG_SIZE);
+        }
+    }
+
+    public static class LongLocationDecorator extends PrimitiveLocationDecorator implements InternalLongLocation {
+        protected final boolean allowInt;
+
+        public LongLocationDecorator(InternalLongLocation longLocation, boolean allowInt) {
+            super(longLocation);
+            this.allowInt = allowInt;
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getLong(store, condition);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setLongInternal(store, ((Number) value).longValue());
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Long || (allowInt && value instanceof Integer);
+        }
+
+        @Override
+        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setLongInternal(store, value);
+        }
+
+        public Class<Long> getType() {
+            return long.class;
+        }
+    }
+
+    public abstract static class SimpleLongFieldLocation extends FieldLocation implements InternalLongLocation {
+
+        public SimpleLongFieldLocation(int index) {
+            super(index);
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getLong(store, condition);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setLongInternal(store, ((Number) value).longValue());
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Long;
+        }
+
+        @Override
+        public final void setLong(DynamicObject store, long value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setLongInternal(store, value);
+        }
+
+        public abstract long getLong(DynamicObject store, boolean condition);
+
+        public final long getLong(DynamicObject store, Shape shape) {
+            return getLong(store, checkShape(store, shape));
+        }
+
+        public final void setLong(DynamicObject store, long value) {
+            setLong(store, value, null);
+        }
+
+        public void setLong(DynamicObject store, long value, Shape shape) {
+            setLongInternal(store, value);
+        }
+
+        public abstract void setLongInternal(DynamicObject store, long value);
+
+        @Override
+        public final int primitiveFieldCount() {
+            return LONG_SIZE;
+        }
+
+        public final Class<Long> getType() {
+            return long.class;
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            locationVisitor.visitPrimitiveField(getIndex(), LONG_SIZE);
+        }
+    }
+
+    public abstract static class PrimitiveLocationDecorator extends LocationImpl {
+        private final InternalLongLocation longLocation;
+
+        public PrimitiveLocationDecorator(InternalLongLocation longLocation) {
+            this.longLocation = longLocation;
+        }
+
+        public final long getLong(DynamicObject store, Shape shape) {
+            return longLocation.getLong(store, shape);
+        }
+
+        public final long getLong(DynamicObject store, boolean condition) {
+            return longLocation.getLong(store, condition);
+        }
+
+        public final void setLong(DynamicObject store, long value, Shape shape) throws FinalLocationException {
+            longLocation.setLong(store, value, shape);
+        }
+
+        public final void setLong(DynamicObject store, long value) throws FinalLocationException {
+            longLocation.setLong(store, value);
+        }
+
+        public final void setLongInternal(DynamicObject store, long value) {
+            longLocation.setLongInternal(store, value);
+        }
+
+        @Override
+        public final int primitiveFieldCount() {
+            return ((LocationImpl) longLocation).primitiveFieldCount();
+        }
+
+        @Override
+        public final int primitiveArrayCount() {
+            return ((LocationImpl) longLocation).primitiveArrayCount();
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            ((LocationImpl) longLocation).accept(locationVisitor);
+        }
+    }
+
+    public static class IntLocationDecorator extends PrimitiveLocationDecorator implements IntLocation {
+        public IntLocationDecorator(InternalLongLocation longLocation) {
+            super(longLocation);
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getInt(store, condition);
+        }
+
+        public int getInt(DynamicObject store, boolean condition) {
+            return (int) getLong(store, condition);
+        }
+
+        public void setInt(DynamicObject store, int value, Shape shape) throws FinalLocationException {
+            setLong(store, value, shape);
+        }
+
+        @Override
+        public final void setInt(DynamicObject store, int value) throws FinalLocationException {
+            setInt(store, value, null);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setLongInternal(store, (int) value);
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        public final int getInt(DynamicObject store, Shape shape) {
+            return getInt(store, checkShape(store, shape));
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Integer;
+        }
+
+        @Override
+        public final void setInt(DynamicObject store, int value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setLongInternal(store, value);
+        }
+
+        public Class<Integer> getType() {
+            return int.class;
+        }
+    }
+
+    public static class DoubleLocationDecorator extends PrimitiveLocationDecorator implements DoubleLocation {
+        private final boolean allowInt;
+
+        public DoubleLocationDecorator(InternalLongLocation longLocation, boolean allowInt) {
+            super(longLocation);
+            this.allowInt = allowInt;
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getDouble(store, condition);
+        }
+
+        public double getDouble(DynamicObject store, boolean condition) {
+            return Double.longBitsToDouble(getLong(store, condition));
+        }
+
+        public void setDouble(DynamicObject store, double value, Shape shape) {
+            setLongInternal(store, Double.doubleToRawLongBits(value));
+        }
+
+        public void setDouble(DynamicObject store, double value) {
+            setDouble(store, value, null);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setDouble(store, ((Number) value).doubleValue(), null);
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        public final double getDouble(DynamicObject store, Shape shape) {
+            return getDouble(store, checkShape(store, shape));
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Double || (allowInt && value instanceof Integer);
+        }
+
+        @Override
+        public final void setDouble(DynamicObject store, double value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setDouble(store, value, newShape);
+        }
+
+        public Class<Double> getType() {
+            return double.class;
+        }
+    }
+
+    public static class BooleanLocationDecorator extends PrimitiveLocationDecorator implements BooleanLocation {
+        public BooleanLocationDecorator(InternalLongLocation longLocation) {
+            super(longLocation);
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return getBoolean(store, condition);
+        }
+
+        public boolean getBoolean(DynamicObject store, boolean condition) {
+            return getLong(store, condition) != 0;
+        }
+
+        public void setBoolean(DynamicObject store, boolean value, Shape shape) {
+            setLongInternal(store, value ? 1 : 0);
+        }
+
+        public void setBoolean(DynamicObject store, boolean value) {
+            setBoolean(store, value, null);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (canStore(value)) {
+                setBoolean(store, (boolean) value, null);
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        public final boolean getBoolean(DynamicObject store, Shape shape) {
+            return getBoolean(store, checkShape(store, shape));
+        }
+
+        @Override
+        public final boolean canStore(Object value) {
+            return value instanceof Boolean;
+        }
+
+        @Override
+        public final void setBoolean(DynamicObject store, boolean value, Shape oldShape, Shape newShape) {
+            store.setShapeAndGrow(oldShape, newShape);
+            setBoolean(store, value, newShape);
+        }
+
+        public Class<Boolean> getType() {
+            return boolean.class;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultLayoutFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+
+public class DefaultLayoutFactory implements LayoutFactory {
+    public Layout createLayout(LayoutBuilder layoutBuilder) {
+        return BasicLayout.createLayoutImpl(layoutBuilder.getAllowedImplicitCasts(), new DefaultStrategy());
+    }
+
+    public Property createProperty(Object id, Location location) {
+        return createProperty(id, location, 0);
+    }
+
+    public Property createProperty(Object id, Location location, int flags) {
+        return new PropertyImpl(id, location, flags);
+    }
+
+    public int getPriority() {
+        return 10;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DefaultStrategy.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
+
+class DefaultStrategy implements LayoutStrategy {
+    public boolean updateShape(DynamicObject object) {
+        assert object.getShape().isValid();
+        return false;
+    }
+
+    public Shape returnCached(Shape newShape) {
+        assert newShape.isValid();
+        return newShape;
+    }
+
+    private static boolean assertLocationInRange(Shape shape, Location location) {
+        BasicLayout layout = (BasicLayout) shape.getLayout();
+        assert (shape.getPrimitiveFieldSize() + ((LocationImpl) location).primitiveFieldCount() <= layout.getPrimitiveFieldCount());
+        assert (shape.getObjectFieldSize() + ((LocationImpl) location).objectFieldCount() <= layout.getObjectFieldCount());
+        return true;
+    }
+
+    public Shape ensureSpace(Shape shape, Location location) {
+        Objects.requireNonNull(location);
+        assert assertLocationInRange(shape, location);
+        return shape;
+    }
+
+    public boolean isAutoExtArray() {
+        return false;
+    }
+
+    public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value) {
+        Shape oldShape = object.getShape();
+        Location oldLocation = oldProperty.getLocation();
+        Location newLocation = ((BasicAllocator) oldShape.allocator()).locationForValueUpcast(value, oldLocation);
+        Property newProperty = oldProperty.relocate(newLocation);
+        Shape newShape = oldShape.replaceProperty(oldProperty, newProperty);
+        newProperty.setSafe(object, value, oldShape, newShape);
+        return newProperty;
+    }
+
+    public Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape currentShape, Shape oldNewShape) {
+        Location oldLocation = oldProperty.getLocation();
+        Location newLocation = ((BasicAllocator) currentShape.allocator()).locationForValueUpcast(value, oldLocation);
+        Property newProperty = oldProperty.relocate(newLocation);
+        Shape newShape = oldNewShape.replaceProperty(oldProperty, newProperty);
+        newProperty.setSafe(object, value, currentShape, newShape);
+        return newProperty;
+    }
+
+    public BaseAllocator createAllocator(Shape shape) {
+        return new DefaultAllocatorImpl((ShapeImpl) shape);
+    }
+
+    public BaseAllocator createAllocator(Layout layout) {
+        return new DefaultAllocatorImpl((LayoutImpl) layout);
+    }
+
+    public static class DefaultAllocatorImpl extends BasicAllocator {
+        protected DefaultAllocatorImpl(LayoutImpl layout) {
+            super(layout);
+        }
+
+        protected DefaultAllocatorImpl(ShapeImpl shape) {
+            super(shape);
+        }
+
+        @Override
+        public Location locationForValue(Object value, boolean useFinal, boolean nonNull) {
+            return super.newDualLocationForValue(value);
+        }
+
+        @Override
+        public Location declaredLocation(Object value) {
+            return super.newDeclaredDualLocation(value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/DynamicObjectBasic.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import java.lang.annotation.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.basic.BasicLocations.SimpleLongFieldLocation;
+import com.oracle.truffle.object.basic.BasicLocations.SimpleObjectFieldLocation;
+
+public class DynamicObjectBasic extends DynamicObjectImpl {
+    @Retention(RetentionPolicy.RUNTIME)
+    protected @interface DynamicField {
+    }
+
+    @DynamicField private long primitive1;
+    @DynamicField private long primitive2;
+    @DynamicField private long primitive3;
+    @DynamicField private Object object1;
+    @DynamicField private Object object2;
+    @DynamicField private Object object3;
+    @DynamicField private Object object4;
+    private Object[] objext;
+    private long[] primext;
+
+    public DynamicObjectBasic(Shape shape) {
+        super(shape);
+    }
+
+    @Override
+    protected final void initialize(Shape shape) {
+        assert getObjectStore(shape) == null;
+        int capacity = ((ShapeImpl) shape).getObjectArrayCapacity();
+        if (capacity != 0) {
+            this.setObjectStore(new Object[capacity], shape);
+        }
+        if (((ShapeImpl) shape).getPrimitiveArrayCapacity() != 0) {
+            this.setPrimitiveStore(new long[((ShapeImpl) shape).getPrimitiveArrayCapacity()], shape);
+        }
+    }
+
+    /**
+     * Simpler version of {@link #resizeObjectStore} when the object is only increasing in size.
+     */
+    @Override
+    protected final void growObjectStore(Shape oldShape, Shape newShape) {
+        int oldObjectArrayCapacity = ((ShapeImpl) oldShape).getObjectArrayCapacity();
+        int newObjectArrayCapacity = ((ShapeImpl) newShape).getObjectArrayCapacity();
+        if (oldObjectArrayCapacity != newObjectArrayCapacity) {
+            growObjectStoreIntl(oldObjectArrayCapacity, newObjectArrayCapacity, oldShape);
+        }
+    }
+
+    private void growObjectStoreIntl(int oldObjectArrayCapacity, int newObjectArrayCapacity, Shape newShape) {
+        Object[] newObjectStore = new Object[newObjectArrayCapacity];
+        if (oldObjectArrayCapacity != 0) {
+            // monotonic growth assumption
+            assert oldObjectArrayCapacity < newObjectArrayCapacity;
+            Object[] oldObjectStore = this.getObjectStore(newShape);
+            for (int i = 0; i < oldObjectArrayCapacity; ++i) {
+                newObjectStore[i] = oldObjectStore[i];
+            }
+        }
+        this.setObjectStore(newObjectStore, newShape);
+    }
+
+    /**
+     * Simpler version of {@link #resizePrimitiveStore} when the object is only increasing in size.
+     */
+    @Override
+    protected final void growPrimitiveStore(Shape oldShape, Shape newShape) {
+        assert ((ShapeImpl) newShape).hasPrimitiveArray();
+        int oldPrimitiveCapacity = oldShape.getPrimitiveArrayCapacity();
+        int newPrimitiveCapacity = newShape.getPrimitiveArrayCapacity();
+        if (newPrimitiveCapacity == 0) {
+            // due to obsolescence, we might have to reserve an empty primitive array slot
+            this.setPrimitiveStore(null, newShape);
+        } else if (oldPrimitiveCapacity != newPrimitiveCapacity) {
+            growPrimitiveStoreIntl(oldPrimitiveCapacity, newPrimitiveCapacity, oldShape);
+        }
+    }
+
+    private void growPrimitiveStoreIntl(int oldPrimitiveCapacity, int newPrimitiveCapacity, Shape newShape) {
+        long[] newPrimitiveArray = new long[newPrimitiveCapacity];
+        if (oldPrimitiveCapacity != 0) {
+            // primitive array can shrink due to type changes
+            long[] oldPrimitiveArray = this.getPrimitiveStore(newShape);
+            for (int i = 0; i < Math.min(oldPrimitiveCapacity, newPrimitiveCapacity); ++i) {
+                newPrimitiveArray[i] = oldPrimitiveArray[i];
+            }
+        }
+        this.setPrimitiveStore(newPrimitiveArray, newShape);
+    }
+
+    @Override
+    protected final void resizeObjectStore(Shape oldShape, Shape newShape) {
+        Object[] newObjectStore = null;
+        int destinationCapacity = newShape.getObjectArrayCapacity();
+        if (destinationCapacity != 0) {
+            newObjectStore = new Object[destinationCapacity];
+            int sourceCapacity = oldShape.getObjectArrayCapacity();
+            if (sourceCapacity != 0) {
+                Object[] oldObjectStore = getObjectStore(newShape);
+                for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) {
+                    newObjectStore[i] = oldObjectStore[i];
+                }
+            }
+        }
+        this.setObjectStore(newObjectStore, newShape);
+    }
+
+    private Object[] getObjectStore(@SuppressWarnings("unused") Shape currentShape) {
+        return objext;
+    }
+
+    private void setObjectStore(Object[] newArray, @SuppressWarnings("unused") Shape currentShape) {
+        objext = newArray;
+    }
+
+    private long[] getPrimitiveStore(@SuppressWarnings("unused") Shape currentShape) {
+        return primext;
+    }
+
+    private void setPrimitiveStore(long[] newArray, @SuppressWarnings("unused") Shape currentShape) {
+        primext = newArray;
+    }
+
+    @Override
+    protected final void resizePrimitiveStore(Shape oldShape, Shape newShape) {
+        assert newShape.hasPrimitiveArray();
+        long[] newPrimitiveArray = null;
+        int destinationCapacity = newShape.getPrimitiveArrayCapacity();
+        if (destinationCapacity != 0) {
+            newPrimitiveArray = new long[destinationCapacity];
+            int sourceCapacity = oldShape.getPrimitiveArrayCapacity();
+            if (sourceCapacity != 0) {
+                long[] oldPrimitiveArray = this.getPrimitiveStore(newShape);
+                for (int i = 0; i < Math.min(sourceCapacity, destinationCapacity); ++i) {
+                    newPrimitiveArray[i] = oldPrimitiveArray[i];
+                }
+            }
+        }
+        this.setPrimitiveStore(newPrimitiveArray, newShape);
+    }
+
+    /**
+     * Check whether fast transition is valid.
+     *
+     * @see #setShapeAndGrow
+     */
+    @SuppressWarnings("unused")
+    private boolean checkSetShape(Shape oldShape, Shape newShape) {
+        Shape currentShape = getShape();
+        assert oldShape != newShape : "Wrong old shape assumption?";
+        assert newShape != currentShape : "Redundant shape change? shape=" + currentShape;
+        assert oldShape == currentShape || oldShape.getParent() == currentShape : "Out-of-order shape change?" + "\nparentShape=" + currentShape + "\noldShape=" + oldShape + "\nnewShape=" + newShape;
+        return true;
+    }
+
+    /**
+     * Check whether the extension arrays are in accordance with the description in the shape.
+     */
+    @Override
+    protected final boolean checkExtensionArrayInvariants(Shape newShape) {
+        assert getShape() == newShape;
+        assert (getObjectStore(newShape) == null && newShape.getObjectArrayCapacity() == 0) ||
+                        (getObjectStore(newShape) != null && getObjectStore(newShape).length == newShape.getObjectArrayCapacity());
+        if (newShape.hasPrimitiveArray()) {
+            assert (getPrimitiveStore(newShape) == null && newShape.getPrimitiveArrayCapacity() == 0) ||
+                            (getPrimitiveStore(newShape) != null && getPrimitiveStore(newShape).length == newShape.getPrimitiveArrayCapacity());
+        }
+        return true;
+    }
+
+    @Override
+    protected final DynamicObject cloneWithShape(Shape currentShape) {
+        assert this.getShape() == currentShape;
+        final DynamicObjectBasic clone = (DynamicObjectBasic) super.clone();
+        if (this.getObjectStore(currentShape) != null) {
+            clone.setObjectStore(this.getObjectStore(currentShape).clone(), currentShape);
+        }
+        if (currentShape.hasPrimitiveArray() && this.getPrimitiveStore(currentShape) != null) {
+            clone.setPrimitiveStore(this.getPrimitiveStore(currentShape).clone(), currentShape);
+        }
+        return clone;
+    }
+
+    protected final void reshape(ShapeImpl newShape) {
+        reshapeCount.inc();
+
+        ShapeImpl oldShape = getShape();
+        ShapeImpl commonAncestor = ShapeImpl.findCommonAncestor(oldShape, newShape);
+        if (ObjectStorageOptions.TraceReshape) {
+            int limit = 150;
+            System.out.printf("RESHAPE\nOLD %s\nNEW %s\nLCA %s\nDIFF %s\n---\n", oldShape.toStringLimit(limit), newShape.toStringLimit(limit), commonAncestor.toStringLimit(limit),
+                            ShapeImpl.diff(oldShape, newShape));
+        }
+
+        DynamicObject original = this.cloneWithShape(oldShape);
+        setShapeAndGrow(oldShape, newShape);
+        assert !((newShape.hasPrimitiveArray() && newShape.getPrimitiveArrayCapacity() == 0)) || getPrimitiveStore(newShape) == null;
+        copyProperties(original, commonAncestor);
+        assert checkExtensionArrayInvariants(newShape);
+    }
+
+    static final SimpleObjectFieldLocation[] OBJECT_FIELD_LOCATIONS;
+    static final SimpleLongFieldLocation[] PRIMITIVE_FIELD_LOCATIONS;
+
+    static final SimpleObjectFieldLocation OBJECT_ARRAY_LOCATION;
+    static final SimpleObjectFieldLocation PRIMITIVE_ARRAY_LOCATION;
+
+    static {
+        int index;
+
+        index = 0;
+        PRIMITIVE_FIELD_LOCATIONS = new SimpleLongFieldLocation[]{new SimpleLongFieldLocation(index++) {
+            @Override
+            public long getLong(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).primitive1;
+            }
+
+            @Override
+            public void setLongInternal(DynamicObject store, long value) {
+                ((DynamicObjectBasic) store).primitive1 = value;
+            }
+        }, new SimpleLongFieldLocation(index++) {
+            @Override
+            public long getLong(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).primitive2;
+            }
+
+            @Override
+            public void setLongInternal(DynamicObject store, long value) {
+                ((DynamicObjectBasic) store).primitive2 = value;
+            }
+        }, new SimpleLongFieldLocation(index++) {
+            @Override
+            public long getLong(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).primitive3;
+            }
+
+            @Override
+            public void setLongInternal(DynamicObject store, long value) {
+                ((DynamicObjectBasic) store).primitive3 = value;
+            }
+        }};
+
+        index = 0;
+        OBJECT_FIELD_LOCATIONS = new SimpleObjectFieldLocation[]{new SimpleObjectFieldLocation(index++) {
+            @Override
+            public Object get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).object1;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).object1 = value;
+            }
+        }, new SimpleObjectFieldLocation(index++) {
+            @Override
+            public Object get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).object2;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).object2 = value;
+            }
+        }, new SimpleObjectFieldLocation(index++) {
+            @Override
+            public Object get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).object3;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).object3 = value;
+            }
+        }, new SimpleObjectFieldLocation(index++) {
+            @Override
+            public Object get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).object4;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).object4 = value;
+            }
+        }};
+
+        OBJECT_ARRAY_LOCATION = new SimpleObjectFieldLocation(index++) {
+            @Override
+            public Object[] get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).objext;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).objext = (Object[]) value;
+            }
+        };
+
+        PRIMITIVE_ARRAY_LOCATION = new SimpleObjectFieldLocation(index++) {
+            @Override
+            public long[] get(DynamicObject store, boolean condition) {
+                return ((DynamicObjectBasic) store).primext;
+            }
+
+            @Override
+            public void setInternal(DynamicObject store, Object value) {
+                ((DynamicObjectBasic) store).primext = (long[]) value;
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.basic;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+
+public final class ShapeBasic extends ShapeImpl {
+    public ShapeBasic(Layout layout, Object sharedData, ObjectType operations, int id) {
+        super(layout, operations, sharedData, id);
+    }
+
+    public ShapeBasic(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
+        super(layout, parent, objectType, sharedData, propertyMap, transition, allocator, id);
+    }
+
+    @SuppressWarnings("hiding")
+    @Override
+    protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
+        return new ShapeBasic(layout, sharedData, parent, objectType, propertyMap, transition, allocator, id);
+    }
+
+    @Override
+    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
+        return directReplaceProperty(oldProperty, newProperty);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Debug.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.object.debug.*;
+
+class Debug {
+    private static Collection<ShapeImpl> allShapes;
+
+    static void registerShape(ShapeImpl newShape) {
+        allShapes.add(newShape);
+    }
+
+    static {
+        if (ObjectStorageOptions.DumpShapes) {
+            allShapes = new ConcurrentLinkedQueue<>();
+        }
+
+        if (ObjectStorageOptions.DumpShapes) {
+            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+                public void run() {
+                    try (PrintWriter out = new PrintWriter("shapes.json", "UTF-8")) {
+                        out.println("{\"shapes\": [");
+                        boolean first = true;
+                        for (ShapeImpl shape : allShapes) {
+                            if (!first) {
+                                out.println(",");
+                            }
+                            first = false;
+                            out.print(shape.accept(new JSONShapeVisitor()));
+                        }
+                        if (!first) {
+                            out.println();
+                        }
+                        out.println("]}");
+                    } catch (FileNotFoundException | UnsupportedEncodingException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DebugShapeVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+
+public abstract class DebugShapeVisitor<R> implements ShapeVisitor<R> {
+    public R visitShape(Shape shape) {
+        return visitShape(shape, Collections.unmodifiableMap(((ShapeImpl) shape).getTransitionMapForRead()));
+    }
+
+    public abstract R visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions);
+
+    public static String getId(Shape shape) {
+        return Integer.toHexString(shape.hashCode());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/DynamicObjectImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.*;
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.Locations.ValueLocation;
+import com.oracle.truffle.object.debug.*;
+
+public abstract class DynamicObjectImpl extends DynamicObject implements Cloneable {
+    private ShapeImpl shape;
+
+    public static final DebugCounter reshapeCount = DebugCounter.create("Reshape count");
+
+    public DynamicObjectImpl(Shape shape) {
+        assert shape instanceof ShapeImpl;
+        initialize(shape);
+        setShape(shape);
+
+        if (ObjectStorageOptions.Profile) {
+            trackObject(this);
+        }
+    }
+
+    public Object getTypeIdentifier() {
+        return getShape();
+    }
+
+    @Override
+    public ShapeImpl getShape() {
+        return shape;
+    }
+
+    protected void setShape(Shape shape) {
+        assert shape.getLayout().getType().isInstance(this);
+        this.shape = (ShapeImpl) shape;
+    }
+
+    protected abstract void initialize(Shape initialShape);
+
+    public final void setShapeAndResize(Shape newShape) {
+        setShapeAndResize(getShape(), newShape);
+    }
+
+    @Override
+    public final void setShapeAndResize(Shape oldShape, Shape newShape) {
+        assert getShape() == oldShape : "wrong old shape";
+        if (oldShape != newShape) {
+            setShape(newShape);
+            resizeStore(oldShape, newShape);
+
+            assert checkExtensionArrayInvariants(newShape);
+        }
+    }
+
+    /**
+     * Set shape to an immediate child of the current shape, optionally growing the extension array.
+     * Typically this would add a single property. Cannot shrink or grow more than one property at a
+     * time.
+     *
+     * @see #setShapeAndResize(Shape, Shape)
+     */
+    @Override
+    public final void setShapeAndGrow(Shape oldShape, Shape newShape) {
+        assert getShape() == oldShape : "wrong old shape";
+        if (oldShape != newShape) {
+            assert checkSetShape(oldShape, newShape);
+
+            setShape(newShape);
+            growStore(oldShape, newShape);
+
+            assert checkExtensionArrayInvariants(newShape);
+        }
+    }
+
+    /**
+     * Simpler version of {@link #resizeStore} when the object is only increasing in size.
+     */
+    private void growStore(Shape oldShape, Shape newShape) {
+        growObjectStore(oldShape, newShape);
+        if (((ShapeImpl) newShape).hasPrimitiveArray) {
+            growPrimitiveStore(oldShape, newShape);
+        }
+    }
+
+    protected abstract void growObjectStore(Shape oldShape, Shape newShape);
+
+    protected abstract void growPrimitiveStore(Shape oldShape, Shape newShape);
+
+    private void resizeStore(Shape oldShape, Shape newShape) {
+        resizeObjectStore(oldShape, newShape);
+        if (((ShapeImpl) newShape).hasPrimitiveArray) {
+            resizePrimitiveStore(oldShape, newShape);
+        }
+    }
+
+    protected abstract void resizePrimitiveStore(Shape oldShape, Shape newShape);
+
+    protected abstract void resizeObjectStore(Shape oldShape, Shape newShape);
+
+    /**
+     * Check whether fast transition is valid.
+     *
+     * @see #setShapeAndGrow
+     */
+    private boolean checkSetShape(Shape oldShape, Shape newShape) {
+        Shape currentShape = getShape();
+        assert oldShape != newShape : "Wrong old shape assumption?";
+        assert newShape != currentShape : "Redundant shape change? shape=" + currentShape;
+        // assert oldShape == currentShape || (oldShape.getLastProperty() == ((EnterpriseLayout)
+        // oldShape.getLayout()).getPrimitiveArrayProperty() && oldShape.getParent() ==
+        // currentShape) : "Out-of-order shape change?" + "\nparentShape=" + currentShape +
+        // "\noldShape=" + oldShape + "\nnewShape=" + newShape;
+        return true;
+    }
+
+    /**
+     * Check whether the extension arrays are in accordance with the description in the shape.
+     */
+    protected abstract boolean checkExtensionArrayInvariants(Shape newShape);
+
+    @Override
+    protected final DynamicObject clone() {
+        try {
+            return (DynamicObject) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    protected abstract DynamicObject cloneWithShape(Shape currentShape);
+
+    void reshapeAfterDelete(final Shape newShape, final Shape deletedParentShape) {
+        DynamicObject original = this.cloneWithShape(getShape());
+        setShapeAndResize(newShape);
+        copyProperties(original, deletedParentShape);
+    }
+
+    public final void copyProperties(DynamicObject fromObject, Shape ancestor) {
+        ShapeImpl fromShape = (ShapeImpl) fromObject.getShape();
+        ShapeImpl toShape = getShape();
+        assert toShape.isRelated(ancestor);
+        assert toShape.isValid();
+        assert ancestor.isValid();
+        PropertyMap ancestorMap = ((ShapeImpl) ancestor).getPropertyMap();
+        PropertyMap fromMap = fromShape.getPropertyMap();
+        for (PropertyMap toMap = toShape.getPropertyMap(); !toMap.isEmpty() && toMap != ancestorMap; toMap = toMap.getParentMap()) {
+            Property toProperty = toMap.getLastProperty();
+            Property fromProperty = fromMap.get(toProperty.getKey());
+
+            // copy only if property has a location and it's not the same as the source location
+            if (toProperty.getLocation() != null && !(toProperty.getLocation() instanceof ValueLocation) && !toProperty.getLocation().equals(fromProperty.getLocation())) {
+                toProperty.setInternal(this, fromProperty.get(fromObject, false));
+                assert toShape.isValid();
+            }
+
+            if (fromProperty == fromMap.getLastProperty()) {
+                // no property is looked up twice, so we can skip over to parent
+                fromMap = fromMap.getParentMap();
+            }
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public boolean changeFlags(Object id, int newFlags) {
+        Shape oldShape = getShape();
+        Property existing = oldShape.getProperty(id);
+        if (existing != null) {
+            if (existing.getFlags() != newFlags) {
+                Property newProperty = existing.copyWithFlags(newFlags);
+                Shape newShape = oldShape.replaceProperty(existing, newProperty);
+                this.setShape(newShape);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public boolean changeFlags(Object id, FlagsFunction updateFunction) {
+        Shape oldShape = getShape();
+        Property existing = oldShape.getProperty(id);
+        if (existing != null) {
+            int newFlags = updateFunction.apply(existing.getFlags());
+            if (existing.getFlags() != newFlags) {
+                Property newProperty = existing.copyWithFlags(newFlags);
+                Shape newShape = oldShape.replaceProperty(existing, newProperty);
+                this.setShape(newShape);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public String debugDump(int level) {
+        return debugDump(0, level);
+    }
+
+    public String debugDump(int level, int levelStop) {
+        List<Property> properties = this.getShape().getPropertyListInternal(true);
+        StringBuilder sb = new StringBuilder(properties.size() * 10);
+        sb.append("{\n");
+        for (Property property : properties) {
+            indent(sb, level + 1);
+
+            sb.append(property.getKey());
+            sb.append('[').append(property.getLocation()).append(']');
+            Object value = property.get(this, false);
+            if (value instanceof DynamicObjectImpl) {
+                if (level < levelStop) {
+                    value = ((DynamicObjectImpl) value).debugDump(level + 1, levelStop);
+                } else {
+                    value = value.toString();
+                }
+            }
+            sb.append(": ");
+            sb.append(value);
+            if (property != properties.get(properties.size() - 1)) {
+                sb.append(",");
+            }
+            sb.append("\n");
+        }
+        indent(sb, level);
+        sb.append("}");
+        return sb.toString();
+    }
+
+    private static StringBuilder indent(StringBuilder sb, int level) {
+        for (int i = 0; i < level; i++) {
+            sb.append(' ');
+        }
+        return sb;
+    }
+
+    @Override
+    public String toString() {
+        return getShape().getObjectType().toString(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return getShape().getObjectType().equals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return getShape().getObjectType().hashCode(this);
+    }
+
+    @Override
+    @TruffleBoundary
+    public Object get(Object id, Object defaultValue) {
+        Property existing = getShape().getProperty(id);
+        if (existing != null) {
+            return existing.get(this, false);
+        } else {
+            return defaultValue;
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public boolean set(Object id, Object value) {
+        Property existing = getShape().getProperty(id);
+        if (existing != null) {
+            existing.setGeneric(this, value, null);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public void define(Object id, Object value, int flags) {
+        ShapeImpl oldShape = getShape();
+        Property existing = oldShape.getProperty(id);
+        if (existing == null) {
+            updateShape();
+            oldShape = getShape();
+            Shape newShape = oldShape.addProperty(Property.create(id, oldShape.allocator().locationForValue(value, true, true), flags));
+            updateShape();
+            newShape.getLastProperty().setGeneric(this, value, oldShape, newShape);
+        } else {
+            defineExisting(id, value, flags, existing, oldShape);
+        }
+    }
+
+    private void defineExisting(Object id, Object value, int flags, Property existing, ShapeImpl oldShape) {
+        if (existing.getFlags() == flags) {
+            existing.setGeneric(this, value, null);
+        } else {
+            Property newProperty = Property.create(id, oldShape.getLayout().existingLocationForValue(value, existing.getLocation(), oldShape), flags);
+            Shape newShape = oldShape.replaceProperty(existing, newProperty);
+            this.setShapeAndResize(newShape);
+            newProperty.setInternal(this, value);
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public void define(Object id, Object value, int flags, LocationFactory locationFactory) {
+        ShapeImpl oldShape = getShape();
+        Property existing = oldShape.getProperty(id);
+        if (existing == null) {
+            updateShape();
+            oldShape = getShape();
+            Shape newShape = oldShape.addProperty(Property.create(id, locationFactory.createLocation(oldShape, value), flags));
+            updateShape();
+            newShape.getLastProperty().setGeneric(this, value, oldShape, newShape);
+        } else {
+            defineExisting(id, value, flags, existing, oldShape);
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public boolean delete(Object id) {
+        ShapeImpl oldShape = getShape();
+        Property existing = oldShape.getProperty(id);
+        if (existing != null) {
+            ShapeImpl newShape = oldShape.removeProperty(existing);
+            this.reshapeAfterDelete(newShape, ShapeImpl.findCommonAncestor(oldShape, newShape));
+            // TODO ancestor should be the parent of found property's shape
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int size() {
+        return getShape().getPropertyCount();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    @Override
+    public final boolean updateShape() {
+        return getShape().getLayout().getStrategy().updateShape(this);
+    }
+
+    private static void trackObject(DynamicObject obj) {
+        ShapeProfiler.getInstance().track(obj);
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return getShape().getForeignAccessFactory();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.api.object.Shape.Allocator;
+import com.oracle.truffle.object.LocationImpl.EffectivelyFinalLocation;
+import com.oracle.truffle.object.LocationImpl.TypedObjectLocation;
+import com.oracle.truffle.object.Locations.ConstantLocation;
+import com.oracle.truffle.object.Locations.DeclaredLocation;
+import com.oracle.truffle.object.Locations.DualLocation;
+import com.oracle.truffle.object.Locations.ValueLocation;
+import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
+
+public abstract class LayoutImpl extends Layout {
+    private static final int INT_TO_DOUBLE_FLAG = 1;
+    private static final int INT_TO_LONG_FLAG = 2;
+
+    private final LayoutStrategy strategy;
+    private final Class<? extends DynamicObject> clazz;
+    private final int allowedImplicitCasts;
+
+    protected LayoutImpl(EnumSet<ImplicitCast> allowedImplicitCasts, Class<? extends DynamicObjectImpl> clazz, LayoutStrategy strategy) {
+        this.strategy = strategy;
+        this.clazz = clazz;
+
+        this.allowedImplicitCasts = (allowedImplicitCasts.contains(ImplicitCast.IntToDouble) ? INT_TO_DOUBLE_FLAG : 0) | (allowedImplicitCasts.contains(ImplicitCast.IntToLong) ? INT_TO_LONG_FLAG : 0);
+    }
+
+    @Override
+    public abstract DynamicObject newInstance(Shape shape);
+
+    @Override
+    public Class<? extends DynamicObject> getType() {
+        return clazz;
+    }
+
+    @Override
+    public final Shape createShape(ObjectType operations, Object sharedData) {
+        return createShape(operations, sharedData, 0);
+    }
+
+    @Override
+    public final Shape createShape(ObjectType operations) {
+        return createShape(operations, null);
+    }
+
+    public boolean isAllowedIntToDouble() {
+        return (allowedImplicitCasts & INT_TO_DOUBLE_FLAG) != 0;
+    }
+
+    public boolean isAllowedIntToLong() {
+        return (allowedImplicitCasts & INT_TO_LONG_FLAG) != 0;
+    }
+
+    protected abstract boolean hasObjectExtensionArray();
+
+    protected abstract boolean hasPrimitiveExtensionArray();
+
+    protected abstract int getObjectFieldCount();
+
+    protected abstract int getPrimitiveFieldCount();
+
+    protected abstract Location getObjectArrayLocation();
+
+    protected abstract Location getPrimitiveArrayLocation();
+
+    protected abstract int objectFieldIndex(Location location);
+
+    protected boolean isLocationAssignableFrom(Location destination, Location source) {
+        LayoutImpl layout = this;
+        if (destination.isFinal()) {
+            // allowed Final<X>Location => Final<X>Location
+            // allowed FinalIntLocation => Final{Int,Double}Location
+            // allowed: Final{Int,Double,TypedObject}Location => FinalObjectLocation
+            if (!source.isFinal()) {
+                return false;
+            }
+        }
+
+        if (destination instanceof IntLocation) {
+            return (source instanceof IntLocation);
+        } else if (destination instanceof DoubleLocation) {
+            return (source instanceof DoubleLocation || (layout.isAllowedIntToDouble() && source instanceof IntLocation));
+        } else if (destination instanceof LongLocation) {
+            return (source instanceof LongLocation || (layout.isAllowedIntToLong() && source instanceof IntLocation));
+        } else if (destination instanceof BooleanLocation) {
+            return (source instanceof BooleanLocation);
+        } else if (destination instanceof TypedObjectLocation) {
+            return source instanceof TypedObjectLocation && ((TypedObjectLocation<?>) destination).getType().isAssignableFrom(((TypedObjectLocation<?>) source).getType());
+        } else if (destination instanceof ValueLocation) {
+            return false;
+        } else {
+            assert destination instanceof ObjectLocation || destination instanceof DualLocation;
+            return true;
+        }
+    }
+
+    protected Location existingLocationForValue(Object value, Location oldLocation, Shape oldShape) {
+        assert oldShape.getLayout() == this;
+        Location newLocation;
+        if (oldLocation instanceof IntLocation && value instanceof Integer) {
+            newLocation = oldLocation;
+        } else if (oldLocation instanceof DoubleLocation && (value instanceof Double || this.isAllowedIntToDouble() && value instanceof Integer)) {
+            newLocation = oldLocation;
+        } else if (oldLocation instanceof LongLocation && (value instanceof Long || this.isAllowedIntToLong() && value instanceof Long)) {
+            newLocation = oldLocation;
+        } else if (oldLocation instanceof DeclaredLocation) {
+            return oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull));
+        } else if (oldLocation instanceof ConstantLocation) {
+            return LocationImpl.valueEquals(oldLocation.get(null, false), value) ? oldLocation : new Locations.ConstantLocation(value);
+        } else if (oldLocation instanceof TypedObjectLocation && !((TypedObjectLocation<?>) oldLocation).getType().isAssignableFrom(value.getClass())) {
+            newLocation = (((TypedObjectLocation<?>) oldLocation).toUntypedLocation());
+        } else if (oldLocation instanceof DualLocation) {
+            if (oldLocation.canStore(value)) {
+                newLocation = oldLocation;
+            } else {
+                newLocation = ((BaseAllocator) oldShape.allocator()).locationForValueUpcast(value, oldLocation);
+            }
+        } else if (oldLocation instanceof ObjectLocation) {
+            newLocation = oldLocation;
+        } else {
+            return oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.NonNull));
+        }
+        if (newLocation instanceof EffectivelyFinalLocation) {
+            newLocation = ((EffectivelyFinalLocation<?>) newLocation).toNonFinalLocation();
+        }
+        return newLocation;
+    }
+
+    /**
+     * Is this property an upcast of the other property?
+     *
+     * @param other the property being compared to
+     * @return true if this is a upcast of the other property, false otherwise
+     */
+    public boolean isPropertyUpcastOf(Property thiz, Property other) {
+        if (thiz.getLocation() != null && other.getLocation() != null && other.getKey().equals(thiz.getKey()) && other.getFlags() == thiz.getFlags()) {
+            if (isLocationAssignableFrom(thiz.getLocation(), other.getLocation())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public abstract Allocator createAllocator();
+
+    public LayoutStrategy getStrategy() {
+        return strategy;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LayoutStrategy.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.ShapeImpl.BaseAllocator;
+
+public interface LayoutStrategy {
+    boolean updateShape(DynamicObject object);
+
+    Shape returnCached(Shape newShape);
+
+    Shape ensureSpace(Shape shape, Location location);
+
+    boolean isAutoExtArray();
+
+    Property generalizeProperty(DynamicObject object, Property oldProperty, Object value);
+
+    Property generalizeProperty(DynamicObject object, Property oldProperty, Object value, Shape oldShape, Shape newShape);
+
+    BaseAllocator createAllocator(Layout shape);
+
+    BaseAllocator createAllocator(Shape shape);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/LocationImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import com.oracle.truffle.api.object.*;
+
+public abstract class LocationImpl extends Location {
+
+    public interface EffectivelyFinalLocation<T extends Location> {
+        T toNonFinalLocation();
+    }
+
+    public interface TypedObjectLocation<T extends Location & ObjectLocation> extends ObjectLocation {
+        T toUntypedLocation();
+    }
+
+    public interface InternalLongLocation extends LongLocation {
+        void setLongInternal(DynamicObject store, long value);
+    }
+
+    public interface LocationVisitor {
+        void visitObjectField(int index, int count);
+
+        void visitObjectArray(int index, int count);
+
+        void visitPrimitiveField(int index, int count);
+
+        void visitPrimitiveArray(int index, int count);
+    }
+
+    @Override
+    public void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
+        setInternal(store, value);
+    }
+
+    @Override
+    protected final Object getInternal(DynamicObject store) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    protected abstract void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException;
+
+    @Override
+    public final boolean canSet(DynamicObject store, Object value) {
+        return canStore(value) && canStoreFinal(store, value);
+    }
+
+    @Override
+    public boolean canStore(Object value) {
+        return true;
+    }
+
+    @SuppressWarnings("unused")
+    protected boolean canStoreFinal(DynamicObject store, Object value) {
+        return true;
+    }
+
+    @Override
+    public boolean isFinal() {
+        return false;
+    }
+
+    @Override
+    public boolean isConstant() {
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (isFinal() ? 1231 : 1237);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Location other = (Location) obj;
+        if (isFinal() != other.isFinal()) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        String finalString = isFinal() ? "f" : "";
+        String typeString = this instanceof IntLocation ? "i" : (this instanceof DoubleLocation ? "d" : (this instanceof BooleanLocation ? "b"
+                        : (this instanceof TypedLocation ? ((TypedLocation) this).getType().getSimpleName() : "o")));
+        return finalString + typeString + getWhereString();
+    }
+
+    protected String getWhereString() {
+        return "";
+    }
+
+    /**
+     * Get the number of object array elements this location requires.
+     */
+    public int objectArrayCount() {
+        return 0;
+    }
+
+    /**
+     * Get the number of in-object {@link Object} fields this location requires.
+     */
+    public int objectFieldCount() {
+        return 0;
+    }
+
+    /**
+     * Get the number of in-object primitive fields this location requires.
+     */
+    public int primitiveFieldCount() {
+        return 0;
+    }
+
+    /**
+     * Get the number of primitive array elements this location requires.
+     */
+    public int primitiveArrayCount() {
+        return 0;
+    }
+
+    /**
+     * Accept a visitor for location allocation for this and every nested location.
+     *
+     * @param locationVisitor visitor to be notified of every allocated slot in use by this location
+     */
+    public abstract void accept(LocationVisitor locationVisitor);
+
+    /**
+     * Boxed values need to be compared by value not by reference.
+     *
+     * The first parameter should be the one with the more precise type information.
+     *
+     * For sets to final locations, otherValue.equals(thisValue) seems more beneficial, since we
+     * usually know more about the value to be set.
+     */
+    public static boolean valueEquals(Object val1, Object val2) {
+        return val1 == val2 || (val1 != null && val1.equals(val2));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Locations.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.object.*;
+
+/**
+ * Property location.
+ *
+ * @see Location
+ * @see Shape
+ * @see Property
+ * @see DynamicObject
+ */
+public abstract class Locations {
+    public abstract static class ValueLocation extends LocationImpl {
+
+        private final Object value;
+
+        public ValueLocation(Object value) {
+            assert !(value instanceof Location);
+            this.value = value;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + ((value == null) ? 0 : 0 /* value.hashCode() */);
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!super.equals(obj)) {
+                return false;
+            }
+            ValueLocation other = (ValueLocation) obj;
+            if (value == null) {
+                if (other.value != null) {
+                    return false;
+                }
+            } else if (!value.equals(other.value)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public final Object get(DynamicObject store, boolean condition) {
+            return value;
+        }
+
+        @Override
+        public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
+            if (!canStoreFinal(store, value)) {
+                throw finalLocation();
+            }
+        }
+
+        @Override
+        protected boolean canStoreFinal(DynamicObject store, Object val) {
+            return valueEquals(this.value, val);
+        }
+
+        @Override
+        public final void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (!canStoreFinal(store, value)) {
+                CompilerDirectives.transferToInterpreter();
+                throw new UnsupportedOperationException();
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "=" + String.valueOf(value);
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+        }
+    }
+
+    public static final class ConstantLocation extends ValueLocation {
+
+        public ConstantLocation(Object value) {
+            super(value);
+        }
+
+        @Override
+        public boolean isConstant() {
+            return true;
+        }
+    }
+
+    public static final class DeclaredLocation extends ValueLocation {
+
+        public DeclaredLocation(Object value) {
+            super(value);
+        }
+    }
+
+    public static class DualLocation extends LocationImpl implements TypedLocation {
+        protected final InternalLongLocation primitiveLocation;
+        protected final ObjectLocation objectLocation;
+        protected final LayoutImpl layout;
+        private final Class<?> type;
+
+        public DualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, LayoutImpl layout) {
+            this(primitiveLocation, objectLocation, layout, null);
+        }
+
+        public DualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, LayoutImpl layout, Class<?> type) {
+            this.primitiveLocation = primitiveLocation;
+            this.objectLocation = objectLocation;
+            this.layout = layout;
+            this.type = type;
+        }
+
+        @Override
+        public Object get(DynamicObject store, boolean condition) {
+            if (type == Object.class) {
+                return objectLocation.get(store, condition);
+            } else {
+                long rawValue = primitiveLocation.getLong(store, condition);
+                if (type == int.class) {
+                    return (int) rawValue;
+                } else if (type == long.class) {
+                    return rawValue;
+                } else if (type == double.class) {
+                    return Double.longBitsToDouble(rawValue);
+                } else if (type == boolean.class) {
+                    return rawValue != 0;
+                } else {
+                    CompilerDirectives.transferToInterpreter();
+                    throw new IllegalStateException();
+                }
+            }
+        }
+
+        @Override
+        public void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (type == Object.class) {
+                ((LocationImpl) objectLocation).setInternal(store, value);
+            } else {
+                long rawValue;
+                if (type == int.class && value instanceof Integer) {
+                    rawValue = (int) value;
+                } else if (type == long.class && value instanceof Long) {
+                    rawValue = (long) value;
+                } else if (type == long.class && layout.isAllowedIntToLong() && value instanceof Integer) {
+                    rawValue = (int) value;
+                } else if (type == double.class && value instanceof Double) {
+                    rawValue = Double.doubleToRawLongBits((double) value);
+                } else if (type == double.class && layout.isAllowedIntToDouble() && value instanceof Integer) {
+                    rawValue = Double.doubleToRawLongBits((int) value);
+                } else if (type == boolean.class && value instanceof Boolean) {
+                    rawValue = (boolean) value ? 1 : 0;
+                } else {
+                    throw incompatibleLocation();
+                }
+
+                primitiveLocation.setLongInternal(store, rawValue);
+            }
+        }
+
+        @Override
+        public int primitiveFieldCount() {
+            return ((LocationImpl) primitiveLocation).primitiveFieldCount();
+        }
+
+        @Override
+        public int primitiveArrayCount() {
+            return ((LocationImpl) primitiveLocation).primitiveArrayCount();
+        }
+
+        @Override
+        public int objectFieldCount() {
+            return ((LocationImpl) objectLocation).objectFieldCount();
+        }
+
+        @Override
+        public int objectArrayCount() {
+            return ((LocationImpl) objectLocation).objectArrayCount();
+        }
+
+        @Override
+        public final void accept(LocationVisitor locationVisitor) {
+            ((LocationImpl) primitiveLocation).accept(locationVisitor);
+            ((LocationImpl) objectLocation).accept(locationVisitor);
+        }
+
+        @Override
+        public String toString() {
+            return objectLocation.toString() + "," + primitiveLocation.toString() + "," + type;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!super.equals(obj)) {
+                return false;
+            }
+            DualLocation other = (DualLocation) obj;
+            return getObjectLocation().equals(other.getObjectLocation()) && primitiveLocation.equals(other.primitiveLocation) && layout.equals(other.layout) && Objects.equals(type, other.type);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + (getObjectLocation() == null ? 0 : getObjectLocation().hashCode());
+            result = prime * result + (primitiveLocation == null ? 0 : primitiveLocation.hashCode());
+            result = prime * result + (type == null ? 0 : type.hashCode());
+            return result;
+        }
+
+        public ObjectLocation getObjectLocation() {
+            return objectLocation;
+        }
+
+        public DualLocation changeType(Class<?> newType) {
+            return new DualLocation(primitiveLocation, objectLocation, layout, newType);
+        }
+
+        public Class<?> getType() {
+            return type;
+        }
+
+        public boolean isNonNull() {
+            return false;
+        }
+
+        @Override
+        public boolean canStore(Object value) {
+            if (type == null) {
+                return false;
+            } else if (type == int.class) {
+                return value instanceof Integer;
+            } else if (type == long.class) {
+                return value instanceof Long || (layout.isAllowedIntToLong() && value instanceof Integer);
+            } else if (type == double.class) {
+                return value instanceof Double || (layout.isAllowedIntToDouble() && value instanceof Integer);
+            } else if (type == boolean.class) {
+                return value instanceof Boolean;
+            } else if (type == Object.class) {
+                return true;
+            } else {
+                throw new IllegalStateException();
+            }
+        }
+    }
+
+    public static class DeclaredDualLocation extends DualLocation {
+        private final Object defaultValue;
+
+        public DeclaredDualLocation(InternalLongLocation primitiveLocation, ObjectLocation objectLocation, Object defaultValue, LayoutImpl layout) {
+            super(primitiveLocation, objectLocation, layout);
+            this.defaultValue = defaultValue;
+        }
+
+        @Override
+        public Object get(DynamicObject store, boolean condition) {
+            return defaultValue;
+        }
+
+        @Override
+        public void setInternal(DynamicObject store, Object value) throws IncompatibleLocationException {
+            if (valueEquals(defaultValue, value)) {
+                return;
+            } else {
+                throw incompatibleLocation();
+            }
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return super.equals(obj) && Objects.equals(defaultValue, ((DeclaredDualLocation) obj).defaultValue);
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode();
+        }
+
+        @Override
+        public DualLocation changeType(Class<?> newType) {
+            return new DualLocation(primitiveLocation, objectLocation, layout, newType);
+        }
+
+        @Override
+        public boolean canStore(Object value) {
+            return valueEquals(defaultValue, value);
+        }
+
+        @Override
+        public String toString() {
+            return objectLocation.toString() + "," + primitiveLocation.toString() + ",unset";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ObjectStorageOptions.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import static com.oracle.truffle.api.object.Layout.*;
+
+public class ObjectStorageOptions {
+    // Shape configuration
+    /** Primitive location switch. */
+    public static boolean PrimitiveLocations = booleanOption(OPTION_PREFIX + "PrimitiveLocations", true);
+    public static boolean IntegerLocations = booleanOption(OPTION_PREFIX + "IntegerLocations", true);
+    public static boolean DoubleLocations = booleanOption(OPTION_PREFIX + "DoubleLocations", true);
+    public static boolean LongLocations = booleanOption(OPTION_PREFIX + "LongLocations", true);
+    public static boolean BooleanLocations = booleanOption(OPTION_PREFIX + "BooleanLocations", true);
+    public static boolean TypedObjectLocations = booleanOption(OPTION_PREFIX + "TypedObjectLocations", true);
+
+    /** Allocation of in-object fields. */
+    public static boolean InObjectFields = booleanOption(OPTION_PREFIX + "InObjectFields", true);
+
+    // Debug options (should be final)
+    public static final boolean TraceReshape = booleanOption(OPTION_PREFIX + "TraceReshape", false);
+    public static final boolean DumpShapes = booleanOption(OPTION_PREFIX + "DumpShapes", false);
+
+    public static final boolean Profile = booleanOption(OPTION_PREFIX + "Profile", false);
+    public static final int ProfileTopResults = Integer.getInteger(OPTION_PREFIX + "ProfileTopResults", -1);
+
+    public static boolean booleanOption(String name, boolean defaultValue) {
+        String value = System.getProperty(name);
+        return value == null ? defaultValue : value.equalsIgnoreCase("true");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.Locations.DeclaredLocation;
+
+/**
+ * Property objects represent the mapping between property identifiers (keys) and storage locations.
+ * Optionally, properties may have metadata attached to them.
+ */
+public class PropertyImpl extends Property {
+    private final Object key;
+    private final Location location;
+    private final int flags;
+    private final boolean shadow;
+    private final boolean relocatable;
+
+    /**
+     * Generic, usual-case constructor for properties storing at least a name.
+     *
+     * @param key the name of the property
+     * @param location the storage location used to access the property
+     * @param flags property flags (optional)
+     */
+    protected PropertyImpl(Object key, Location location, int flags, boolean shadow, boolean relocatable) {
+        this.key = Objects.requireNonNull(key);
+        this.location = Objects.requireNonNull(location);
+        this.flags = flags;
+        this.shadow = shadow;
+        this.relocatable = relocatable;
+    }
+
+    public PropertyImpl(Object name, Location location, int flags) {
+        this(name, location, flags, false, true);
+    }
+
+    @Override
+    public final Object getKey() {
+        return key;
+    }
+
+    @Override
+    public int getFlags() {
+        return flags;
+    }
+
+    @Override
+    public Property relocate(Location newLocation) {
+        if (!getLocation().equals(newLocation) && relocatable) {
+            return construct(key, newLocation, flags);
+        }
+        return this;
+    }
+
+    @Override
+    public final Object get(DynamicObject store, Shape shape) {
+        return getLocation().get(store, shape);
+    }
+
+    @Override
+    public final Object get(DynamicObject store, boolean condition) {
+        return getLocation().get(store, condition);
+    }
+
+    @Override
+    public final void setInternal(DynamicObject store, Object value) {
+        try {
+            ((LocationImpl) getLocation()).setInternal(store, value);
+        } catch (IncompatibleLocationException e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public final void set(DynamicObject store, Object value, Shape shape) throws IncompatibleLocationException, FinalLocationException {
+        assert shape == null || store.getShape() == shape : "wrong shape";
+        getLocation().set(store, value, shape);
+    }
+
+    @Override
+    public final void setSafe(DynamicObject store, Object value, Shape shape) {
+        assert shape == null || store.getShape() == shape : "wrong shape";
+        try {
+            getLocation().set(store, value, shape);
+        } catch (IncompatibleLocationException | FinalLocationException ex) {
+            throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public final void setGeneric(DynamicObject store, Object value, Shape shape) {
+        assert shape == null || store.getShape() == shape : "wrong shape";
+        try {
+            set(store, value, shape);
+        } catch (IncompatibleLocationException | FinalLocationException ex) {
+            setSlowCase(store, value);
+        }
+    }
+
+    @Override
+    public final void set(DynamicObject store, Object value, Shape oldShape, Shape newShape) throws IncompatibleLocationException {
+        assert store.getShape() == oldShape : "wrong shape";
+        assert newShape.isValid();
+        assert getLocation() != null;
+        getLocation().set(store, value, oldShape, newShape);
+    }
+
+    @Override
+    public final void setSafe(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
+        assert store.getShape() == oldShape : "wrong old shape";
+        assert newShape.isValid();
+        assert getLocation() != null;
+        try {
+            getLocation().set(store, value, oldShape, newShape);
+        } catch (IncompatibleLocationException ex) {
+            throw new IllegalStateException();
+        }
+    }
+
+    @Override
+    public final void setGeneric(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
+        assert store.getShape() == oldShape : "wrong old shape";
+        assert newShape.isValid();
+        assert getLocation() != null;
+        try {
+            getLocation().set(store, value, oldShape, newShape);
+        } catch (IncompatibleLocationException ex) {
+            setWithShapeSlowCase(store, value, oldShape, newShape);
+        }
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        PropertyImpl other = (PropertyImpl) obj;
+        return key.equals(other.key) && location.equals(other.location) && flags == other.flags && shadow == other.shadow && relocatable == other.relocatable;
+    }
+
+    @Override
+    public boolean isSame(Property obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        PropertyImpl other = (PropertyImpl) obj;
+        return key.equals(other.key) && flags == other.flags;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + getClass().hashCode();
+        result = prime * result + key.hashCode();
+        result = prime * result + location.hashCode();
+        result = prime * result + flags;
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "\"" + key + "\"" + ":" + location;
+    }
+
+    @Override
+    public final Location getLocation() {
+        return location;
+    }
+
+    private void setSlowCase(DynamicObject store, Object value) {
+        if (getLocation() instanceof DeclaredLocation) {
+            setDeclaredLocation(store, value);
+        } else {
+            generalize(store, value);
+        }
+    }
+
+    private void setDeclaredLocation(DynamicObject store, Object value) {
+        store.updateShape();
+        Shape oldShape = store.getShape();
+        Shape newShape = oldShape.addProperty(this.relocateShadow(oldShape.allocator().locationForValue(value, EnumSet.of(LocationModifier.Final, LocationModifier.NonNull))));
+        store.updateShape();
+        newShape.getLastProperty().setGeneric(store, value, oldShape, newShape);
+    }
+
+    private Property generalize(DynamicObject store, Object value) {
+        return ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value);
+    }
+
+    private void setWithShapeSlowCase(DynamicObject store, Object value, Shape oldShape, Shape newShape) {
+        ((LayoutImpl) store.getShape().getLayout()).getStrategy().generalizeProperty(store, this, value, oldShape, newShape);
+    }
+
+    @Override
+    public final boolean isHidden() {
+        return key instanceof HiddenKey;
+    }
+
+    @Override
+    public final boolean isShadow() {
+        return shadow;
+    }
+
+    private Property relocateShadow(Location newLocation) {
+        assert !isShadow() && getLocation() instanceof DeclaredLocation && relocatable;
+        return new PropertyImpl(key, newLocation, flags, true, relocatable);
+    }
+
+    @SuppressWarnings("hiding")
+    protected Property construct(Object name, Location location, int flags) {
+        return new PropertyImpl(name, location, flags, shadow, relocatable);
+    }
+
+    @Override
+    public Property copyWithFlags(int newFlags) {
+        return construct(key, location, newFlags);
+    }
+
+    @Override
+    public Property copyWithRelocatable(boolean newRelocatable) {
+        if (this.relocatable != newRelocatable) {
+            return new PropertyImpl(key, location, flags, shadow, newRelocatable);
+        }
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/PropertyMap.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+
+public final class PropertyMap implements Map<Object, Property> {
+    private final PropertyMap car;
+    private final Property cdr;
+    private final int size;
+
+    private static final PropertyMap EMPTY = new PropertyMap();
+
+    private PropertyMap() {
+        this.car = null;
+        this.cdr = null;
+        this.size = 0;
+    }
+
+    private PropertyMap(PropertyMap parent, Property added) {
+        this.car = Objects.requireNonNull(parent);
+        this.cdr = added;
+        this.size = parent.size + 1;
+    }
+
+    public static PropertyMap empty() {
+        return EMPTY;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    public boolean containsKey(Object key) {
+        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getKey().equals(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean containsValue(Object value) {
+        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getValue().equals(value)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Property get(Object key) {
+        for (Map.Entry<Object, Property> entry : reverseOrderEntrySet()) {
+            if (entry.getKey().equals(key)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    public Property put(Object key, Property value) {
+        throw unmodifiableException();
+    }
+
+    public Property remove(Object key) {
+        throw unmodifiableException();
+    }
+
+    public void putAll(Map<? extends Object, ? extends Property> m) {
+        throw unmodifiableException();
+    }
+
+    public void clear() {
+        throw unmodifiableException();
+    }
+
+    public Set<Object> keySet() {
+        return new AbstractSet<Object>() {
+            @Override
+            public Iterator<Object> iterator() {
+                Object[] keys = new Object[size()];
+                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
+                for (int pos = size() - 1; pos >= 0; pos--) {
+                    keys[pos] = iterator.next().getKey();
+                }
+                return Arrays.asList(keys).iterator();
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    public Collection<Property> values() {
+        return new AbstractSet<Property>() {
+            @Override
+            public Iterator<Property> iterator() {
+                Property[] values = new Property[size()];
+                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
+                for (int pos = size() - 1; pos >= 0; pos--) {
+                    values[pos] = iterator.next().getValue();
+                }
+                return Arrays.asList(values).iterator();
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    public Set<Map.Entry<Object, Property>> entrySet() {
+        return new AbstractSet<Map.Entry<Object, Property>>() {
+            @Override
+            public Iterator<Map.Entry<Object, Property>> iterator() {
+                @SuppressWarnings("unchecked")
+                Map.Entry<Object, Property>[] entries = (Map.Entry<Object, Property>[]) new Map.Entry<?, ?>[size()];
+                Iterator<Map.Entry<Object, Property>> iterator = reverseOrderEntrySet().iterator();
+                for (int pos = size() - 1; pos >= 0; pos--) {
+                    entries[pos] = iterator.next();
+                }
+                return Arrays.asList(entries).iterator();
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    public Set<Map.Entry<Object, Property>> reverseOrderEntrySet() {
+        return new AbstractSet<Map.Entry<Object, Property>>() {
+            @Override
+            public Iterator<Map.Entry<Object, Property>> iterator() {
+                return new Iterator<Map.Entry<Object, Property>>() {
+                    PropertyMap current = PropertyMap.this;
+
+                    public Entry<Object, Property> next() {
+                        if (hasNext()) {
+                            try {
+                                return new MapEntryImpl(current.cdr);
+                            } finally {
+                                current = current.car;
+                            }
+                        } else {
+                            throw new NoSuchElementException();
+                        }
+                    }
+
+                    public boolean hasNext() {
+                        return current != empty();
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    public Set<Object> reverseOrderKeys() {
+        return new AbstractSet<Object>() {
+            @Override
+            public Iterator<Object> iterator() {
+                return new Iterator<Object>() {
+                    PropertyMap current = PropertyMap.this;
+
+                    public Object next() {
+                        if (hasNext()) {
+                            try {
+                                return current.cdr.getKey();
+                            } finally {
+                                current = current.car;
+                            }
+                        } else {
+                            throw new NoSuchElementException();
+                        }
+                    }
+
+                    public boolean hasNext() {
+                        return current != empty();
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    public Set<Property> reverseOrderValues() {
+        return new AbstractSet<Property>() {
+            @Override
+            public Iterator<Property> iterator() {
+                return new Iterator<Property>() {
+                    PropertyMap current = PropertyMap.this;
+
+                    public Property next() {
+                        if (hasNext()) {
+                            try {
+                                return current.cdr;
+                            } finally {
+                                current = current.car;
+                            }
+                        } else {
+                            throw new NoSuchElementException();
+                        }
+                    }
+
+                    public boolean hasNext() {
+                        return current != empty();
+                    }
+
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+
+            @Override
+            public int size() {
+                return PropertyMap.this.size();
+            }
+        };
+    }
+
+    private static final class MapEntryImpl implements Map.Entry<Object, Property> {
+        private final Property backingProperty;
+
+        public MapEntryImpl(Property backingProperty) {
+            this.backingProperty = backingProperty;
+        }
+
+        public Object getKey() {
+            return backingProperty.getKey();
+        }
+
+        public Property getValue() {
+            return backingProperty;
+        }
+
+        public Property setValue(Property value) {
+            throw unmodifiableException();
+        }
+    }
+
+    private static UnsupportedOperationException unmodifiableException() {
+        throw new UnsupportedOperationException("unmodifiable");
+    }
+
+    public PropertyMap putCopy(Property value) {
+        return new PropertyMap(this, value);
+    }
+
+    public PropertyMap removeCopy(Property value) {
+        Deque<Property> shelve = new ArrayDeque<>();
+        PropertyMap current = this;
+        while (!current.isEmpty()) {
+            if (current.getLastProperty().equals(value)) {
+                PropertyMap newMap = current.getParentMap();
+                for (Property property : shelve) {
+                    newMap = newMap.putCopy(property);
+                }
+                return newMap;
+            } else {
+                shelve.push(current.getLastProperty());
+                current = current.getParentMap();
+            }
+        }
+        return this;
+    }
+
+    public PropertyMap replaceCopy(Property oldValue, Property newValue) {
+        Deque<Property> shelve = new ArrayDeque<>();
+        PropertyMap current = this;
+        while (!current.isEmpty()) {
+            if (current.getLastProperty().equals(oldValue)) {
+                PropertyMap newMap = current.getParentMap();
+                newMap = newMap.putCopy(newValue);
+                for (Property property : shelve) {
+                    newMap = newMap.putCopy(property);
+                }
+                return newMap;
+            } else {
+                shelve.push(current.getLastProperty());
+                current = current.getParentMap();
+            }
+        }
+        return this;
+    }
+
+    public PropertyMap getOwningMap(Property value) {
+        PropertyMap current = this;
+        while (!current.isEmpty()) {
+            if (current.getLastProperty().equals(value)) {
+                return current;
+            }
+            current = current.getParentMap();
+        }
+        return null;
+    }
+
+    PropertyMap getParentMap() {
+        return car;
+    }
+
+    public Property getLastProperty() {
+        return cdr;
+    }
+
+    @Override
+    public String toString() {
+        return values().toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1074 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.object.LocationImpl.InternalLongLocation;
+import com.oracle.truffle.object.LocationImpl.LocationVisitor;
+import com.oracle.truffle.object.Locations.ConstantLocation;
+import com.oracle.truffle.object.Locations.DeclaredDualLocation;
+import com.oracle.truffle.object.Locations.DeclaredLocation;
+import com.oracle.truffle.object.Locations.DualLocation;
+import com.oracle.truffle.object.Locations.ValueLocation;
+import com.oracle.truffle.object.Transition.AddPropertyTransition;
+import com.oracle.truffle.object.Transition.DirectReplacePropertyTransition;
+import com.oracle.truffle.object.Transition.ObjectTypeTransition;
+import com.oracle.truffle.object.Transition.PropertyTransition;
+import com.oracle.truffle.object.Transition.RemovePropertyTransition;
+import com.oracle.truffle.object.Transition.ReservePrimitiveArrayTransition;
+
+/**
+ * Shape objects create a mapping of Property objects to indexes. The mapping of those indexes to an
+ * actual store is not part of Shape's role, but JSObject's. Shapes are immutable; adding or
+ * deleting a property yields a new Shape which links to the old one. This allows inline caching to
+ * simply check the identity of an object's Shape to determine if the cache is valid. There is one
+ * exception to this immutability, the transition map, but that is used simply to assure that an
+ * identical series of property additions and deletions will yield the same Shape object.
+ *
+ * @see DynamicObject
+ * @see Property
+ * @see Locations
+ */
+public abstract class ShapeImpl extends Shape {
+    private final int id;
+
+    protected final LayoutImpl layout;
+    protected final ObjectType objectType;
+    protected final ShapeImpl parent;
+    protected final PropertyMap propertyMap;
+
+    private final Object extraData;
+    private final Object sharedData;
+    private final ShapeImpl root;
+
+    protected final int objectArraySize;
+    protected final int objectArrayCapacity;
+    protected final int objectFieldSize;
+    protected final int primitiveFieldSize;
+    protected final int primitiveArraySize;
+    protected final int primitiveArrayCapacity;
+    protected final boolean hasPrimitiveArray;
+
+    protected final int depth;
+    protected final int propertyCount;
+
+    protected final Assumption validAssumption;
+    @CompilationFinal protected volatile Assumption leafAssumption;
+
+    /**
+     * Shape transition map; lazily initialized.
+     *
+     * @see #getTransitionMapForRead()
+     * @see #getTransitionMapForWrite()
+     */
+    private volatile Map<Transition, ShapeImpl> transitionMap;
+
+    private final Transition transitionFromParent;
+
+    /**
+     * Private constructor.
+     *
+     * @param parent predecessor shape
+     * @param transitionFromParent direct transition from parent shape
+     * @see #ShapeImpl(Layout, ShapeImpl, ObjectType, Object, PropertyMap, Transition,
+     *      BaseAllocator, int)
+     */
+    private ShapeImpl(Layout layout, ShapeImpl parent, ObjectType objectType, Object sharedData, PropertyMap propertyMap, Transition transitionFromParent, int objectArraySize, int objectFieldSize,
+                    int primitiveFieldSize, int primitiveArraySize, boolean hasPrimitiveArray, int id) {
+        this.layout = (LayoutImpl) layout;
+        this.objectType = Objects.requireNonNull(objectType);
+        this.propertyMap = Objects.requireNonNull(propertyMap);
+        this.root = parent != null ? parent.getRoot() : this;
+        this.parent = parent;
+        this.transitionFromParent = transitionFromParent;
+        this.objectArraySize = objectArraySize;
+        this.objectArrayCapacity = capacityFromSize(objectArraySize);
+        this.objectFieldSize = objectFieldSize;
+        this.primitiveFieldSize = primitiveFieldSize;
+        this.primitiveArraySize = primitiveArraySize;
+        this.primitiveArrayCapacity = capacityFromSize(primitiveArraySize);
+        this.hasPrimitiveArray = hasPrimitiveArray;
+
+        if (parent != null) {
+            this.propertyCount = makePropertyCount(parent, propertyMap);
+            this.depth = parent.depth + 1;
+        } else {
+            this.propertyCount = 0;
+            this.depth = 0;
+        }
+
+        this.validAssumption = createValidAssumption();
+
+        this.id = id;
+        shapeCount.inc();
+
+        this.sharedData = sharedData;
+        this.extraData = objectType.createShapeData(this);
+
+        debugRegisterShape(this);
+    }
+
+    protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
+        this(layout, parent, operations, sharedData, propertyMap, transition, ((BaseAllocator) allocator).objectArraySize, ((BaseAllocator) allocator).objectFieldSize,
+                        ((BaseAllocator) allocator).primitiveFieldSize, ((BaseAllocator) allocator).primitiveArraySize, ((BaseAllocator) allocator).hasPrimitiveArray, id);
+    }
+
+    @SuppressWarnings("hiding")
+    protected abstract ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Transition transition, Allocator allocator, int id);
+
+    protected ShapeImpl(Layout layout, ObjectType operations, Object sharedData, int id) {
+        this(layout, null, operations, sharedData, PropertyMap.empty(), null, layout.createAllocator(), id);
+    }
+
+    private static int makePropertyCount(ShapeImpl parent, PropertyMap propertyMap) {
+        return parent.propertyCount + ((propertyMap.size() > parent.propertyMap.size() && !propertyMap.getLastProperty().isHidden() && !propertyMap.getLastProperty().isShadow()) ? 1 : 0);
+    }
+
+    @Override
+    public final Property getLastProperty() {
+        return propertyMap.getLastProperty();
+    }
+
+    @Override
+    public final int getId() {
+        return this.id;
+    }
+
+    /**
+     * Calculate array size for the given number of elements.
+     */
+    private static int capacityFromSize(int size) {
+        if (size == 0) {
+            return 0;
+        } else if (size < 4) {
+            return 4;
+        } else if (size < 32) {
+            return ((size + 7) / 8) * 8;
+        } else {
+            return ((size + 15) / 16) * 16;
+        }
+    }
+
+    @Override
+    public final int getObjectArraySize() {
+        return objectArraySize;
+    }
+
+    @Override
+    public final int getObjectFieldSize() {
+        return objectFieldSize;
+    }
+
+    @Override
+    public final int getPrimitiveFieldSize() {
+        return primitiveFieldSize;
+    }
+
+    @Override
+    public final int getObjectArrayCapacity() {
+        return objectArrayCapacity;
+    }
+
+    @Override
+    public final int getPrimitiveArrayCapacity() {
+        return primitiveArrayCapacity;
+    }
+
+    @Override
+    public final int getPrimitiveArraySize() {
+        return primitiveArraySize;
+    }
+
+    @Override
+    public final boolean hasPrimitiveArray() {
+        return hasPrimitiveArray;
+    }
+
+    /**
+     * Get the (parent) shape that holds the given property.
+     */
+    public final ShapeImpl getShapeFromProperty(Object propertyName) {
+        ShapeImpl current = this;
+        while (current != getRoot()) {
+            if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().getKey().equals(propertyName)) {
+                return current;
+            }
+            current = current.getParent();
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the (parent) shape that holds the given property.
+     */
+    public final ShapeImpl getShapeFromProperty(Property prop) {
+        ShapeImpl current = this;
+        while (current != getRoot()) {
+            if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().equals(prop)) {
+                return current;
+            }
+            current = current.parent;
+        }
+
+        return null;
+    }
+
+    /**
+     * Get a property entry by string name.
+     *
+     * @param key the name to look up
+     * @return a Property object, or null if not found
+     */
+    @Override
+    @TruffleBoundary
+    public Property getProperty(Object key) {
+        return propertyMap.get(key);
+    }
+
+    protected final void addDirectTransition(Transition transition, ShapeImpl next) {
+        assert next.getParent() == this && transition.isDirect();
+        addTransitionInternal(transition, next);
+    }
+
+    public final void addIndirectTransition(Transition transition, ShapeImpl next) {
+        assert next.getParent() != this && !transition.isDirect();
+        addTransitionInternal(transition, next);
+    }
+
+    private void addTransitionInternal(Transition transition, ShapeImpl next) {
+        getTransitionMapForWrite().put(transition, next);
+    }
+
+    public final Map<Transition, ShapeImpl> getTransitionMapForRead() {
+        return transitionMap != null ? transitionMap : Collections.<Transition, ShapeImpl> emptyMap();
+    }
+
+    private Map<Transition, ShapeImpl> getTransitionMapForWrite() {
+        if (transitionMap != null) {
+            return transitionMap;
+        } else {
+            synchronized (getMutex()) {
+                if (transitionMap != null) {
+                    return transitionMap;
+                }
+                invalidateLeafAssumption();
+                return transitionMap = new ConcurrentHashMap<>();
+            }
+        }
+    }
+
+    public final PropertyMap getPropertyMap() {
+        return propertyMap;
+    }
+
+    protected final ShapeImpl queryTransition(Transition transition) {
+        ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition);
+        if (cachedShape != null) { // Shape already exists?
+            shapeCacheHitCount.inc();
+            return (ShapeImpl) layout.getStrategy().returnCached(cachedShape);
+        }
+        shapeCacheMissCount.inc();
+
+        return null;
+    }
+
+    /**
+     * Add a new property in the map, yielding a new or cached Shape object.
+     *
+     * @param property the property to add
+     * @return the new Shape
+     */
+    @TruffleBoundary
+    @Override
+    public ShapeImpl addProperty(Property property) {
+        assert isValid();
+        onPropertyTransition(property);
+        return addPropertyInternal(property);
+    }
+
+    private void onPropertyTransition(Property property) {
+        if (sharedData instanceof ShapeListener) {
+            ((ShapeListener) sharedData).onPropertyTransition(property.getKey());
+        }
+    }
+
+    /**
+     * Add a new property in the map, yielding a new or cached Shape object.
+     *
+     * In contrast to {@link ShapeImpl#addProperty(Property)}, this method does not care about
+     * obsolete shapes.
+     *
+     * @see #addProperty(Property)
+     */
+    private ShapeImpl addPropertyInternal(Property prop) {
+        CompilerAsserts.neverPartOfCompilation();
+        assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property " + prop.getKey();
+
+        AddPropertyTransition addTransition = new AddPropertyTransition(prop);
+        ShapeImpl cachedShape = queryTransition(addTransition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+
+        ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, prop.getLocation());
+
+        ShapeImpl newShape = makeShapeWithAddedProperty(oldShape, addTransition);
+        oldShape.addDirectTransition(addTransition, newShape);
+        return newShape;
+    }
+
+    protected ShapeImpl cloneRoot(ShapeImpl from, Object newSharedData) {
+        return createShape(from.layout, newSharedData, null, from.objectType, from.propertyMap, null, from.allocator(), from.id);
+    }
+
+    /**
+     * Create a separate clone of a shape.
+     *
+     * @param newParent the cloned parent shape
+     */
+    protected final ShapeImpl cloneOnto(ShapeImpl newParent) {
+        ShapeImpl from = this;
+        ShapeImpl newShape = createShape(newParent.layout, newParent.sharedData, newParent, from.objectType, from.propertyMap, from.transitionFromParent, from.allocator(), newParent.id);
+
+        shapeCloneCount.inc();
+
+        // (aw) need to have this transition for obsolescence
+        newParent.addDirectTransition(from.transitionFromParent, newShape);
+        return newShape;
+    }
+
+    public final Transition getTransitionFromParent() {
+        return transitionFromParent;
+    }
+
+    /**
+     * Create a new shape that adds a property to the parent shape.
+     */
+    private static ShapeImpl makeShapeWithAddedProperty(ShapeImpl parent, AddPropertyTransition addTransition) {
+        Property addend = addTransition.getProperty();
+        BaseAllocator allocator = parent.allocator().addLocation(addend.getLocation());
+
+        PropertyMap newPropertyMap = parent.propertyMap.putCopy(addend);
+
+        ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, newPropertyMap, addTransition, allocator, parent.id);
+        assert ((LocationImpl) addend.getLocation()).primitiveArrayCount() == 0 || newShape.hasPrimitiveArray;
+        assert newShape.depth == allocator.depth;
+        return newShape;
+    }
+
+    /**
+     * Create a new shape that reserves the primitive extension array field.
+     */
+    private static ShapeImpl makeShapeWithPrimitiveExtensionArray(ShapeImpl parent, Transition transition) {
+        assert parent.getLayout().hasPrimitiveExtensionArray();
+        assert !parent.hasPrimitiveArray();
+        BaseAllocator allocator = parent.allocator().addLocation(parent.getLayout().getPrimitiveArrayLocation());
+        ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, parent.propertyMap, transition, allocator, parent.id);
+        assert newShape.hasPrimitiveArray();
+        assert newShape.depth == allocator.depth;
+        return newShape;
+    }
+
+    private ShapeImpl addPrimitiveExtensionArray() {
+        assert layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray();
+        Transition transition = new ReservePrimitiveArrayTransition();
+        ShapeImpl cachedShape = queryTransition(transition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+
+        ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, layout.getPrimitiveArrayLocation());
+        ShapeImpl newShape = makeShapeWithPrimitiveExtensionArray(oldShape, transition);
+        oldShape.addDirectTransition(transition, newShape);
+        return newShape;
+    }
+
+    /**
+     * Are these two shapes related, i.e. do they have the same root?
+     *
+     * @param other Shape to compare to
+     * @return true if one shape is an upcast of the other, or the Shapes are equal
+     */
+    @Override
+    public boolean isRelated(Shape other) {
+        if (this == other) {
+            return true;
+        }
+        if (this.getRoot() == getRoot()) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Get a list of all properties that this Shape stores.
+     *
+     * @return list of properties
+     */
+    @TruffleBoundary
+    @Override
+    public final List<Property> getPropertyList(Pred<Property> filter) {
+        LinkedList<Property> props = new LinkedList<>();
+        next: for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
+            if (!currentProperty.isHidden() && filter.test(currentProperty)) {
+                if (currentProperty.getLocation() instanceof DeclaredLocation) {
+                    for (Iterator<Property> iter = props.iterator(); iter.hasNext();) {
+                        Property other = iter.next();
+                        if (other.isShadow() && other.getKey().equals(currentProperty.getKey())) {
+                            iter.remove();
+                            props.addFirst(other);
+                            continue next;
+                        }
+                    }
+                }
+                props.addFirst(currentProperty);
+            }
+        }
+        return props;
+    }
+
+    @Override
+    public final List<Property> getPropertyList() {
+        return getPropertyList(ALL);
+    }
+
+    /**
+     * Returns all (also hidden) Property objects in this shape.
+     *
+     * @param ascending desired order
+     */
+    @TruffleBoundary
+    @Override
+    public final List<Property> getPropertyListInternal(boolean ascending) {
+        LinkedList<Property> props = new LinkedList<>();
+        for (Property current : this.propertyMap.reverseOrderValues()) {
+            if (ascending) {
+                props.addFirst(current);
+            } else {
+                props.add(current);
+            }
+        }
+        return props;
+    }
+
+    /**
+     * Get a list of all (visible) property names in insertion order.
+     *
+     * @return list of property names
+     */
+    @TruffleBoundary
+    @Override
+    public final List<Object> getKeyList(Pred<Property> filter) {
+        LinkedList<Object> keys = new LinkedList<>();
+        for (Property currentProperty : this.propertyMap.reverseOrderValues()) {
+            if (!currentProperty.isHidden() && filter.test(currentProperty) && !currentProperty.isShadow()) {
+                keys.addFirst(currentProperty.getKey());
+            }
+        }
+        return keys;
+    }
+
+    @Override
+    public final List<Object> getKeyList() {
+        return getKeyList(ALL);
+    }
+
+    @Override
+    public Iterable<Object> getKeys() {
+        return getKeyList();
+    }
+
+    @Override
+    public final boolean isValid() {
+        return getValidAssumption().isValid();
+    }
+
+    @Override
+    public final Assumption getValidAssumption() {
+        return validAssumption;
+    }
+
+    private static Assumption createValidAssumption() {
+        return Truffle.getRuntime().createAssumption("valid shape");
+    }
+
+    public final void invalidateValidAssumption() {
+        getValidAssumption().invalidate();
+    }
+
+    @Override
+    public final boolean isLeaf() {
+        return leafAssumption == null || leafAssumption.isValid();
+    }
+
+    @Override
+    public final Assumption getLeafAssumption() {
+        if (leafAssumption == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            synchronized (getMutex()) {
+                if (leafAssumption == null) {
+                    leafAssumption = isLeafHelper() ? createLeafAssumption() : NeverValidAssumption.INSTANCE;
+                }
+            }
+        }
+        return leafAssumption;
+    }
+
+    private boolean isLeafHelper() {
+        return getTransitionMapForRead().isEmpty();
+    }
+
+    private static Assumption createLeafAssumption() {
+        return Truffle.getRuntime().createAssumption("leaf shape");
+    }
+
+    private void invalidateLeafAssumption() {
+        Assumption assumption = leafAssumption;
+        if (assumption != null) {
+            assumption.invalidate();
+        } else {
+            leafAssumption = NeverValidAssumption.INSTANCE;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return toStringLimit(Integer.MAX_VALUE);
+    }
+
+    @TruffleBoundary
+    public String toStringLimit(int limit) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('@');
+        sb.append(Integer.toHexString(hashCode()));
+        if (!isValid()) {
+            sb.append('!');
+        }
+
+        sb.append("{");
+        for (Iterator<Property> iterator = propertyMap.reverseOrderValues().iterator(); iterator.hasNext();) {
+            Property p = iterator.next();
+            sb.append(p);
+            if (iterator.hasNext()) {
+                sb.append(", ");
+            }
+            if (sb.length() >= limit) {
+                sb.append("...");
+                break;
+            }
+            sb.append("\n");
+        }
+        sb.append("}");
+
+        return sb.toString();
+    }
+
+    @Override
+    public final ShapeImpl getParent() {
+        return parent;
+    }
+
+    public final int getDepth() {
+        return depth;
+    }
+
+    @Override
+    public final boolean hasProperty(Object name) {
+        return getProperty(name) != null;
+    }
+
+    @TruffleBoundary
+    @Override
+    public final ShapeImpl removeProperty(Property prop) {
+        onPropertyTransition(prop);
+
+        RemovePropertyTransition transition = new RemovePropertyTransition(prop);
+        ShapeImpl cachedShape = queryTransition(transition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+
+        ShapeImpl shape = getShapeFromProperty(prop.getKey());
+        if (shape != null) {
+            List<Transition> transitionList = new ArrayList<>();
+            ShapeImpl current = this;
+            while (current != shape) {
+                if (!(current.getTransitionFromParent() instanceof Transition.DirectReplacePropertyTransition) ||
+                                !((Transition.DirectReplacePropertyTransition) current.getTransitionFromParent()).getPropertyBefore().getKey().equals(prop.getKey())) {
+                    transitionList.add(current.getTransitionFromParent());
+                }
+                current = current.parent;
+            }
+            ShapeImpl newShape = shape.parent;
+            for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) {
+                Transition previous = iterator.previous();
+                newShape = newShape.applyTransition(previous, true);
+            }
+
+            addIndirectTransition(transition, newShape);
+            return newShape;
+        } else {
+            return null;
+        }
+    }
+
+    @TruffleBoundary
+    @Override
+    public final ShapeImpl append(Property oldProperty) {
+        return addProperty(oldProperty.relocate(allocator().moveLocation(oldProperty.getLocation())));
+    }
+
+    public final ShapeImpl applyTransition(Transition transition, boolean append) {
+        if (transition instanceof AddPropertyTransition) {
+            return append ? append(((AddPropertyTransition) transition).getProperty()) : addProperty(((AddPropertyTransition) transition).getProperty());
+        } else if (transition instanceof ObjectTypeTransition) {
+            return changeType(((ObjectTypeTransition) transition).getObjectType());
+        } else if (transition instanceof ReservePrimitiveArrayTransition) {
+            return reservePrimitiveExtensionArray();
+        } else if (transition instanceof DirectReplacePropertyTransition) {
+            Property oldProperty = ((DirectReplacePropertyTransition) transition).getPropertyBefore();
+            Property newProperty = ((DirectReplacePropertyTransition) transition).getPropertyAfter();
+            if (append) {
+                assert oldProperty.getLocation() instanceof DualLocation && newProperty.getLocation() instanceof DualLocation;
+                oldProperty = getProperty(oldProperty.getKey());
+                newProperty = newProperty.relocate(((DualLocation) oldProperty.getLocation()).changeType(((DualLocation) newProperty.getLocation()).getType()));
+            }
+            return replaceProperty(oldProperty, newProperty);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public final BaseAllocator allocator() {
+        return layout.getStrategy().createAllocator(this);
+    }
+
+    /**
+     * Duplicate shape exchanging existing property with new property.
+     */
+    @Override
+    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
+        return indirectReplaceProperty(oldProperty, newProperty);
+    }
+
+    protected final ShapeImpl indirectReplaceProperty(Property oldProperty, Property newProperty) {
+        assert oldProperty.getKey().equals(newProperty.getKey());
+
+        Transition replacePropertyTransition = new Transition.IndirectReplacePropertyTransition(oldProperty, newProperty);
+        ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+
+        ShapeImpl top = this;
+        List<Transition> transitionList = new ArrayList<>();
+        boolean found = false;
+        while (top != getRoot() && !found) {
+            Transition transition = top.getTransitionFromParent();
+            transitionList.add(transition);
+            if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) {
+                found = true;
+            }
+            top = top.parent;
+        }
+        ShapeImpl newShape = top;
+        for (ListIterator<Transition> iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) {
+            Transition transition = iterator.previous();
+            if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) {
+                newShape = newShape.addProperty(newProperty);
+            } else {
+                newShape = newShape.applyTransition(transition, false);
+            }
+        }
+
+        addIndirectTransition(replacePropertyTransition, newShape);
+        return newShape;
+    }
+
+    protected final ShapeImpl directReplaceProperty(Property oldProperty, Property newProperty) {
+        assert oldProperty.getKey().equals(newProperty.getKey());
+        onPropertyTransition(oldProperty);
+
+        Transition replacePropertyTransition = new Transition.DirectReplacePropertyTransition(oldProperty, newProperty);
+        ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+        PropertyMap newPropertyMap = this.getPropertyMap().replaceCopy(oldProperty, newProperty);
+        ShapeImpl newShape = createShape(getLayout(), getSharedData(), this, getObjectType(), newPropertyMap, replacePropertyTransition, allocator(), getId());
+
+        addDirectTransition(replacePropertyTransition, newShape);
+        return newShape;
+    }
+
+    /**
+     * Find lowest common ancestor of two related shapes.
+     */
+    public static ShapeImpl findCommonAncestor(ShapeImpl left, ShapeImpl right) {
+        if (!left.isRelated(right)) {
+            throw new IllegalArgumentException("shapes must have the same root");
+        } else if (left == right) {
+            return left;
+        }
+        int leftLength = left.depth;
+        int rightLength = right.depth;
+        ShapeImpl leftPtr = left;
+        ShapeImpl rightPtr = right;
+        while (leftLength > rightLength) {
+            leftPtr = leftPtr.parent;
+            leftLength--;
+        }
+        while (rightLength > leftLength) {
+            rightPtr = rightPtr.parent;
+            rightLength--;
+        }
+        while (leftPtr != rightPtr) {
+            leftPtr = leftPtr.parent;
+            rightPtr = rightPtr.parent;
+        }
+        return leftPtr;
+    }
+
+    @Override
+    public final int getPropertyCount() {
+        return propertyCount;
+    }
+
+    /**
+     * Find difference between two shapes.
+     *
+     * @see ObjectStorageOptions#TraceReshape
+     */
+    public static List<Property> diff(Shape oldShape, Shape newShape) {
+        List<Property> oldList = oldShape.getPropertyListInternal(false);
+        List<Property> newList = newShape.getPropertyListInternal(false);
+
+        List<Property> diff = new ArrayList<>(oldList);
+        diff.addAll(newList);
+        List<Property> intersection = new ArrayList<>(oldList);
+        intersection.retainAll(newList);
+        diff.removeAll(intersection);
+        return diff;
+    }
+
+    @Override
+    public ObjectType getObjectType() {
+        return objectType;
+    }
+
+    @Override
+    public ShapeImpl getRoot() {
+        return root;
+    }
+
+    @Override
+    public final boolean check(DynamicObject subject) {
+        return subject.getShape() == this;
+    }
+
+    @Override
+    public final LayoutImpl getLayout() {
+        return layout;
+    }
+
+    @Override
+    public final Object getData() {
+        return extraData;
+    }
+
+    @Override
+    public final Object getSharedData() {
+        return sharedData;
+    }
+
+    @TruffleBoundary
+    @Override
+    public final boolean hasTransitionWithKey(Object key) {
+        for (Transition transition : getTransitionMapForRead().keySet()) {
+            if (transition instanceof PropertyTransition) {
+                if (((PropertyTransition) transition).getProperty().getKey().equals(key)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Clone off a separate shape with new shared data.
+     */
+    @TruffleBoundary
+    @Override
+    public final ShapeImpl createSeparateShape(Object newSharedData) {
+        if (parent == null) {
+            return cloneRoot(this, newSharedData);
+        } else {
+            return this.cloneOnto(parent.createSeparateShape(newSharedData));
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    public final ShapeImpl changeType(ObjectType newOps) {
+        ObjectTypeTransition transition = new ObjectTypeTransition(newOps);
+        ShapeImpl cachedShape = queryTransition(transition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+
+        ShapeImpl newShape = createShape(layout, sharedData, this, newOps, propertyMap, transition, allocator(), id);
+        addDirectTransition(transition, newShape);
+        return newShape;
+    }
+
+    @Override
+    public final ShapeImpl reservePrimitiveExtensionArray() {
+        if (layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray()) {
+            return addPrimitiveExtensionArray();
+        }
+        return this;
+    }
+
+    @Override
+    public final Iterable<Property> getProperties() {
+        return getPropertyList();
+    }
+
+    @Override
+    public final DynamicObject newInstance() {
+        return layout.newInstance(this);
+    }
+
+    @Override
+    public final DynamicObjectFactory createFactory() {
+        final List<Property> properties = getPropertyListInternal(true);
+        for (Iterator<Property> iterator = properties.iterator(); iterator.hasNext();) {
+            Property property = iterator.next();
+            // skip non-instance fields
+            assert property.getLocation() != layout.getPrimitiveArrayLocation();
+            if (property.getLocation() instanceof ValueLocation) {
+                iterator.remove();
+            }
+        }
+
+        return new DynamicObjectFactory() {
+            @CompilationFinal private final PropertyImpl[] instanceFields = properties.toArray(new PropertyImpl[properties.size()]);
+
+            @ExplodeLoop
+            public DynamicObject newInstance(Object... initialValues) {
+                DynamicObject store = ShapeImpl.this.newInstance();
+                for (int i = 0; i < instanceFields.length; i++) {
+                    instanceFields[i].setInternal(store, initialValues[i]);
+                }
+                return store;
+            }
+
+            public Shape getShape() {
+                return ShapeImpl.this;
+            }
+        };
+    }
+
+    @Override
+    public Object getMutex() {
+        return getRoot();
+    }
+
+    @Override
+    public Shape tryMerge(Shape other) {
+        return null;
+    }
+
+    public abstract static class BaseAllocator extends Allocator implements LocationVisitor {
+        protected final LayoutImpl layout;
+        protected int objectArraySize;
+        protected int objectFieldSize;
+        protected int primitiveFieldSize;
+        protected int primitiveArraySize;
+        protected boolean hasPrimitiveArray;
+        protected int depth;
+
+        protected BaseAllocator(LayoutImpl layout) {
+            this.layout = layout;
+        }
+
+        protected BaseAllocator(ShapeImpl shape) {
+            this(shape.getLayout());
+            this.objectArraySize = shape.objectArraySize;
+            this.objectFieldSize = shape.objectFieldSize;
+            this.primitiveFieldSize = shape.primitiveFieldSize;
+            this.primitiveArraySize = shape.primitiveArraySize;
+            this.hasPrimitiveArray = shape.hasPrimitiveArray;
+            this.depth = shape.depth;
+        }
+
+        protected abstract Location moveLocation(Location oldLocation);
+
+        protected abstract Location newObjectLocation(boolean useFinal, boolean nonNull);
+
+        protected abstract Location newTypedObjectLocation(boolean useFinal, Class<?> type, boolean nonNull);
+
+        protected abstract Location newIntLocation(boolean useFinal);
+
+        protected abstract Location newDoubleLocation(boolean useFinal);
+
+        protected abstract Location newLongLocation(boolean useFinal);
+
+        protected abstract Location newBooleanLocation(boolean useFinal);
+
+        @Override
+        public final Location constantLocation(Object value) {
+            return new ConstantLocation(value);
+        }
+
+        @Override
+        protected Location locationForValue(Object value, boolean useFinal, boolean nonNull) {
+            if (value instanceof Integer) {
+                return newIntLocation(useFinal);
+            } else if (value instanceof Double) {
+                return newDoubleLocation(useFinal);
+            } else if (value instanceof Long) {
+                return newLongLocation(useFinal);
+            } else if (value instanceof Boolean) {
+                return newBooleanLocation(useFinal);
+            } else if (ObjectStorageOptions.TypedObjectLocations && value != null) {
+                return newTypedObjectLocation(useFinal, value.getClass(), nonNull);
+            }
+            return newObjectLocation(useFinal, nonNull && value != null);
+        }
+
+        protected abstract Location locationForValueUpcast(Object value, Location oldLocation);
+
+        @Override
+        protected Location locationForType(Class<?> type, boolean useFinal, boolean nonNull) {
+            if (type == int.class) {
+                return newIntLocation(useFinal);
+            } else if (type == double.class) {
+                return newDoubleLocation(useFinal);
+            } else if (type == long.class) {
+                return newLongLocation(useFinal);
+            } else if (type == boolean.class) {
+                return newBooleanLocation(useFinal);
+            } else if (ObjectStorageOptions.TypedObjectLocations && type != null && type != Object.class) {
+                assert !type.isPrimitive() : "unsupported primitive type";
+                return newTypedObjectLocation(useFinal, type, nonNull);
+            }
+            return newObjectLocation(useFinal, nonNull);
+        }
+
+        protected Location newDualLocation(Class<?> type) {
+            return new DualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), layout, type);
+        }
+
+        protected DualLocation newDualLocationForValue(Object value) {
+            Class<?> initialType = null;
+            if (value instanceof Integer) {
+                initialType = int.class;
+            } else if (value instanceof Double) {
+                initialType = double.class;
+            } else if (value instanceof Boolean) {
+                initialType = boolean.class;
+            } else {
+                initialType = Object.class;
+            }
+            return new DualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), layout, initialType);
+        }
+
+        protected Location newDeclaredDualLocation(Object value) {
+            return new DeclaredDualLocation((InternalLongLocation) newLongLocation(false), (ObjectLocation) newObjectLocation(false, false), value, layout);
+        }
+
+        protected <T extends Location> T advance(T location0) {
+            if (location0 instanceof LocationImpl) {
+                LocationImpl location = (LocationImpl) location0;
+                if (location != layout.getPrimitiveArrayLocation()) {
+                    location.accept(this);
+                }
+                if (layout.hasPrimitiveExtensionArray()) {
+                    hasPrimitiveArray |= location == layout.getPrimitiveArrayLocation() || primitiveArraySize > 0;
+                } else {
+                    assert !hasPrimitiveArray && primitiveArraySize == 0;
+                }
+            }
+            depth++;
+            return location0;
+        }
+
+        @Override
+        public BaseAllocator addLocation(Location location) {
+            advance(location);
+            return this;
+        }
+
+        public void visitObjectField(int index, int count) {
+            objectFieldSize = Math.max(objectFieldSize, index + count);
+        }
+
+        public void visitObjectArray(int index, int count) {
+            objectArraySize = Math.max(objectArraySize, index + count);
+        }
+
+        public void visitPrimitiveArray(int index, int count) {
+            primitiveArraySize = Math.max(primitiveArraySize, index + count);
+        }
+
+        public void visitPrimitiveField(int index, int count) {
+            primitiveFieldSize = Math.max(primitiveFieldSize, index + count);
+        }
+    }
+
+    private static void debugRegisterShape(ShapeImpl newShape) {
+        if (ObjectStorageOptions.DumpShapes) {
+            Debug.registerShape(newShape);
+        }
+    }
+
+    /**
+     * Match all filter.
+     */
+    private static final Pred<Property> ALL = new Pred<Property>() {
+        public boolean test(Property t) {
+            return true;
+        }
+    };
+
+    private static final DebugCounter shapeCount = DebugCounter.create("Shapes allocated total");
+    private static final DebugCounter shapeCloneCount = DebugCounter.create("Shapes allocated cloned");
+    private static final DebugCounter shapeCacheHitCount = DebugCounter.create("Shape cache hits");
+    private static final DebugCounter shapeCacheMissCount = DebugCounter.create("Shape cache misses");
+
+    public ForeignAccess getForeignAccessFactory() {
+        return getObjectType().getForeignAccessFactory();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object;
+
+import java.util.*;
+
+import com.oracle.truffle.api.object.*;
+
+public abstract class Transition {
+    @Override
+    public int hashCode() {
+        int result = 1;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        return true;
+    }
+
+    public abstract boolean isDirect();
+
+    public abstract static class PropertyTransition extends Transition {
+        private final Property property;
+
+        public PropertyTransition(Property property) {
+            this.property = property;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + ((property == null) ? 0 : property.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!super.equals(obj)) {
+                return false;
+            }
+            PropertyTransition other = (PropertyTransition) obj;
+            if (!Objects.equals(property, other.property)) {
+                return false;
+            }
+            return true;
+        }
+
+        public Property getProperty() {
+            return property;
+        }
+    }
+
+    public static final class AddPropertyTransition extends PropertyTransition {
+        public AddPropertyTransition(Property property) {
+            super(property);
+        }
+
+        @Override
+        public boolean isDirect() {
+            return true;
+        }
+    }
+
+    public static final class RemovePropertyTransition extends PropertyTransition {
+        public RemovePropertyTransition(Property property) {
+            super(property);
+        }
+
+        @Override
+        public boolean isDirect() {
+            return false;
+        }
+    }
+
+    public static final class ObjectTypeTransition extends Transition {
+        private final ObjectType objectType;
+
+        public ObjectTypeTransition(ObjectType objectType) {
+            this.objectType = objectType;
+        }
+
+        public ObjectType getObjectType() {
+            return objectType;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return super.equals(other) && Objects.equals(objectType, ((ObjectTypeTransition) other).objectType);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + ((objectType == null) ? 0 : objectType.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean isDirect() {
+            return true;
+        }
+    }
+
+    public abstract static class AbstractReplacePropertyTransition extends PropertyTransition {
+        private final Property after;
+
+        public AbstractReplacePropertyTransition(Property before, Property after) {
+            super(before);
+            this.after = after;
+        }
+
+        public Property getPropertyBefore() {
+            return this.getProperty();
+        }
+
+        public Property getPropertyAfter() {
+            return after;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return super.equals(obj) && this.after.equals(((AbstractReplacePropertyTransition) obj).after);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + after.hashCode();
+            return result;
+        }
+    }
+
+    public static final class IndirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
+        public IndirectReplacePropertyTransition(Property before, Property after) {
+            super(before, after);
+        }
+
+        @Override
+        public boolean isDirect() {
+            return false;
+        }
+    }
+
+    public static final class DirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
+        public DirectReplacePropertyTransition(Property before, Property after) {
+            super(before, after);
+        }
+
+        @Override
+        public boolean isDirect() {
+            return true;
+        }
+    }
+
+    public static final class ReservePrimitiveArrayTransition extends Transition {
+        public ReservePrimitiveArrayTransition() {
+        }
+
+        @Override
+        public boolean isDirect() {
+            return true;
+        }
+    }
+
+    public String getShortName() {
+        return this.getClass().getSimpleName().replaceFirst("Transition$", "").toLowerCase();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/GraphvizShapeVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.debug;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+
+public class GraphvizShapeVisitor extends DebugShapeVisitor<GraphvizShapeVisitor> {
+    private final Set<Shape> drawn;
+    private final StringBuilder sb = new StringBuilder();
+
+    public GraphvizShapeVisitor() {
+        this.drawn = new HashSet<>();
+    }
+
+    @Override
+    public GraphvizShapeVisitor visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions) {
+        if (!drawn.add(shape)) {
+            return null;
+        }
+
+        String prefix = "s";
+        sb.append(prefix).append(getId(shape));
+        sb.append(" [label=\"");
+        if (shape.getLastProperty() != null) {
+            sb.append(escapeString(shape.getLastProperty().toString()));
+        } else {
+            sb.append("ROOT");
+        }
+        sb.append("\"");
+        sb.append(", shape=\"rectangle\"");
+        if (!shape.isValid()) {
+            sb.append(", color=\"red\", style=dotted");
+        }
+        sb.append("];");
+
+        for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
+            Shape dst = entry.getValue();
+            dst.accept(this);
+            assert drawn.contains(dst);
+
+            sb.append(prefix).append(getId(shape)).append("->").append(prefix).append(getId(dst));
+            sb.append(" [label=\"").append(escapeString(entry.getKey().getShortName())).append("\"]");
+            sb.append(";");
+        }
+
+        return this;
+    }
+
+    private static String escapeString(String str) {
+        return str.replaceAll("\\\\", "\\\\").replaceAll("\"", "\\\\\"");
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder("digraph{").append(sb).append("}").toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/JSONShapeVisitor.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.debug;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.api.utilities.JSONHelper.JSONArrayBuilder;
+import com.oracle.truffle.api.utilities.JSONHelper.JSONObjectBuilder;
+import com.oracle.truffle.object.*;
+import com.oracle.truffle.object.Transition.PropertyTransition;
+
+public class JSONShapeVisitor extends DebugShapeVisitor<JSONObjectBuilder> {
+    @Override
+    public JSONObjectBuilder visitShape(Shape shape, Map<? extends Transition, ? extends Shape> transitions) {
+        JSONObjectBuilder sb = JSONHelper.object();
+        JSONArrayBuilder transitionarray = JSONHelper.array();
+        for (Entry<? extends Transition, ? extends Shape> entry : transitions.entrySet()) {
+            transitionarray.add(JSONHelper.object().add("transition", dumpTransition(entry.getKey())).add("successor", getId(entry.getValue())));
+        }
+        JSONArrayBuilder propertiesarray = JSONHelper.array();
+        for (Property p : shape.getPropertyList()) {
+            propertiesarray.add(dumpProperty(p));
+        }
+        sb.add("id", getId(shape));
+        sb.add("properties", propertiesarray);
+        sb.add("transitions", transitionarray);
+        sb.add("predecessor", shape.getParent() != null ? getId(shape.getParent()) : null);
+        sb.add("valid", shape.isValid());
+        return sb;
+    }
+
+    public JSONObjectBuilder dumpProperty(Property property) {
+        return JSONHelper.object().add("id", property.getKey().toString()).add("location", dumpLocation(property.getLocation())).add("flags", property.getFlags());
+    }
+
+    public JSONObjectBuilder dumpTransition(Transition transition) {
+        JSONObjectBuilder sb = JSONHelper.object().add("type", transition.getShortName());
+        if (transition instanceof PropertyTransition) {
+            sb.add("property", dumpProperty(((PropertyTransition) transition).getProperty()));
+        }
+        return sb;
+    }
+
+    public JSONObjectBuilder dumpLocation(Location location) {
+        JSONObjectBuilder obj = JSONHelper.object();
+        obj.add("type", (location instanceof TypedLocation ? ((TypedLocation) location).getType() : Object.class).getName());
+        // if (location instanceof Locations.FieldLocation) {
+        // obj.add("offset", ((Locations.FieldLocation) location).getOffset());
+        // }
+        // if (location instanceof Locations.ArrayLocation) {
+        // obj.add("index", ((Locations.ArrayLocation) location).getIndex());
+        // }
+        if (location instanceof Locations.ValueLocation) {
+            obj.add("value", String.valueOf(((Locations.ValueLocation) location).get(null, false)));
+        }
+        return obj;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.object/src/com/oracle/truffle/object/debug/ShapeProfiler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.object.debug;
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.object.*;
+
+public class ShapeProfiler {
+    private static final String LINE_SEPARATOR = "***********************************************";
+    private static final String BULLET = "* ";
+    private static final String TOKEN_SEPARATOR = "\t";
+    private final ConcurrentLinkedQueue<DynamicObject> queue;
+
+    public ShapeProfiler() {
+        queue = new ConcurrentLinkedQueue<>();
+    }
+
+    public void track(DynamicObject obj) {
+        queue.add(obj);
+    }
+
+    public void dump(PrintWriter out) {
+        ShapeStats globalStats = new ShapeStats("Cumulative results for all shapes");
+        for (DynamicObject obj : queue) {
+            Shape shape = obj.getShape();
+            globalStats.profile(shape);
+        }
+
+        globalStats.dump(out);
+    }
+
+    public void dump(PrintWriter out, int topResults) {
+        if (topResults > 0) {
+            IdentityHashMap<Shape, ShapeStats> shapeMap = new IdentityHashMap<>();
+
+            for (DynamicObject obj : queue) {
+                Shape shape = obj.getShape();
+                ShapeStats stats = shapeMap.get(shape);
+                if (stats == null) {
+                    shapeMap.put(shape, stats = new ShapeStats(createLabel(shape)));
+                }
+                stats.profile(shape);
+            }
+
+            List<ShapeStats> allStats = new ArrayList<>(shapeMap.values());
+            Collections.sort(allStats, new Comparator<ShapeStats>() {
+                public int compare(ShapeStats a, ShapeStats b) {
+                    return Long.compare(b.jsObjects, a.jsObjects);
+                }
+            });
+
+            ShapeStats avgStats = new ShapeStats("Cumulative results for top " + topResults + " shapes");
+            for (int i = 0; i < topResults; i++) {
+                ShapeStats stats = allStats.get(i);
+                stats.setLabel("Shape " + (i + 1) + ": " + stats.getLabel());
+                stats.dump(out);
+                avgStats.add(stats);
+            }
+            avgStats.dump(out);
+        }
+        // Dump also cumulative results.
+        dump(out);
+    }
+
+    private static String createLabel(Shape shape) {
+        String label = shape.toString();
+        return label.substring(label.indexOf('{') + 1, label.lastIndexOf('}'));
+    }
+
+    private static class ShapeStats {
+        private String label;
+        private long jsObjects;
+        private long oac;
+        private long oas;
+        private long ofs;
+        private long pac;
+        private long pas;
+        private long pfs;
+
+        public ShapeStats(String label) {
+            this.label = label;
+        }
+
+        public String getLabel() {
+            return label;
+        }
+
+        public void setLabel(String label) {
+            this.label = label;
+        }
+
+        public void profile(Shape shape) {
+            jsObjects++;
+            oac += shape.getObjectArrayCapacity();
+            oas += shape.getObjectArraySize();
+            ofs += shape.getObjectFieldSize();
+            pac += shape.getPrimitiveArrayCapacity();
+            pas += shape.getPrimitiveArraySize();
+            pfs += shape.getPrimitiveFieldSize();
+        }
+
+        public void add(ShapeStats stats) {
+            jsObjects += stats.jsObjects;
+            oac += stats.oac;
+            oas += stats.oas;
+            ofs += stats.ofs;
+            oac += stats.oac;
+            oas += stats.oas;
+            ofs += stats.ofs;
+        }
+
+        public void dump(PrintWriter out) {
+            DecimalFormat format = new DecimalFormat("###.####");
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + label);
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + "Allocated objects:\t" + jsObjects);
+            out.println(BULLET + "Total object array capacity:\t" + oac);
+            out.println(BULLET + "Total object array size:\t" + oas);
+            out.println(BULLET + "Total object field size:\t" + ofs);
+            out.println(BULLET + "Average object array capacity:\t" + avgOAC(format));
+            out.println(BULLET + "Average object array size:\t" + avgOAS(format));
+            out.println(BULLET + "Average object field size:\t" + avgOFS(format));
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + "Total primitive array capacity:\t" + pac);
+            out.println(BULLET + "Total primitive array size:\t" + pas);
+            out.println(BULLET + "Total primitive field size:\t" + pfs);
+            out.println(BULLET + "Average primitive array capacity:\t" + avgPAC(format));
+            out.println(BULLET + "Average primitive array size:\t" + avgPAS(format));
+            out.println(BULLET + "Average primitive field size:\t" + avgPFS(format));
+            out.println(LINE_SEPARATOR);
+            out.println(BULLET + toString());
+            out.println(LINE_SEPARATOR + "\n");
+            out.flush();
+        }
+
+        @Override
+        public String toString() {
+            DecimalFormat format = new DecimalFormat("###.####");
+            // @formatter:off
+            return "{" + label + "}" + TOKEN_SEPARATOR
+                   + jsObjects + TOKEN_SEPARATOR
+                   + avgOAC(format) + TOKEN_SEPARATOR
+                   + avgOAS(format) + TOKEN_SEPARATOR
+                   + avgOFS(format) + TOKEN_SEPARATOR
+                   + avgPAC(format) + TOKEN_SEPARATOR
+                   + avgPAS(format) + TOKEN_SEPARATOR
+                   + avgPFS(format);
+            // @formatter:on
+        }
+
+        private String avgOAC(DecimalFormat format) {
+            return format.format((double) oac / jsObjects);
+        }
+
+        private String avgOAS(DecimalFormat format) {
+            return format.format((double) oas / jsObjects);
+        }
+
+        private String avgOFS(DecimalFormat format) {
+            return format.format((double) ofs / jsObjects);
+        }
+
+        private String avgPAC(DecimalFormat format) {
+            return format.format((double) pac / jsObjects);
+        }
+
+        private String avgPAS(DecimalFormat format) {
+            return format.format((double) pas / jsObjects);
+        }
+
+        private String avgPFS(DecimalFormat format) {
+            return format.format((double) pfs / jsObjects);
+        }
+    }
+
+    public static ShapeProfiler getInstance() {
+        return shapeProf;
+    }
+
+    private static final ShapeProfiler shapeProf;
+    static {
+        if (ObjectStorageOptions.Profile) {
+            shapeProf = new ShapeProfiler();
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    getInstance().dump(new PrintWriter(System.out), ObjectStorageOptions.ProfileTopResults);
+                }
+            });
+        } else {
+            shapeProf = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLSimpleTestSuite.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import org.junit.*;
+import org.junit.runner.*;
+
+@RunWith(SLTestRunner.class)
+@SLTestSuite({"truffle/com.oracle.truffle.sl.test/tests", "tests"})
+public class SLSimpleTestSuite {
+
+    public static void main(String[] args) throws Exception {
+        SLTestRunner.runInMain(SLSimpleTestSuite.class, args);
+    }
+
+    /*
+     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
+     * an empty method, this class gets included and the test suite is properly executed.
+     */
+    @Test
+    public void unittest() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import com.oracle.truffle.tck.TruffleTCK;
+import com.oracle.truffle.api.vm.TruffleVM;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * This is the way to verify your language implementation is compatible.
+ *
+ */
+public class SLTckTest extends TruffleTCK {
+    @Test
+    public void testVerifyPresence() {
+        TruffleVM vm = TruffleVM.newVM().build();
+        assertTrue("Our language is present", vm.getLanguages().containsKey("application/x-sl"));
+    }
+
+    @Override
+    protected TruffleVM prepareVM() throws Exception {
+        TruffleVM vm = TruffleVM.newVM().build();
+        // @formatter:off
+        vm.eval("application/x-sl",
+            "function fourtyTwo() {\n" +
+            "  return 42;\n" + //
+            "}\n" +
+            "function plus(a, b) {\n" +
+            "  return a + b;\n" +
+            "}\n" +
+            "function null() {\n" +
+            "}\n"
+        );
+        // @formatter:on
+        return vm;
+    }
+
+    @Override
+    protected String mimeType() {
+        return "application/x-sl";
+    }
+
+    @Override
+    protected String fourtyTwo() {
+        return "fourtyTwo";
+    }
+
+    @Override
+    protected String plusInt() {
+        return "plus";
+    }
+
+    @Override
+    protected String returnsNull() {
+        return "null";
+    }
+
+    @Override
+    protected String invalidCode() {
+        // @formatter:off
+        return
+            "f unction main() {\n" +
+            "  retu rn 42;\n" +
+            "}\n";
+        // @formatter:on
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestRunner.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+
+import org.junit.*;
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.manipulation.*;
+import org.junit.runner.notification.*;
+import org.junit.runners.*;
+import org.junit.runners.model.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.vm.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.builtins.*;
+import com.oracle.truffle.sl.test.SLTestRunner.TestCase;
+
+public final class SLTestRunner extends ParentRunner<TestCase> {
+
+    private static int repeats = 1;
+
+    private static final String SOURCE_SUFFIX = ".sl";
+    private static final String INPUT_SUFFIX = ".input";
+    private static final String OUTPUT_SUFFIX = ".output";
+
+    private static final String LF = System.getProperty("line.separator");
+
+    static class TestCase {
+        protected final Description name;
+        protected final Path path;
+        protected final String sourceName;
+        protected final String testInput;
+        protected final String expectedOutput;
+        protected String actualOutput;
+
+        protected TestCase(Class<?> testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) {
+            this.name = Description.createTestDescription(testClass, baseName);
+            this.sourceName = sourceName;
+            this.path = path;
+            this.testInput = testInput;
+            this.expectedOutput = expectedOutput;
+        }
+    }
+
+    private final List<TestCase> testCases;
+
+    public SLTestRunner(Class<?> runningClass) throws InitializationError {
+        super(runningClass);
+        try {
+            testCases = createTests(runningClass);
+        } catch (IOException e) {
+            throw new InitializationError(e);
+        }
+    }
+
+    @Override
+    protected Description describeChild(TestCase child) {
+        return child.name;
+    }
+
+    @Override
+    protected List<TestCase> getChildren() {
+        return testCases;
+    }
+
+    protected static List<TestCase> createTests(final Class<?> c) throws IOException, InitializationError {
+        SLTestSuite suite = c.getAnnotation(SLTestSuite.class);
+        if (suite == null) {
+            throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLTestSuite.class.getSimpleName(), c.getName(), SLTestRunner.class.getSimpleName()));
+        }
+
+        String[] pathes = suite.value();
+
+        Path root = null;
+        for (String path : pathes) {
+            root = FileSystems.getDefault().getPath(path);
+            if (Files.exists(root)) {
+                break;
+            }
+        }
+        if (root == null && pathes.length > 0) {
+            throw new FileNotFoundException(pathes[0]);
+        }
+
+        final Path rootPath = root;
+
+        final List<TestCase> foundCases = new ArrayList<>();
+        Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
+                String sourceName = sourceFile.getFileName().toString();
+                if (sourceName.endsWith(SOURCE_SUFFIX)) {
+                    String baseName = sourceName.substring(0, sourceName.length() - SOURCE_SUFFIX.length());
+
+                    Path inputFile = sourceFile.resolveSibling(baseName + INPUT_SUFFIX);
+                    String testInput = "";
+                    if (Files.exists(inputFile)) {
+                        testInput = readAllLines(inputFile);
+                    }
+
+                    Path outputFile = sourceFile.resolveSibling(baseName + OUTPUT_SUFFIX);
+                    String expectedOutput = "";
+                    if (Files.exists(outputFile)) {
+                        expectedOutput = readAllLines(outputFile);
+                    }
+
+                    foundCases.add(new TestCase(c, baseName, sourceName, sourceFile, testInput, expectedOutput));
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+        return foundCases;
+    }
+
+    private static String readAllLines(Path file) throws IOException {
+        // fix line feeds for non unix os
+        StringBuilder outFile = new StringBuilder();
+        for (String line : Files.readAllLines(file, Charset.defaultCharset())) {
+            outFile.append(line).append(LF);
+        }
+        return outFile.toString();
+    }
+
+    public static void setRepeats(int repeats) {
+        SLTestRunner.repeats = repeats;
+    }
+
+    private static final List<NodeFactory<? extends SLBuiltinNode>> builtins = new ArrayList<>();
+
+    public static void installBuiltin(NodeFactory<? extends SLBuiltinNode> builtin) {
+        builtins.add(builtin);
+    }
+
+    @Override
+    protected void runChild(TestCase testCase, RunNotifier notifier) {
+        notifier.fireTestStarted(testCase.name);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        PrintWriter printer = new PrintWriter(out);
+        try {
+            TruffleVM vm = TruffleVM.newVM().stdIn(new BufferedReader(new StringReader(repeat(testCase.testInput, repeats)))).stdOut(printer).build();
+
+            String script = readAllLines(testCase.path);
+            SLLanguage.run(vm, testCase.path.toUri(), null, printer, repeats, builtins);
+
+            printer.flush();
+            String actualOutput = new String(out.toByteArray());
+            Assert.assertEquals(script, repeat(testCase.expectedOutput, repeats), actualOutput);
+        } catch (Throwable ex) {
+            notifier.fireTestFailure(new Failure(testCase.name, new IllegalStateException("Cannot run " + testCase.sourceName, ex)));
+        } finally {
+            notifier.fireTestFinished(testCase.name);
+        }
+    }
+
+    private static String repeat(String s, int count) {
+        StringBuilder result = new StringBuilder(s.length() * count);
+        for (int i = 0; i < count; i++) {
+            result.append(s);
+        }
+        return result.toString();
+    }
+
+    public static void runInMain(Class<?> testClass, String[] args) throws InitializationError, NoTestsRemainException {
+        JUnitCore core = new JUnitCore();
+        core.addListener(new TextListener(System.out));
+        SLTestRunner suite = new SLTestRunner(testClass);
+        if (args.length > 0) {
+            suite.filter(new NameFilter(args[0]));
+        }
+        Result r = core.run(suite);
+        if (!r.wasSuccessful()) {
+            System.exit(1);
+        }
+    }
+
+    private static final class NameFilter extends Filter {
+        private final String pattern;
+
+        private NameFilter(String pattern) {
+            this.pattern = pattern.toLowerCase();
+        }
+
+        @Override
+        public boolean shouldRun(Description description) {
+            return description.getMethodName().toLowerCase().contains(pattern);
+        }
+
+        @Override
+        public String describe() {
+            return "Filter contains " + pattern;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTestSuite.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SLTestSuite {
+
+    /**
+     * Defines the base path of the test suite. Multiple base pathes can be specified. However only
+     * the first base that exists is used to lookup the test cases.
+     */
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test.instrument;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+
+import org.junit.*;
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.manipulation.*;
+import org.junit.runner.notification.*;
+import org.junit.runners.*;
+import org.junit.runners.model.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.factory.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase;
+
+/**
+ * This class builds and executes the tests for instrumenting SL. Although much of this class is
+ * written with future automation in mind, at the moment the tests that are created are hard-coded
+ * according to the file name of the test. To be automated, an automatic way of generating both the
+ * node visitor and the node prober is necessary.
+ *
+ * Testing is done via JUnit via comparing execution outputs with expected outputs.
+ */
+public final class SLInstrumentTestRunner extends ParentRunner<InstrumentTestCase> {
+
+    private static final String SOURCE_SUFFIX = ".sl";
+    private static final String INPUT_SUFFIX = ".input";
+    private static final String OUTPUT_SUFFIX = ".output";
+    private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount";
+
+    private static final String LF = System.getProperty("line.separator");
+    private static SLContext slContext;
+
+    static class InstrumentTestCase {
+        protected final Description name;
+        protected final Path path;
+        protected final String baseName;
+        protected final String sourceName;
+        protected final String testInput;
+        protected final String expectedOutput;
+        protected String actualOutput;
+
+        protected InstrumentTestCase(Class<?> testClass, String baseName, String sourceName, Path path, String testInput, String expectedOutput) {
+            this.name = Description.createTestDescription(testClass, baseName);
+            this.baseName = baseName;
+            this.sourceName = sourceName;
+            this.path = path;
+            this.testInput = testInput;
+            this.expectedOutput = expectedOutput;
+        }
+    }
+
+    private final List<InstrumentTestCase> testCases;
+
+    public SLInstrumentTestRunner(Class<?> testClass) throws InitializationError {
+        super(testClass);
+        final SLStandardASTProber prober = new SLStandardASTProber();
+        Probe.registerASTProber(prober);
+        try {
+            testCases = createTests(testClass);
+        } catch (IOException e) {
+            throw new InitializationError(e);
+        } finally {
+            Probe.unregisterASTProber(prober);
+        }
+    }
+
+    @Override
+    protected List<InstrumentTestCase> getChildren() {
+        return testCases;
+    }
+
+    @Override
+    protected Description describeChild(InstrumentTestCase child) {
+        return child.name;
+    }
+
+    /**
+     * Tests are created based on the files that exist in the directory specified in the passed in
+     * annotation. Each test must have a source file and an expected output file. Optionally, each
+     * test can also include an input file. Source files have an ".sl" extension. Expected output
+     * have a ".output" extension. Input files have an ".input" extension. All these files must
+     * share the same base name to be correctly grouped. For example: "test1_assnCount.sl",
+     * "test1_assnCount.output" and "test1_assnCount.input" would all be used to create a single
+     * test called "test1_assnCount".
+     *
+     * This method iterates over the files in the directory and creates a new InstrumentTestCase for
+     * each group of related files. Each file is also expected to end with an identified at the end
+     * of the base name to indicate what visitor needs to be attached. Currently, visitors are hard
+     * coded to work on specific lines, so the code here is not currently generalizable.
+     *
+     * @param c The annotation containing the directory with tests
+     * @return A list of {@link InstrumentTestCase}s to run.
+     * @throws IOException If the directory is invalid.
+     * @throws InitializationError If no directory is provided.
+     *
+     * @see #runChild(InstrumentTestCase, RunNotifier)
+     */
+    protected static List<InstrumentTestCase> createTests(final Class<?> c) throws IOException, InitializationError {
+        SLInstrumentTestSuite suite = c.getAnnotation(SLInstrumentTestSuite.class);
+        if (suite == null) {
+            throw new InitializationError(String.format("@%s annotation required on class '%s' to run with '%s'.", SLInstrumentTestSuite.class.getSimpleName(), c.getName(),
+                            SLInstrumentTestRunner.class.getSimpleName()));
+        }
+
+        String[] paths = suite.value();
+
+        Path root = null;
+        for (String path : paths) {
+            root = FileSystems.getDefault().getPath(path);
+            if (Files.exists(root)) {
+                break;
+            }
+        }
+        if (root == null && paths.length > 0) {
+            throw new FileNotFoundException(paths[0]);
+        }
+
+        final Path rootPath = root;
+
+        final List<InstrumentTestCase> testCases = new ArrayList<>();
+
+        // Scaffolding in place for future automation
+        Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path sourceFile, BasicFileAttributes attrs) throws IOException {
+                String sourceName = sourceFile.getFileName().toString();
+                if (sourceName.endsWith(SOURCE_SUFFIX)) {
+                    String baseName = sourceName.substring(0, sourceName.length() - SOURCE_SUFFIX.length());
+
+                    Path inputFile = sourceFile.resolveSibling(baseName + INPUT_SUFFIX);
+                    String testInput = "";
+                    if (Files.exists(inputFile)) {
+                        testInput = readAllLines(inputFile);
+                    }
+
+                    Path outputFile = sourceFile.resolveSibling(baseName + OUTPUT_SUFFIX);
+                    String expectedOutput = "";
+                    if (Files.exists(outputFile)) {
+                        expectedOutput = readAllLines(outputFile);
+                    }
+
+                    testCases.add(new InstrumentTestCase(c, baseName, sourceName, sourceFile, testInput, expectedOutput));
+
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+
+        return testCases;
+    }
+
+    private static String readAllLines(Path file) throws IOException {
+        // fix line feeds for non unix os
+        StringBuilder outFile = new StringBuilder();
+        for (String line : Files.readAllLines(file, Charset.defaultCharset())) {
+            outFile.append(line).append(LF);
+        }
+        return outFile.toString();
+    }
+
+    /**
+     * Executes the passed in test case. Instrumentation is added according to the name of the file
+     * as explained in {@link #createTests(Class)}. Note that this code is not generalizable.
+     */
+    @Override
+    protected void runChild(InstrumentTestCase testCase, RunNotifier notifier) {
+        // TODO Current tests are hard-coded, automate this eventually
+        notifier.fireTestStarted(testCase.name);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        PrintWriter printer = new PrintWriter(out);
+        final ASTProber prober = new SLStandardASTProber();
+        Probe.registerASTProber(prober);
+        try {
+            // We use the name of the file to determine what visitor to attach to it.
+            if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
+                // Set up the execution context for Simple and register our two listeners
+                slContext = SLContextFactory.create(new BufferedReader(new StringReader(testCase.testInput)), printer);
+
+                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
+                Parser.parseSL(slContext, source);
+
+                // Attach an instrument to every probe tagged as an assignment
+                for (Probe probe : Probe.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
+                    SLPrintAssigmentValueListener slPrintAssigmentValueListener = new SLPrintAssigmentValueListener(printer);
+                    probe.attach(Instrument.create(slPrintAssigmentValueListener, "SL print assignment value"));
+                }
+
+                SLFunction main = slContext.getFunctionRegistry().lookup("main");
+                main.getCallTarget().call();
+            } else {
+                notifier.fireTestFailure(new Failure(testCase.name, new UnsupportedOperationException("No instrumentation found.")));
+            }
+
+            printer.flush();
+            String actualOutput = new String(out.toByteArray());
+            Assert.assertEquals(testCase.expectedOutput, actualOutput);
+        } catch (Throwable ex) {
+            notifier.fireTestFailure(new Failure(testCase.name, ex));
+        } finally {
+            Probe.unregisterASTProber(prober);
+            notifier.fireTestFinished(testCase.name);
+        }
+
+    }
+
+    public static void runInMain(Class<?> testClass, String[] args) throws InitializationError, NoTestsRemainException {
+        JUnitCore core = new JUnitCore();
+        core.addListener(new TextListener(System.out));
+        SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass);
+        if (args.length > 0) {
+            suite.filter(new NameFilter(args[0]));
+        }
+        Result r = core.run(suite);
+        if (!r.wasSuccessful()) {
+            System.exit(1);
+        }
+    }
+
+    private static final class NameFilter extends Filter {
+        private final String pattern;
+
+        private NameFilter(String pattern) {
+            this.pattern = pattern.toLowerCase();
+        }
+
+        @Override
+        public boolean shouldRun(Description description) {
+            return description.getMethodName().toLowerCase().contains(pattern);
+        }
+
+        @Override
+        public String describe() {
+            return "Filter contains " + pattern;
+        }
+    }
+
+    /**
+     * This sample listener provides prints the value of an assignment (after the assignment is
+     * complete) to the {@link PrintWriter} specified in the constructor. This listener can only be
+     * attached at {@link SLWriteLocalVariableNode}, but provides no guards to protect it from being
+     * attached elsewhere.
+     */
+    public final class SLPrintAssigmentValueListener extends DefaultSimpleInstrumentListener {
+
+        private PrintWriter output;
+
+        public SLPrintAssigmentValueListener(PrintWriter output) {
+            this.output = output;
+        }
+
+        @Override
+        public void returnValue(Probe probe, Object result) {
+            output.println(result);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestSuite.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test.instrument;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface SLInstrumentTestSuite {
+
+    /**
+     * Defines the base path of the test suite. Multiple base paths can be specified. However only
+     * the first base that exists is used to lookup the test cases.
+     */
+    String[] value();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLSimpleInstrumentTestSuite.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test.instrument;
+
+import org.junit.*;
+import org.junit.runner.*;
+
+@RunWith(SLInstrumentTestRunner.class)
+@SLInstrumentTestSuite({"truffle/com.oracle.truffle.sl.test/tests_instrumentation", "tests_instrumentation"})
+public class SLSimpleInstrumentTestSuite {
+
+    public static void main(String[] args) throws Exception {
+        SLInstrumentTestRunner.runInMain(SLSimpleInstrumentTestSuite.class, args);
+    }
+
+    /*
+     * Our "mx unittest" command looks for methods that are annotated with @Test. By just defining
+     * an empty method, this class gets included and the test suite is properly executed.
+     */
+    @Test
+    public void unittest() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Add.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,7 @@
+7
+34
+34
+34
+4000000000003
+3000000000004
+7000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Add.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,9 @@
+function main() {  
+  println(3 + 4);  
+  println(3 + "4");  
+  println("3" + 4);  
+  println("3" + "4");  
+  println(3 + 4000000000000);  
+  println(3000000000000 + 4);  
+  println(3000000000000 + 4000000000000);  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Arithmetic.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,10 @@
+5
+1
+-3
+14
+11
+5
+-3
+1
+18
+11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Arithmetic.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,12 @@
+function main() {  
+  println(3 + 4 - 2);  
+  println(3 - 4 + 2);  
+  println(3 - 4 - 2);  
+  println(3 * 4 + 2);  
+  println(3 + 4 * 2);  
+  println(3 + (4 - 2));  
+  println(3 - (4 + 2));  
+  println(3 - (4 - 2));  
+  println(3 * (4 + 2));  
+  println(3 + (4 * 2));  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Break.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Break.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,10 @@
+function main() {  
+  i = 0;  
+  while (i < 1000) {
+    if (i >= 942) {
+      break;
+    }  
+    i = i + 1;  
+  }
+  return i;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Builtins.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Hello World!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Builtins.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,4 @@
+function main() {  
+  println("Hello World!");  
+  nanoTime();  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/CalcShell.input	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,15 @@
+i
+80
+c
+return cur + i;
+r
+c
+if (i <= 2) { return 1; } else { return prev + cur; }
+r
+i
+100
+r
+c
+if (i == 0) { return 1; } else { return cur * i; }
+r
+x
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/CalcShell.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,35 @@
+available commands:
+x: exit
+c: define the calculation function with the parameters prev, cur, and i
+   prev and cur start with 0; i is the loop variable from 0 to n
+     example: 'return cur + i;' computes the sum of 1 to n
+     example: 'if (i == 0) { return 1; } else { return cur * i; }' computes the factorial of i
+     example: 'if (i <= 2) { return 1; } else { return prev + cur; }' computes the nth Fibonacci number
+i: define the number of iterations, i.e, the number n in the examples above
+r: Run the calculation loop often, and print the first and last result
+t: Run the calculation loop a couple of time, and print timing information for each run
+h: Print this help message
+
+cmd>
+n>
+cmd>
+function>
+cmd>
+** first: 3240
+** last:  3240
+cmd>
+function>
+cmd>
+** first: 23416728348467685
+** last:  23416728348467685
+cmd>
+n>
+cmd>
+** first: 354224848179261915075
+** last:  354224848179261915075
+cmd>
+function>
+cmd>
+** first: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
+** last:  93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
+cmd>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/CalcShell.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,89 @@
+function iterations() {
+  return 80;
+}
+
+function calcLoop(n) {
+  i = 0;
+  prev = cur = 0;
+  while (i <= n) {
+    next = calc(prev, cur, i);
+    prev = cur;
+    cur = next;  
+    i = i + 1;
+  }  
+  return cur;  
+}
+
+function timing(n) {
+  i = 0;
+  while (i < 20) {
+    start = nanoTime();
+    calcLoop(n);
+    end = nanoTime();
+    i = i + 1;
+
+    println("** run " + i + ": " + (end - start) + " ns");
+  }
+}
+
+function run(n) {
+  firstResult = calcLoop(n);
+  println("** first: " + firstResult);
+  i = 0;
+  while (i < 100) {
+    calcLoop(n);
+    i = i + 1;
+  }
+  lastResult = calcLoop(n);
+  println("** last:  " + lastResult);
+  
+  if (firstResult != lastResult) {
+    println("ERROR: result not stable");
+  }
+}  
+
+function help() {
+  println("available commands:");
+  println("x: exit");
+  println("c: define the calculation function with the parameters prev, cur, and i");
+  println("   prev and cur start with 0; i is the loop variable from 0 to n");
+  println("     example: 'return cur + i;' computes the sum of 1 to n"); 
+  println("     example: 'if (i == 0) { return 1; } else { return cur * i; }' computes the factorial of i"); 
+  println("     example: 'if (i <= 2) { return 1; } else { return prev + cur; }' computes the nth Fibonacci number");
+  println("i: define the number of iterations, i.e, the number n in the examples above");
+  println("r: Run the calculation loop often, and print the first and last result");
+  println("t: Run the calculation loop a couple of time, and print timing information for each run");
+  println("h: Print this help message");
+  println("");
+}
+
+function main() {
+  help();
+  
+  while (1 == 1) {
+    println("cmd>");
+    cmd = readln();
+    if (cmd == "x" || cmd == "") {
+      return;
+    }
+    if (cmd == "h") {
+      help();
+    }
+    if (cmd == "c") {
+      println("function>");
+      code = readln();
+      defineFunction("function calc(prev, cur, i) { " + code + "}");
+    }
+    if (cmd == "t") {
+      timing(iterations());
+    }
+    if (cmd == "r") {
+      run(iterations());
+    }
+    if (cmd == "i") {
+      println("n>");
+      n = readln();
+      defineFunction("function iterations() { return " + n + "; }");
+    }
+  }
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Call.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,8 @@
+42
+42
+42
+42
+42
+42
+42
+42
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Call.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,16 @@
+function ret(a) { return a; } 
+function dub(a) { return a * 2; } 
+function inc(a) { return a + 1; } 
+function dec(a) { return a - 1; } 
+function call(f, v) { return f(v); }
+ 
+function main() {  
+  println(ret(42));
+  println(dub(21));
+  println(inc(41));
+  println(dec(43));
+  println(call(ret, 42));
+  println(call(dub, 21));
+  println(call(inc, 41));
+  println(call(dec, 43));
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Comparison.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+<
+true
+false
+false
+true
+false
+true
+false
+false
+<=
+true
+false
+true
+true
+false
+true
+false
+true
+>
+false
+true
+false
+false
+true
+false
+true
+false
+>=
+false
+true
+true
+false
+true
+false
+true
+true
+==
+false
+false
+true
+false
+false
+false
+false
+true
+!=
+true
+true
+false
+true
+true
+true
+true
+false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Comparison.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,61 @@
+function main() {  
+  println("<");
+  println(4 < 20);  
+  println(40 < 2);  
+  println(4 < 4);  
+  println(4 < 200000000000000000000000000);  
+  println(40000000000000000000000000 < 20);  
+  println(40000000000000000000000000 < 200000000000000000000000000);  
+  println(400000000000000000000000000 < 20000000000000000000000000);  
+  println(40000000000000000000000000 < 40000000000000000000000000);  
+
+  println("<=");
+  println(4 <= 20);  
+  println(40 <= 2);  
+  println(4 <= 4);  
+  println(4 <= 200000000000000000000000000);  
+  println(40000000000000000000000000 <= 20);  
+  println(40000000000000000000000000 <= 200000000000000000000000000);  
+  println(400000000000000000000000000 <= 20000000000000000000000000);  
+  println(40000000000000000000000000 <= 40000000000000000000000000);  
+
+  println(">");
+  println(4 > 20);  
+  println(40 > 2);  
+  println(4 > 4);  
+  println(4 > 200000000000000000000000000);  
+  println(40000000000000000000000000 > 20);  
+  println(40000000000000000000000000 > 200000000000000000000000000);  
+  println(400000000000000000000000000 > 20000000000000000000000000);  
+  println(40000000000000000000000000 > 40000000000000000000000000);  
+
+  println(">=");
+  println(4 >= 20);  
+  println(40 >= 2);  
+  println(4 >= 4);  
+  println(4 >= 200000000000000000000000000);  
+  println(40000000000000000000000000 >= 20);  
+  println(40000000000000000000000000 >= 200000000000000000000000000);  
+  println(400000000000000000000000000 >= 20000000000000000000000000);  
+  println(40000000000000000000000000 >= 40000000000000000000000000);  
+
+  println("==");
+  println(4 == 20);  
+  println(40 == 2);  
+  println(4 == 4);  
+  println(4 == 200000000000000000000000000);  
+  println(40000000000000000000000000 == 20);  
+  println(40000000000000000000000000 == 200000000000000000000000000);  
+  println(400000000000000000000000000 == 20000000000000000000000000);  
+  println(40000000000000000000000000 == 40000000000000000000000000);  
+
+  println("!=");
+  println(4 != 20);  
+  println(40 != 2);  
+  println(4 != 4);  
+  println(4 != 200000000000000000000000000);  
+  println(40000000000000000000000000 != 20);  
+  println(40000000000000000000000000 != 200000000000000000000000000);  
+  println(400000000000000000000000000 != 20000000000000000000000000);  
+  println(40000000000000000000000000 != 40000000000000000000000000);  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/ControlFlow.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/ControlFlow.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,10 @@
+function foo() {}
+function bar() {}
+
+function main() {  
+  foo();
+  if (1 < 2) {
+    bar();
+    return 1;
+  }
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/DefineFunction.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,2 @@
+42
+38
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/DefineFunction.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,11 @@
+function foo() {
+  println(test(40, 2));
+}
+
+function main() {
+  defineFunction("function test(a, b) { return a + b; }");
+  foo();
+
+  defineFunction("function test(a, b) { return a - b; }");
+  foo();
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Div.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,4 @@
+2
+0
+1000000000000
+1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Div.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,6 @@
+function main() {  
+  println(4 / 2);  
+  println(4 / 4000000000000);  
+  println(3000000000000 / 3);  
+  println(3000000000000 / 3000000000000);  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Fibonacci.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,10 @@
+1: 1
+2: 1
+3: 2
+4: 3
+5: 5
+6: 8
+7: 13
+8: 21
+9: 34
+10: 55
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Fibonacci.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,21 @@
+function fib(num) { 
+  if (num < 1) {return 0;}
+  n1 = 0;
+  n2 = 1;
+  i = 1;
+  while (i < num) {
+    next = n2 + n1;
+    n1 = n2;
+    n2 = next;
+    i = i + 1;
+  }
+  return n2;
+}
+
+function main() {  
+  i = 1;
+  while (i <= 10) {
+    println(i + ": " + fib(i));
+    i = i + 1;
+  }
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/FunctionLiteral.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,2 @@
+42
+38
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/FunctionLiteral.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,16 @@
+function add(a, b) {
+  return a + b;
+}
+
+function sub(a, b) {
+  return a - b;
+}
+
+function foo(f) {
+  println(f(40, 2));
+}
+
+function main() {
+  foo(add);
+  foo(sub);
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,90 @@
+Initial stack trace:
+Frame: root doIt, a=0, hello=null
+Frame: root main, i=0
+After 123 assignment:
+Frame: root doIt, a=0, hello=123
+Frame: root main, i=0
+After hello assignment:
+Frame: root doIt, a=0, hello=world
+Frame: root main, i=0
+Initial stack trace:
+Frame: root doIt, a=1, hello=null
+Frame: root main, i=1
+After 123 assignment:
+Frame: root doIt, a=1, hello=123
+Frame: root main, i=1
+After hello assignment:
+Frame: root doIt, a=1, hello=world
+Frame: root main, i=1
+Initial stack trace:
+Frame: root doIt, a=2, hello=null
+Frame: root main, i=2
+After 123 assignment:
+Frame: root doIt, a=2, hello=123
+Frame: root main, i=2
+After hello assignment:
+Frame: root doIt, a=2, hello=world
+Frame: root main, i=2
+Initial stack trace:
+Frame: root doIt, a=3, hello=null
+Frame: root main, i=3
+After 123 assignment:
+Frame: root doIt, a=3, hello=123
+Frame: root main, i=3
+After hello assignment:
+Frame: root doIt, a=3, hello=world
+Frame: root main, i=3
+Initial stack trace:
+Frame: root doIt, a=4, hello=null
+Frame: root main, i=4
+After 123 assignment:
+Frame: root doIt, a=4, hello=123
+Frame: root main, i=4
+After hello assignment:
+Frame: root doIt, a=4, hello=world
+Frame: root main, i=4
+Initial stack trace:
+Frame: root doIt, a=5, hello=null
+Frame: root main, i=5
+After 123 assignment:
+Frame: root doIt, a=5, hello=123
+Frame: root main, i=5
+After hello assignment:
+Frame: root doIt, a=5, hello=world
+Frame: root main, i=5
+Initial stack trace:
+Frame: root doIt, a=6, hello=null
+Frame: root main, i=6
+After 123 assignment:
+Frame: root doIt, a=6, hello=123
+Frame: root main, i=6
+After hello assignment:
+Frame: root doIt, a=6, hello=world
+Frame: root main, i=6
+Initial stack trace:
+Frame: root doIt, a=7, hello=null
+Frame: root main, i=7
+After 123 assignment:
+Frame: root doIt, a=7, hello=123
+Frame: root main, i=7
+After hello assignment:
+Frame: root doIt, a=7, hello=world
+Frame: root main, i=7
+Initial stack trace:
+Frame: root doIt, a=8, hello=null
+Frame: root main, i=8
+After 123 assignment:
+Frame: root doIt, a=8, hello=123
+Frame: root main, i=8
+After hello assignment:
+Frame: root doIt, a=8, hello=world
+Frame: root main, i=8
+Initial stack trace:
+Frame: root doIt, a=9, hello=null
+Frame: root main, i=9
+After 123 assignment:
+Frame: root doIt, a=9, hello=123
+Frame: root main, i=9
+After hello assignment:
+Frame: root doIt, a=9, hello=world
+Frame: root main, i=9
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/HelloEqualsWorld.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,22 @@
+function doIt(a) {
+  println("Initial stack trace:");
+  println(stacktrace());
+  
+  hello = 123;
+  println("After 123 assignment:");
+  println(stacktrace());
+  
+  helloEqualsWorld();
+  println("After hello assignment:");
+  println(stacktrace());
+  
+//  readln();
+}
+
+function main() {
+  i = 0;
+  while (i < 10) {
+    doIt(i);
+    i = i + 1;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/HelloWorld.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Hello World!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/HelloWorld.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  println("Hello World!");  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Inlining.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1260000
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Inlining.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,18 @@
+
+function a() {return 42;}
+function b() {return a();}
+function c() {return b();}
+function d() {return c();}
+function e() {return c();}
+function f() {return c();}
+function g() {return d() + e() + f();}
+
+function main() {
+    i = 0;
+    result = 0;
+    while (i < 10000) {
+        result = result + g();
+        i = i + 1;
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Loop.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Loop.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,7 @@
+function main() {  
+  i = 0;  
+  while (i < 1000) {  
+    i = i + 1;  
+  }  
+  return i;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopCall.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopCall.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,20 @@
+function add(a, b) {
+  return a + b;
+}
+
+function loop(n) {
+  i = 0;
+  while (i < n) {  
+    i = add(i, 1);  
+  }
+  return i;
+}
+
+function main() {
+  i = 0;
+  while (i < 20) {
+    loop(1000);
+    i = i + 1;
+  }
+  println(loop(1000));  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopInvalidate.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopInvalidate.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,21 @@
+function add(a, b) {
+  return a + b;
+}
+
+function loop(n) {
+  i = 0;  
+  while (i < n) {  
+    i = add(i, 1);  
+  }  
+  return i;
+}  
+
+function main() {
+  i = 0;
+  while (i < 20) {
+    loop(1000);
+    i = i + 1;
+  }
+  add("a", "b");
+  println(loop(1000));  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,22 @@
+function add(a, b) {
+  return a + b;
+}
+
+function loop(n) {
+  i = 0;
+  while (i < n) {
+    i = add(i, 1); 
+  }
+  return i;
+}
+
+function main() {
+  add("a", "b");
+
+  i = 0;
+  while (i < 20) {
+    loop(1000);
+    i = i + 1;
+  }
+  println(loop(1000));  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopPrint.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/LoopPrint.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,16 @@
+function loop(n) {
+  i = 0;  
+  while (i < n) {  
+    i = i + 1;  
+  }  
+  return i;
+}  
+
+function main() {
+  i = 0;
+  while (i < 20) {
+    loop(1000);
+    i = i + 1;
+  }
+  println(loop(1000));  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Mul.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,4 @@
+12
+12000000000000
+12000000000000
+12000000000000000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Mul.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,6 @@
+function main() {  
+  println(3 * 4);  
+  println(3 * 4000000000000);  
+  println(3000000000000 * 4);  
+  println(3000000000000 * 4000000000000);  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Null.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,7 @@
+null
+true
+false
+false
+true
+false
+true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Null.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,13 @@
+/* The easiest way to generate null: a function without a return statement implicitly returns null. */
+function null() {
+}
+
+function main() {  
+  println(null());  
+  println(null() == null());  
+  println(null() != null());  
+  println(null() == 42);  
+  println(null() != 42);  
+  println(null() == "42");  
+  println(null() != "42");  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Object.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,6 @@
+null
+42
+42
+why
+zzz
+zzz
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Object.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+function main() {  
+  obj1 = new();
+  println(obj1.x);
+  obj1.x = 42;
+  println(obj1.x);
+  
+  obj2 = new();
+  obj2.o = obj1;
+  println(obj2.o.x);
+  obj2.o.y = "why";
+  println(obj1.y);
+  
+  println(mkobj().z);
+  
+  obj3 = new();
+  obj3.fn = mkobj;
+  println(obj3.fn().z);
+
+  obj4 = new();
+  write(obj4, 1);
+  read(obj4);
+  write(obj4, 2);
+  read(obj4);
+  write(obj4, "three");
+  read(obj4);
+}
+
+function mkobj() {
+  newobj = new();
+  newobj.z = "zzz";
+  return newobj;
+}
+
+function read(obj) {
+  return obj.prop;
+}
+
+function write(obj, value) {
+  return obj.prop = value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/String.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,10 @@
+snull
+snull
+sbar
+sfoo
+nulls
+nulls
+bars
+foos
+2 < 4: true
+Type error at String.sl line 9 col 34: operation "<" not defined for Number 2, String "4"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/String.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,25 @@
+function null() {
+}
+
+function foo() {
+  return "bar";
+}
+
+function f(a, b) {
+  return a + " < " + b + ": " + (a < b);
+}
+
+function main() {  
+  println("s" + null());  
+  println("s" + null);  
+  println("s" + foo());  
+  println("s" + foo);
+    
+  println(null() + "s");  
+  println(null() + "s");  
+  println(foo() + "s");  
+  println(foo + "s");
+
+  println(f(2, 4));
+  println(f(2, "4"));
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Sub.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,4 @@
+-1
+-3999999999997
+2999999999996
+-1000000000000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Sub.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,6 @@
+function main() {  
+  println(3 - 4);  
+  println(3 - 4000000000000);  
+  println(3000000000000 - 4);  
+  println(3000000000000 - 4000000000000);  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Sum.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+50005000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/Sum.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,9 @@
+function main() {  
+  i = 0;  
+  sum = 0;  
+  while (i <= 10000) {  
+    sum = sum + i;  
+    i = i + 1;  
+  }  
+  return sum;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError01.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error at TypeError01.sl line 2 col 3: operation "-" not defined for Number 3, String "4"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError01.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  3 - "4";  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError02.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error at TypeError02.sl line 2 col 3: operation "if" not defined for String "4"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError02.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  if ("4") { }  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError03.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error at TypeError03.sl line 2 col 3: operation "&&" not defined for String "4", ANY
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError03.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  "4" && 4;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError04.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error at TypeError04.sl line 2 col 3: operation "||" not defined for Boolean false, Number 4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError04.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  (1 > 2) || 4;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError05.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error at TypeError05.sl line 3 col 3: operation "invoke" not defined for Boolean true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError05.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,4 @@
+function main() {
+  f = 1 < 2;
+  f();  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError06.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error: operation "defineFunction" not defined for Number 3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError06.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {
+  defineFunction(3);
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError07.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Type error: operation "defineFunction" not defined for NULL
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/TypeError07.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {
+  defineFunction();
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1 @@
+Undefined function: foo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests/error/UndefinedFunction01.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,3 @@
+function main() {  
+  foo();
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,103 @@
+100
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+100
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,11 @@
+function loop(count) {  
+  i = 0;  
+  while (i < count) {  
+    i = i + 1;  
+  }  
+  return i;  
+}
+
+function main() {
+  count = loop(100);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLHandler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.tools.debug;
+
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.debug.shell.*;
+import com.oracle.truffle.tools.debug.shell.client.*;
+import com.oracle.truffle.tools.debug.shell.server.*;
+
+/**
+ * Instantiation of the "server handler" part of the "REPL*" debugger for the simple language.
+ * <p>
+ * These handlers implement debugging commands that require language-specific support.
+ *
+ * @see SimpleREPLClient
+ */
+public abstract class SLREPLHandler extends REPLHandler {
+
+    protected SLREPLHandler(String op) {
+        super(op);
+    }
+
+    public static final SLREPLHandler INFO_HANDLER = new SLREPLHandler(REPLMessage.INFO) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final String topic = request.get(REPLMessage.TOPIC);
+
+            if (topic == null || topic.isEmpty()) {
+                final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
+                return finishReplyFailed(message, "No info topic specified");
+            }
+
+            switch (topic) {
+
+                case REPLMessage.LANGUAGE:
+                    return createLanguageInfoReply();
+
+                default:
+                    final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
+                    return finishReplyFailed(message, "No info about topic \"" + topic + "\"");
+            }
+        }
+    };
+
+    private static REPLMessage[] createLanguageInfoReply() {
+        final ArrayList<REPLMessage> langMessages = new ArrayList<>();
+
+        final REPLMessage msg1 = new REPLMessage(REPLMessage.OP, REPLMessage.INFO);
+        msg1.put(REPLMessage.TOPIC, REPLMessage.LANGUAGE);
+        msg1.put(REPLMessage.INFO_KEY, "Language");
+        msg1.put(REPLMessage.INFO_VALUE, "Simple");
+        msg1.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+        langMessages.add(msg1);
+
+        return langMessages.toArray(new REPLMessage[0]);
+    }
+
+    public static final SLREPLHandler LOAD_RUN_SOURCE_HANDLER = new SLREPLHandler(REPLMessage.LOAD_RUN) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            return loadHandler(request, serverContext, false);
+        }
+    };
+
+    public static final SLREPLHandler LOAD_STEP_SOURCE_HANDLER = new SLREPLHandler(REPLMessage.LOAD_STEP) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            return loadHandler(request, serverContext, true);
+        }
+    };
+
+    /**
+     * Runs a source, optionally stepping into a specified tag.
+     */
+    private static REPLMessage[] loadHandler(REPLMessage request, REPLServerContext serverContext, boolean stepInto) {
+        final REPLMessage reply = new REPLMessage(REPLMessage.OP, REPLMessage.LOAD_RUN);
+        final String fileName = request.get(REPLMessage.SOURCE_NAME);
+        try {
+            final Source source = Source.fromFileName(fileName, true);
+            if (source == null) {
+                return finishReplyFailed(reply, "can't find file \"" + fileName + "\"");
+            }
+            serverContext.getDebugEngine().run(source, stepInto);
+            reply.put(REPLMessage.FILE_PATH, source.getPath());
+            return finishReplySucceeded(reply, source.getName() + "  exited");
+        } catch (QuitException ex) {
+            throw ex;
+        } catch (KillException ex) {
+            return finishReplySucceeded(reply, fileName + " killed");
+        } catch (Exception ex) {
+            return finishReplyFailed(reply, "error loading file \"" + fileName + "\": " + ex.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl.tools/src/com/oracle/truffle/sl/tools/debug/SLREPLServer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.tools.debug;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.tools.debug.engine.*;
+import com.oracle.truffle.tools.debug.shell.*;
+import com.oracle.truffle.tools.debug.shell.client.*;
+import com.oracle.truffle.tools.debug.shell.server.*;
+
+/**
+ * Instantiation of the "server" side of the "REPL*" debugger for the Simple language.
+ * <p>
+ * The SL parser is not equipped to parse program fragments, so any debugging functions that depend
+ * on this are not supported, for example {@link DebugEngine#eval(Source, Node, MaterializedFrame)}
+ * and {@link Breakpoint#setCondition(String)}.
+ *
+ * @see SimpleREPLClient
+ */
+public final class SLREPLServer implements REPLServer {
+
+    // TODO (mlvdv) remove when there's a better way to express this dependency
+    @SuppressWarnings("unused") private static final Class<SLLanguage> DYNAMIC_DEPENDENCY = com.oracle.truffle.sl.SLLanguage.class;
+
+    public static void main(String[] args) {
+        // Cheating for the prototype: start from SL, rather than from the client.
+        final SLREPLServer server = new SLREPLServer();
+        final SimpleREPLClient client = new SimpleREPLClient(server.language.getShortName(), server);
+
+        // Cheating for the prototype: allow server access to client for recursive debugging
+        server.setClient(client);
+
+        try {
+            client.start();
+        } catch (QuitException ex) {
+        }
+    }
+
+    private final Language language;
+    private final DebugEngine slDebugEngine;
+    private final String statusPrefix;
+    private final Map<String, REPLHandler> handlerMap = new HashMap<>();
+    private SLServerContext currentServerContext;
+    private SimpleREPLClient replClient = null;
+
+    private void add(REPLHandler fileHandler) {
+        handlerMap.put(fileHandler.getOp(), fileHandler);
+    }
+
+    public SLREPLServer() {
+        add(REPLHandler.BACKTRACE_HANDLER);
+        add(REPLHandler.BREAK_AT_LINE_HANDLER);
+        add(REPLHandler.BREAK_AT_LINE_ONCE_HANDLER);
+        add(REPLHandler.BREAK_AT_THROW_HANDLER);
+        add(REPLHandler.BREAK_AT_THROW_ONCE_HANDLER);
+        add(REPLHandler.BREAKPOINT_INFO_HANDLER);
+        add(REPLHandler.CLEAR_BREAK_HANDLER);
+        add(REPLHandler.CONTINUE_HANDLER);
+        add(REPLHandler.DELETE_HANDLER);
+        add(REPLHandler.DISABLE_BREAK_HANDLER);
+        add(REPLHandler.ENABLE_BREAK_HANDLER);
+        add(REPLHandler.FILE_HANDLER);
+        add(REPLHandler.FRAME_HANDLER);
+        add(SLREPLHandler.INFO_HANDLER);
+        add(REPLHandler.KILL_HANDLER);
+        add(SLREPLHandler.LOAD_RUN_SOURCE_HANDLER);
+        add(SLREPLHandler.LOAD_STEP_SOURCE_HANDLER);
+        add(REPLHandler.QUIT_HANDLER);
+        add(REPLHandler.STEP_INTO_HANDLER);
+        add(REPLHandler.STEP_OUT_HANDLER);
+        add(REPLHandler.STEP_OVER_HANDLER);
+        add(REPLHandler.TRUFFLE_HANDLER);
+        add(REPLHandler.TRUFFLE_NODE_HANDLER);
+
+        TruffleVM vm = TruffleVM.newVM().build();
+        this.language = vm.getLanguages().get("application/x-sl");
+        assert language != null;
+
+        final SLREPLDebugClient slDebugClient = new SLREPLDebugClient(language);
+        this.slDebugEngine = DebugEngine.create(slDebugClient, language);
+
+        this.statusPrefix = language.getShortName() + " REPL:";
+    }
+
+    private void setClient(SimpleREPLClient replClient) {
+        this.replClient = replClient;
+    }
+
+    public REPLMessage start() {
+
+        this.currentServerContext = new SLServerContext(null, null, null);
+
+        // SL doesn't load modules (like other languages), so we just return a success
+        final REPLMessage reply = new REPLMessage();
+        reply.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+        reply.put(REPLMessage.DISPLAY_MSG, language.getShortName() + " started");
+        return reply;
+    }
+
+    public REPLMessage[] receive(REPLMessage request) {
+        if (currentServerContext == null) {
+            final REPLMessage message = new REPLMessage();
+            message.put(REPLMessage.STATUS, REPLMessage.FAILED);
+            message.put(REPLMessage.DISPLAY_MSG, "server not started");
+            final REPLMessage[] reply = new REPLMessage[]{message};
+            return reply;
+        }
+        return currentServerContext.receive(request);
+    }
+
+    /**
+     * Execution context of a halted SL program.
+     */
+    public final class SLServerContext extends REPLServerContext {
+
+        private final SLServerContext predecessor;
+
+        public SLServerContext(SLServerContext predecessor, Node astNode, MaterializedFrame mFrame) {
+            super(predecessor == null ? 0 : predecessor.getLevel() + 1, astNode, mFrame);
+            this.predecessor = predecessor;
+        }
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request) {
+            final String command = request.get(REPLMessage.OP);
+            final REPLHandler handler = handlerMap.get(command);
+
+            if (handler == null) {
+                final REPLMessage message = new REPLMessage();
+                message.put(REPLMessage.OP, command);
+                message.put(REPLMessage.STATUS, REPLMessage.FAILED);
+                message.put(REPLMessage.DISPLAY_MSG, statusPrefix + " op \"" + command + "\" not supported");
+                final REPLMessage[] reply = new REPLMessage[]{message};
+                return reply;
+            }
+            return handler.receive(request, currentServerContext);
+        }
+
+        @Override
+        public Language getLanguage() {
+            return language;
+        }
+
+        @Override
+        public DebugEngine getDebugEngine() {
+            return slDebugEngine;
+        }
+
+    }
+
+    /**
+     * Specialize the standard SL debug context by notifying the REPL client when execution is
+     * halted, e.g. at a breakpoint.
+     * <p>
+     * Before notification, the server creates a new context at the halted location, in which
+     * subsequent evaluations take place until such time as the client says to "continue".
+     * <p>
+     * This implementation "cheats" the intended asynchronous architecture by calling back directly
+     * to the client with the notification.
+     */
+    private final class SLREPLDebugClient implements DebugClient {
+
+        private final Language language;
+
+        SLREPLDebugClient(Language language) {
+            this.language = language;
+        }
+
+        public void haltedAt(Node node, MaterializedFrame mFrame, List<String> warnings) {
+            // Create and push a new debug context where execution is halted
+            currentServerContext = new SLServerContext(currentServerContext, node, mFrame);
+
+            // Message the client that execution is halted and is in a new debugging context
+            final REPLMessage message = new REPLMessage();
+            message.put(REPLMessage.OP, REPLMessage.STOPPED);
+            final SourceSection src = node.getSourceSection();
+            final Source source = src.getSource();
+            message.put(REPLMessage.SOURCE_NAME, source.getName());
+            message.put(REPLMessage.FILE_PATH, source.getPath());
+            message.put(REPLMessage.LINE_NUMBER, Integer.toString(src.getStartLine()));
+            message.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+            message.put(REPLMessage.DEBUG_LEVEL, Integer.toString(currentServerContext.getLevel()));
+            if (!warnings.isEmpty()) {
+                final StringBuilder sb = new StringBuilder();
+                for (String warning : warnings) {
+                    sb.append(warning + "\n");
+                }
+                message.put(REPLMessage.WARNINGS, sb.toString());
+            }
+            try {
+                // Cheat with synchrony: call client directly about entering a nested debugging
+                // context.
+                replClient.halted(message);
+            } finally {
+                // Returns when "continue" is called in the new debugging context
+
+                // Pop the debug context, and return so that the old context will continue
+                currentServerContext = currentServerContext.predecessor;
+            }
+        }
+
+        public Language getLanguage() {
+            return language;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLAssertionError.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+/**
+ * An implementation of an {@link AssertionError} also containing the guest language stack trace.
+ */
+public class SLAssertionError extends AssertionError {
+
+    private static final long serialVersionUID = -9138475336963945873L;
+
+    public SLAssertionError(String message) {
+        super(message);
+        initCause(new AssertionError("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return SLException.fillInSLStackTrace(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * SL does not need a sophisticated error checking and reporting mechanism, so all unexpected
+ * conditions just abort execution. This exception class is used when we abort from within the SL
+ * implementation.
+ */
+public class SLException extends RuntimeException {
+
+    private static final long serialVersionUID = -6799734410727348507L;
+
+    public SLException(String message) {
+        super(message);
+        initCause(new Throwable("Java stack trace"));
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return fillInSLStackTrace(this);
+    }
+
+    /**
+     * Uses the Truffle API to iterate the stack frames and to create and set Java
+     * {@link StackTraceElement} elements based on the source sections of the call nodes on the
+     * stack.
+     */
+    static Throwable fillInSLStackTrace(Throwable t) {
+        final List<StackTraceElement> stackTrace = new ArrayList<>();
+        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
+            public Void visitFrame(FrameInstance frame) {
+                Node callNode = frame.getCallNode();
+                if (callNode == null) {
+                    return null;
+                }
+                RootNode root = callNode.getRootNode();
+
+                /*
+                 * There should be no RootNodes other than SLRootNodes on the stack. Just for the
+                 * case if this would change.
+                 */
+                String methodName = "$unknownFunction";
+                if (root instanceof SLRootNode) {
+                    methodName = ((SLRootNode) root).getName();
+                }
+
+                SourceSection sourceSection = callNode.getEncapsulatingSourceSection();
+                Source source = sourceSection != null ? sourceSection.getSource() : null;
+                String sourceName = source != null ? source.getName() : null;
+                int lineNumber;
+                try {
+                    lineNumber = sourceSection != null ? sourceSection.getLineLocation().getLineNumber() : -1;
+                } catch (UnsupportedOperationException e) {
+                    /*
+                     * SourceSection#getLineLocation() may throw an UnsupportedOperationException.
+                     */
+                    lineNumber = -1;
+                }
+                stackTrace.add(new StackTraceElement("SL", methodName, sourceName, lineNumber));
+                return null;
+            }
+        });
+        t.setStackTrace(stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
+        return t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+import java.io.*;
+import java.math.*;
+import java.net.*;
+import java.util.*;
+import java.util.Scanner;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.*;
+import com.oracle.truffle.api.vm.TruffleVM.Symbol;
+import com.oracle.truffle.sl.builtins.*;
+import com.oracle.truffle.sl.factory.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.call.*;
+import com.oracle.truffle.sl.nodes.controlflow.*;
+import com.oracle.truffle.sl.nodes.expression.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+import com.oracle.truffle.tools.*;
+
+/**
+ * SL is a simple language to demonstrate and showcase features of Truffle. The implementation is as
+ * simple and clean as possible in order to help understanding the ideas and concepts of Truffle.
+ * The language has first class functions, but no object model.
+ * <p>
+ * SL is dynamically typed, i.e., there are no type names specified by the programmer. SL is
+ * strongly typed, i.e., there is no automatic conversion between types. If an operation is not
+ * available for the types encountered at run time, a type error is reported and execution is
+ * stopped. For example, {@code 4 - "2"} results in a type error because subtraction is only defined
+ * for numbers.
+ *
+ * <p>
+ * <b>Types:</b>
+ * <ul>
+ * <li>Number: arbitrary precision integer numbers. The implementation uses the Java primitive type
+ * {@code long} to represent numbers that fit into the 64 bit range, and {@link BigInteger} for
+ * numbers that exceed the range. Using a primitive type such as {@code long} is crucial for
+ * performance.
+ * <li>Boolean: implemented as the Java primitive type {@code boolean}.
+ * <li>String: implemented as the Java standard type {@link String}.
+ * <li>Function: implementation type {@link SLFunction}.
+ * <li>Null (with only one value {@code null}): implemented as the singleton
+ * {@link SLNull#SINGLETON}.
+ * </ul>
+ * The class {@link SLTypes} lists these types for the Truffle DSL, i.e., for type-specialized
+ * operations that are specified using Truffle DSL annotations.
+ *
+ * <p>
+ * <b>Language concepts:</b>
+ * <ul>
+ * <li>Literals for {@link SLBigIntegerLiteralNode numbers} , {@link SLStringLiteralNode strings},
+ * and {@link SLFunctionLiteralNode functions}.
+ * <li>Basic arithmetic, logical, and comparison operations: {@link SLAddNode +}, {@link SLSubNode
+ * -}, {@link SLMulNode *}, {@link SLDivNode /}, {@link SLLogicalAndNode logical and},
+ * {@link SLLogicalOrNode logical or}, {@link SLEqualNode ==}, !=, {@link SLLessThanNode &lt;},
+ * {@link SLLessOrEqualNode &le;}, &gt;, &ge;.
+ * <li>Local variables: local variables must be defined (via a {@link SLWriteLocalVariableNode
+ * write}) before they can be used (by a {@link SLReadLocalVariableNode read}). Local variables are
+ * not visible outside of the block where they were first defined.
+ * <li>Basic control flow statements: {@link SLBlockNode blocks}, {@link SLIfNode if},
+ * {@link SLWhileNode while} with {@link SLBreakNode break} and {@link SLContinueNode continue},
+ * {@link SLReturnNode return}.
+ * <li>Function calls: {@link SLInvokeNode invocations} are efficiently implemented with
+ * {@link SLDispatchNode polymorphic inline caches}.
+ * </ul>
+ *
+ * <p>
+ * <b>Syntax and parsing:</b><br>
+ * The syntax is described as an attributed grammar. The {@link Parser} and {@link Scanner} are
+ * automatically generated by the parser generator Coco/R (available from <a
+ * href="http://ssw.jku.at/coco/">http://ssw.jku.at/coco/</a>). The grammar contains semantic
+ * actions that build the AST for a method. To keep these semantic actions short, they are mostly
+ * calls to the {@link SLNodeFactory} that performs the actual node creation. All functions found in
+ * the SL source are added to the {@link SLFunctionRegistry}, which is accessible from the
+ * {@link SLContext}.
+ *
+ * <p>
+ * <b>Builtin functions:</b><br>
+ * Library functions that are available to every SL source without prior definition are called
+ * builtin functions. They are added to the {@link SLFunctionRegistry} when the {@link SLContext} is
+ * created. There current builtin functions are
+ * <ul>
+ * <li>{@link SLReadlnBuiltin readln}: Read a String from the {@link SLContext#getInput() standard
+ * input}.
+ * <li>{@link SLPrintlnBuiltin println}: Write a value to the {@link SLContext#getOutput() standard
+ * output}.
+ * <li>{@link SLNanoTimeBuiltin nanoTime}: Returns the value of a high-resolution time, in
+ * nanoseconds.
+ * <li>{@link SLDefineFunctionBuiltin defineFunction}: Parses the functions provided as a String
+ * argument and adds them to the function registry. Functions that are already defined are replaced
+ * with the new version.
+ * </ul>
+ *
+ * <p>
+ * <b>Tools:</b><br>
+ * The use of some of Truffle's support for developer tools (based on the Truffle Instrumentation
+ * Framework) are demonstrated in this file, for example:
+ * <ul>
+ * <li>a {@linkplain NodeExecCounter counter for node executions}, tabulated by node type; and</li>
+ * <li>a simple {@linkplain CoverageTracker code coverage engine}.</li>
+ * </ul>
+ * In each case, the tool is enabled if a corresponding local boolean variable in this file is set
+ * to {@code true}. Results are printed at the end of the execution using each tool's
+ * <em>default printer</em>.
+ *
+ */
+@TruffleLanguage.Registration(name = "SL", version = "0.5", mimeType = "application/x-sl")
+public class SLLanguage extends TruffleLanguage {
+    private static SLLanguage LAST;
+    private static List<NodeFactory<? extends SLBuiltinNode>> builtins = Collections.emptyList();
+    private static Visualizer visualizer = new SLDefaultVisualizer();
+    private static ASTProber registeredASTProber; // non-null if prober already registered
+    private final SLContext context;
+    private DebugSupportProvider debugSupport;
+
+    public SLLanguage(Env env) {
+        super(env);
+        context = SLContextFactory.create(new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true));
+        LAST = this;
+        for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) {
+            context.installBuiltin(builtin);
+        }
+    }
+
+    // TODO (mlvdv) command line options
+    /* Enables demonstration of per-type tabulation of node execution counts */
+    private static boolean nodeExecCounts = false;
+    /* Enables demonstration of per-line tabulation of STATEMENT node execution counts */
+    private static boolean statementCounts = false;
+    /* Enables demonstration of per-line tabulation of STATEMENT coverage */
+    private static boolean coverage = false;
+
+    /* Small tools that can be installed for demonstration */
+    private static NodeExecCounter nodeExecCounter = null;
+    private static NodeExecCounter statementExecCounter = null;
+    private static CoverageTracker coverageTracker = null;
+
+    /**
+     * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup.
+     */
+    public static void main(String[] args) throws IOException {
+        TruffleVM vm = TruffleVM.newVM().build();
+        assert vm.getLanguages().containsKey("application/x-sl");
+
+        setupToolDemos();
+
+        int repeats = 1;
+        if (args.length >= 2) {
+            repeats = Integer.parseInt(args[1]);
+        }
+
+        if (args.length == 0) {
+            vm.eval("application/x-sl", new InputStreamReader(System.in));
+        } else {
+            vm.eval(new File(args[0]).toURI());
+        }
+        Symbol main = vm.findGlobalSymbol("main");
+        if (main == null) {
+            throw new SLException("No function main() defined in SL source file.");
+        }
+        while (repeats-- > 0) {
+            main.invoke(null);
+        }
+        reportToolDemos();
+    }
+
+    /**
+     * Temporary method during API evolution, supports debugger integration.
+     */
+    public static void run(Source source) throws IOException {
+        TruffleVM vm = TruffleVM.newVM().build();
+        assert vm.getLanguages().containsKey("application/x-sl");
+        vm.eval(new File(source.getPath()).toURI());
+        Symbol main = vm.findGlobalSymbol("main");
+        if (main == null) {
+            throw new SLException("No function main() defined in SL source file.");
+        }
+        main.invoke(null);
+    }
+
+    /**
+     * Parse and run the specified SL source. Factored out in a separate method so that it can also
+     * be used by the unit test harness.
+     */
+    public static long run(TruffleVM context, URI source, PrintWriter logOutput, PrintWriter out, int repeats, List<NodeFactory<? extends SLBuiltinNode>> currentBuiltins) throws IOException {
+        builtins = currentBuiltins;
+
+        if (logOutput != null) {
+            logOutput.println("== running on " + Truffle.getRuntime().getName());
+            // logOutput.println("Source = " + source.getCode());
+        }
+
+        /* Parse the SL source file. */
+        Object result = context.eval(source);
+        if (result != null) {
+            out.println(result);
+        }
+
+        /* Lookup our main entry point, which is per definition always named "main". */
+        Symbol main = context.findGlobalSymbol("main");
+        if (main == null) {
+            throw new SLException("No function main() defined in SL source file.");
+        }
+
+        /* Change to true if you want to see the AST on the console. */
+        boolean printASTToLog = false;
+        /* Change to true if you want to see source attribution for the AST to the console */
+        boolean printSourceAttributionToLog = false;
+        /* Change to dump the AST to IGV over the network. */
+        boolean dumpASTToIGV = false;
+
+        printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
+        long totalRuntime = 0;
+        try {
+            for (int i = 0; i < repeats; i++) {
+                long start = System.nanoTime();
+                /* Call the main entry point, without any arguments. */
+                try {
+                    result = main.invoke(null);
+                    if (result != null) {
+                        out.println(result);
+                    }
+                } catch (UnsupportedSpecializationException ex) {
+                    out.println(formatTypeError(ex));
+                } catch (SLUndefinedFunctionException ex) {
+                    out.println(String.format("Undefined function: %s", ex.getFunctionName()));
+                }
+                long end = System.nanoTime();
+                totalRuntime += end - start;
+
+                if (logOutput != null && repeats > 1) {
+                    logOutput.println("== iteration " + (i + 1) + ": " + ((end - start) / 1000000) + " ms");
+                }
+            }
+
+        } finally {
+            printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV);
+        }
+        return totalRuntime;
+    }
+
+    /**
+     * When dumpASTToIGV is true: dumps the AST of all functions to the IGV visualizer, via a socket
+     * connection. IGV can be started with the mx command "mx igv".
+     * <p>
+     * When printASTToLog is true: prints the ASTs to the console.
+     */
+    private static void printScript(String groupName, SLContext context, PrintWriter logOutput, boolean printASTToLog, boolean printSourceAttributionToLog, boolean dumpASTToIGV) {
+        if (dumpASTToIGV) {
+            GraphPrintVisitor graphPrinter = new GraphPrintVisitor();
+            graphPrinter.beginGroup(groupName);
+            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
+                RootCallTarget callTarget = function.getCallTarget();
+                if (callTarget != null) {
+                    graphPrinter.beginGraph(function.toString()).visit(callTarget.getRootNode());
+                }
+            }
+            graphPrinter.printToNetwork(true);
+        }
+        if (printASTToLog && logOutput != null) {
+            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
+                RootCallTarget callTarget = function.getCallTarget();
+                if (callTarget != null) {
+                    logOutput.println("=== " + function);
+                    NodeUtil.printTree(logOutput, callTarget.getRootNode());
+                }
+            }
+        }
+        if (printSourceAttributionToLog && logOutput != null) {
+            for (SLFunction function : context.getFunctionRegistry().getFunctions()) {
+                RootCallTarget callTarget = function.getCallTarget();
+                if (callTarget != null) {
+                    logOutput.println("=== " + function);
+                    NodeUtil.printSourceAttributionTree(logOutput, callTarget.getRootNode());
+                }
+            }
+        }
+    }
+
+    /**
+     * Provides a user-readable message for run-time type errors. SL is strongly typed, i.e., there
+     * are no automatic type conversions of values. Therefore, Truffle does the type checking for
+     * us: if no matching node specialization for the actual values is found, then we have a type
+     * error. Specialized nodes use the {@link UnsupportedSpecializationException} to report that no
+     * specialization was found. We therefore just have to convert the information encapsulated in
+     * this exception in a user-readable form.
+     */
+    private static String formatTypeError(UnsupportedSpecializationException ex) {
+        StringBuilder result = new StringBuilder();
+        result.append("Type error");
+        if (ex.getNode() != null && ex.getNode().getSourceSection() != null) {
+            SourceSection ss = ex.getNode().getSourceSection();
+            if (ss != null && !(ss instanceof NullSourceSection)) {
+                result.append(" at ").append(ss.getSource().getShortName()).append(" line ").append(ss.getStartLine()).append(" col ").append(ss.getStartColumn());
+            }
+        }
+        result.append(": operation");
+        if (ex.getNode() != null) {
+            NodeInfo nodeInfo = SLContext.lookupNodeInfo(ex.getNode().getClass());
+            if (nodeInfo != null) {
+                result.append(" \"").append(nodeInfo.shortName()).append("\"");
+            }
+        }
+        result.append(" not defined for");
+
+        String sep = " ";
+        for (int i = 0; i < ex.getSuppliedValues().length; i++) {
+            Object value = ex.getSuppliedValues()[i];
+            Node node = ex.getSuppliedNodes()[i];
+            if (node != null) {
+                result.append(sep);
+                sep = ", ";
+
+                if (value instanceof Long || value instanceof BigInteger) {
+                    result.append("Number ").append(value);
+                } else if (value instanceof Boolean) {
+                    result.append("Boolean ").append(value);
+                } else if (value instanceof String) {
+                    result.append("String \"").append(value).append("\"");
+                } else if (value instanceof SLFunction) {
+                    result.append("Function ").append(value);
+                } else if (value == SLNull.SINGLETON) {
+                    result.append("NULL");
+                } else if (value == null) {
+                    // value is not evaluated because of short circuit evaluation
+                    result.append("ANY");
+                } else {
+                    result.append(value);
+                }
+            }
+        }
+        return result.toString();
+    }
+
+    @Override
+    protected Object eval(Source code) throws IOException {
+        try {
+            context.evalSource(code);
+        } catch (Exception e) {
+            throw new IOException(e);
+        }
+        return null;
+    }
+
+    @Override
+    protected Object findExportedSymbol(String globalName, boolean onlyExplicit) {
+        for (SLFunction f : context.getFunctionRegistry().getFunctions()) {
+            if (globalName.equals(f.getName())) {
+                return f;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    protected Object getLanguageGlobal() {
+        return context;
+    }
+
+    @Override
+    protected boolean isObjectOfLanguage(Object object) {
+        return object instanceof SLFunction;
+    }
+
+    @Override
+    protected ToolSupportProvider getToolSupport() {
+        return getDebugSupport();
+    }
+
+    @Override
+    protected DebugSupportProvider getDebugSupport() {
+        if (debugSupport == null) {
+            debugSupport = new SLDebugProvider();
+        }
+        return debugSupport;
+    }
+
+    // TODO (mlvdv) remove the static hack when we no longer have the static demo variables
+    private static void setupToolDemos() {
+        if (statementCounts || coverage) {
+            if (registeredASTProber == null) {
+                final ASTProber newProber = new SLStandardASTProber();
+                // This should be registered on the TruffleVM
+                Probe.registerASTProber(newProber);
+                registeredASTProber = newProber;
+            }
+        }
+        if (nodeExecCounts) {
+            nodeExecCounter = new NodeExecCounter();
+            nodeExecCounter.install();
+        }
+
+        if (statementCounts) {
+            statementExecCounter = new NodeExecCounter(StandardSyntaxTag.STATEMENT);
+            statementExecCounter.install();
+        }
+
+        if (coverage) {
+            coverageTracker = new CoverageTracker();
+            coverageTracker.install();
+        }
+    }
+
+    private static void reportToolDemos() {
+        if (nodeExecCounter != null) {
+            nodeExecCounter.print(System.out);
+            nodeExecCounter.dispose();
+        }
+        if (statementExecCounter != null) {
+            statementExecCounter.print(System.out);
+            statementExecCounter.dispose();
+        }
+        if (coverageTracker != null) {
+            coverageTracker.print(System.out);
+            coverageTracker.dispose();
+        }
+    }
+
+    private final class SLDebugProvider implements DebugSupportProvider {
+
+        public SLDebugProvider() {
+            if (registeredASTProber == null) {
+                registeredASTProber = new SLStandardASTProber();
+                // This should be registered on the TruffleVM
+                Probe.registerASTProber(registeredASTProber);
+            }
+        }
+
+        public Visualizer getVisualizer() {
+            if (visualizer == null) {
+                visualizer = new SLDefaultVisualizer();
+            }
+            return visualizer;
+        }
+
+        public void enableASTProbing(ASTProber prober) {
+            if (prober != null) {
+                // This should be registered on the TruffleVM
+                Probe.registerASTProber(prober);
+            }
+        }
+
+        public void run(Source source) throws DebugSupportException {
+            // TODO (mlvdv) fix to run properly in the current VM
+            try {
+                SLLanguage.run(source);
+            } catch (Exception e) {
+                throw new DebugSupportException(e);
+            }
+        }
+
+        public Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugSupportException {
+            throw new DebugSupportException("evalInContext not supported in this language");
+        }
+
+        public AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugSupportException {
+            throw new DebugSupportException("createAdvancedInstrumentRootFactory not supported in this language");
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertFalseBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Asserts a given value to be <code>false</code> and throws an {@link AssertionError} if the value
+ * was <code>true</code>.
+ */
+@NodeInfo(shortName = "assertFalse")
+public abstract class SLAssertFalseBuiltin extends SLBuiltinNode {
+
+    public SLAssertFalseBuiltin() {
+        super(new NullSourceSection("SL builtin", "assertFalse"));
+    }
+
+    @Specialization
+    public boolean doAssert(boolean value, String message) {
+        if (value) {
+            CompilerDirectives.transferToInterpreter();
+            throw new SLAssertionError(message == null ? "" : message);
+        }
+        return value;
+    }
+
+    @Specialization
+    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
+        return doAssert(value, null);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLAssertTrueBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Asserts a given value to be <code>true</code> and throws an {@link AssertionError} if the value
+ * was <code>false</code>.
+ */
+@NodeInfo(shortName = "assertTrue")
+public abstract class SLAssertTrueBuiltin extends SLBuiltinNode {
+
+    public SLAssertTrueBuiltin() {
+        super(new NullSourceSection("SL builtin", "assertTrue"));
+    }
+
+    @Specialization
+    public boolean doAssert(boolean value, String message) {
+        if (!value) {
+            CompilerDirectives.transferToInterpreter();
+            throw new SLAssertionError(message == null ? "" : message);
+        }
+        return value;
+    }
+
+    @Specialization
+    public boolean doAssertNull(boolean value, @SuppressWarnings("unused") SLNull message) {
+        return doAssert(value, null);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Base class for all builtin functions. It contains the Truffle DSL annotation {@link NodeChild}
+ * that defines the function arguments.<br>
+ * Builtin functions need access to the {@link SLContext}. Instead of defining a Java field manually
+ * and setting it in a constructor, we use the Truffle DSL annotation {@link NodeField} that
+ * generates the field and constructor automatically.
+ * <p>
+ * The builtin functions are registered in {@link SLContext#installBuiltins}. Every builtin node
+ * subclass is instantiated there, wrapped into a function, and added to the
+ * {@link SLFunctionRegistry}. This ensures that builtin functions can be called like user-defined
+ * functions; there is no special function lookup or call node for builtin functions.
+ */
+@NodeChild(value = "arguments", type = SLExpressionNode[].class)
+@NodeField(name = "context", type = SLContext.class)
+@GenerateNodeFactory
+public abstract class SLBuiltinNode extends SLExpressionNode {
+
+    public SLBuiltinNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * Accessor for the {@link SLContext}. The implementation of this method is generated
+     * automatically based on the {@link NodeField} annotation on the class.
+     */
+    public abstract SLContext getContext();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Builtin function to define (or redefine) functions. The provided source code is parsed the same
+ * way as the initial source of the script, so the same syntax applies.
+ */
+@NodeInfo(shortName = "defineFunction")
+public abstract class SLDefineFunctionBuiltin extends SLBuiltinNode {
+
+    public SLDefineFunctionBuiltin() {
+        super(new NullSourceSection("SL builtin", "defineFunction"));
+    }
+
+    @Specialization
+    public String defineFunction(String code) {
+        doDefineFunction(getContext(), code);
+        return code;
+    }
+
+    @TruffleBoundary
+    private static void doDefineFunction(SLContext context, String code) {
+        Source source = Source.fromText(code, "[defineFunction]");
+        /* The same parsing code as for parsing the initial source. */
+        Parser.parseSL(context, source);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLHelloEqualsWorldBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * This builtin sets the variable named "hello" in the caller frame to the string "world".
+ */
+@NodeInfo(shortName = "helloEqualsWorld")
+public abstract class SLHelloEqualsWorldBuiltin extends SLBuiltinNode {
+
+    public SLHelloEqualsWorldBuiltin() {
+        super(new NullSourceSection("SL builtin", "helloEqualsWorld"));
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public String change() {
+        FrameInstance frameInstance = Truffle.getRuntime().getCallerFrame();
+        Frame frame = frameInstance.getFrame(FrameAccess.READ_WRITE, false);
+        FrameSlot slot = frame.getFrameDescriptor().findOrAddFrameSlot("hello");
+        frame.setObject(slot, "world");
+        return "world";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNanoTimeBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Builtin function that returns the value of a high-resolution time, in nanoseconds.
+ */
+@NodeInfo(shortName = "nanoTime")
+public abstract class SLNanoTimeBuiltin extends SLBuiltinNode {
+
+    public SLNanoTimeBuiltin() {
+        super(new NullSourceSection("SL builtin", "nanoTime"));
+    }
+
+    @Specialization
+    public long nanoTime() {
+        return System.nanoTime();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Built-in function to create a new object. Objects in SL are simply made up of name/value pairs.
+ */
+@NodeInfo(shortName = "new")
+public abstract class SLNewObjectBuiltin extends SLBuiltinNode {
+
+    public SLNewObjectBuiltin() {
+        super(new NullSourceSection("SL builtin", "new"));
+    }
+
+    @Specialization
+    public Object newObject() {
+        return getContext().createObject();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLPrintlnBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import java.io.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Builtin function to write a value to the {@link SLContext#getOutput() standard output}. The
+ * different specialization leverage the typed {@code println} methods available in Java, i.e.,
+ * primitive values are printed without converting them to a {@link String} first.
+ * <p>
+ * Printing involves a lot of Java code, so we need to tell the optimizing system that it should not
+ * unconditionally inline everything reachable from the println() method. This is done via the
+ * {@link TruffleBoundary} annotations.
+ */
+@NodeInfo(shortName = "println")
+public abstract class SLPrintlnBuiltin extends SLBuiltinNode {
+
+    public SLPrintlnBuiltin() {
+        super(new NullSourceSection("SL builtin", "println"));
+    }
+
+    @Specialization
+    public long println(long value) {
+        doPrint(getContext().getOutput(), value);
+        return value;
+    }
+
+    @TruffleBoundary
+    private static void doPrint(PrintWriter out, long value) {
+        out.println(value);
+    }
+
+    @Specialization
+    public boolean println(boolean value) {
+        doPrint(getContext().getOutput(), value);
+        return value;
+    }
+
+    @TruffleBoundary
+    private static void doPrint(PrintWriter out, boolean value) {
+        out.println(value);
+    }
+
+    @Specialization
+    public String println(String value) {
+        doPrint(getContext().getOutput(), value);
+        return value;
+    }
+
+    @TruffleBoundary
+    private static void doPrint(PrintWriter out, String value) {
+        out.println(value);
+    }
+
+    @Specialization
+    public Object println(Object value) {
+        doPrint(getContext().getOutput(), value);
+        return value;
+    }
+
+    @TruffleBoundary
+    private static void doPrint(PrintWriter out, Object value) {
+        out.println(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLReadlnBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import java.io.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Builtin function that reads a String from the {@link SLContext#getInput() standard input}.
+ */
+@NodeInfo(shortName = "readln")
+public abstract class SLReadlnBuiltin extends SLBuiltinNode {
+
+    public SLReadlnBuiltin() {
+        super(new NullSourceSection("SL builtin", "readln"));
+    }
+
+    @Specialization
+    public String readln() {
+        String result = doRead(getContext().getInput());
+        if (result == null) {
+            /*
+             * We do not have a sophisticated end of file handling, so returning an empty string is
+             * a reasonable alternative. Note that the Java null value should never be used, since
+             * it can interfere with the specialization logic in generated source code.
+             */
+            result = "";
+        }
+        return result;
+    }
+
+    @TruffleBoundary
+    private static String doRead(BufferedReader in) {
+        try {
+            return in.readLine();
+        } catch (IOException ex) {
+            throw new SLException(ex.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLStackTraceBuiltin.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Returns a string representation of the current stack. This includes the {@link CallTarget}s and
+ * the contents of the {@link Frame}. Note that this is implemented as a slow path by passing
+ * {@code true} to {@link FrameInstance#getFrame(FrameAccess, boolean)}.
+ */
+@NodeInfo(shortName = "stacktrace")
+public abstract class SLStackTraceBuiltin extends SLBuiltinNode {
+
+    public SLStackTraceBuiltin() {
+        super(new NullSourceSection("SL builtin", "stacktrace"));
+    }
+
+    @Specialization
+    public String trace() {
+        return createStackTrace();
+    }
+
+    @TruffleBoundary
+    private static String createStackTrace() {
+        final StringBuilder str = new StringBuilder();
+
+        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Integer>() {
+            @Override
+            public Integer visitFrame(FrameInstance frameInstance) {
+                CallTarget callTarget = frameInstance.getCallTarget();
+                Frame frame = frameInstance.getFrame(FrameAccess.READ_ONLY, true);
+                RootNode rn = ((RootCallTarget) callTarget).getRootNode();
+                if (rn.getClass().getName().contains("SLFunctionForeignAccess")) {
+                    return 1;
+                }
+                if (str.length() > 0) {
+                    str.append(System.getProperty("line.separator"));
+                }
+                str.append("Frame: ").append(rn.toString());
+                FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
+                for (FrameSlot s : frameDescriptor.getSlots()) {
+                    str.append(", ").append(s.getIdentifier()).append("=").append(frame.getValue(s));
+                }
+                return null;
+            }
+        });
+        return str.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.factory;
+
+import java.io.*;
+
+import com.oracle.truffle.sl.runtime.*;
+
+public final class SLContextFactory {
+
+    private SLContextFactory() {
+    }
+
+    public static SLContext create(BufferedReader input, PrintWriter output) {
+        return new SLContext(input, output);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Utility base class for operations that take two arguments (per convention called "left" and
+ * "right"). For concrete subclasses of this class, the Truffle DSL creates two child fields, and
+ * the necessary constructors and logic to set them.
+ */
+@NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")})
+public abstract class SLBinaryNode extends SLExpressionNode {
+
+    public SLBinaryNode(SourceSection src) {
+        super(src);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Base class for all SL nodes that produce a value and therefore benefit from type specialization.
+ * The annotation {@link TypeSystemReference} specifies the SL types. Specifying it here defines the
+ * type system for all subclasses.
+ */
+@TypeSystemReference(SLTypes.class)
+@NodeInfo(description = "The abstract base node for all expressions")
+public abstract class SLExpressionNode extends SLStatementNode {
+
+    public SLExpressionNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * The execute method when no specialization is possible. This is the most general case,
+     * therefore it must be provided by all subclasses.
+     */
+    public abstract Object executeGeneric(VirtualFrame frame);
+
+    /**
+     * When we use an expression at places where a {@link SLStatementNode statement} is already
+     * sufficient, the return value is just discarded.
+     */
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        executeGeneric(frame);
+    }
+
+    /*
+     * Execute methods for specialized types. They all follow the same pattern: they call the
+     * generic execution method and then expect a result of their return type. Type-specialized
+     * subclasses overwrite the appropriate methods.
+     */
+
+    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.expectLong(executeGeneric(frame));
+    }
+
+    public SLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.expectSLFunction(executeGeneric(frame));
+    }
+
+    public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.expectBoolean(executeGeneric(frame));
+    }
+
+    @Override
+    public boolean isInstrumentable() {
+        return true;
+    }
+
+    @Override
+    public WrapperNode createWrapperNode() {
+        return new SLExpressionWrapperNode(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.builtins.*;
+import com.oracle.truffle.sl.nodes.controlflow.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The root of all SL execution trees. It is a Truffle requirement that the tree root extends the
+ * class {@link RootNode}. This class is used for both builtin and user-defined functions. For
+ * builtin functions, the {@link #bodyNode} is a subclass of {@link SLBuiltinNode}. For user-defined
+ * functions, the {@link #bodyNode} is a {@link SLFunctionBodyNode}.
+ */
+@NodeInfo(language = "Simple Language", description = "The root of all Simple Language execution trees")
+public final class SLRootNode extends RootNode {
+
+    /** The function body that is executed, and specialized during execution. */
+    @Child private SLExpressionNode bodyNode;
+
+    /** The name of the function, for printing purposes only. */
+    private final String name;
+
+    /** The Simple execution context for this tree. **/
+    private final SLContext context;
+
+    @CompilationFinal private boolean isCloningAllowed;
+
+    public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) {
+        super(null, frameDescriptor);
+        this.bodyNode = bodyNode;
+        this.name = name;
+        this.context = context;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return bodyNode.executeGeneric(frame);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setCloningAllowed(boolean isCloningAllowed) {
+        this.isCloningAllowed = isCloningAllowed;
+    }
+
+    public SLExpressionNode getBodyNode() {
+        return bodyNode;
+    }
+
+    @Override
+    public boolean isCloningAllowed() {
+        return isCloningAllowed;
+    }
+
+    @Override
+    public void applyInstrumentation() {
+        Probe.applyASTProbers(bodyNode);
+    }
+
+    @Override
+    public String toString() {
+        return "root " + name;
+    }
+
+    public SLContext getSLContext() {
+        return this.context;
+    }
+
+    @Override
+    public ExecutionContext getExecutionContext() {
+        return this.context;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import java.io.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.instrument.*;
+
+/**
+ * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
+ * statements, i.e., without returning a value. The {@link VirtualFrame} provides access to the
+ * local variables.
+ */
+@NodeInfo(language = "Simple Language", description = "The abstract base node for all statements")
+public abstract class SLStatementNode extends Node {
+
+    public SLStatementNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * Execute this node as as statement, where no return value is necessary.
+     */
+    public abstract void executeVoid(VirtualFrame frame);
+
+    public SLStatementNode getNonWrapperNode() {
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        return formatSourceSection(this);
+    }
+
+    /**
+     * Formats a source section of a node in human readable form. If no source section could be
+     * found it looks up the parent hierarchy until it finds a source section. Nodes where this was
+     * required append a <code>'~'</code> at the end.
+     *
+     * @param node the node to format.
+     * @return a formatted source section string
+     */
+    public static String formatSourceSection(Node node) {
+        if (node == null) {
+            return "<unknown>";
+        }
+        SourceSection section = node.getSourceSection();
+        boolean estimated = false;
+        if (section == null) {
+            section = node.getEncapsulatingSourceSection();
+            estimated = true;
+        }
+
+        if (section == null || section.getSource() == null) {
+            return "<unknown source>";
+        } else {
+            String sourceName = new File(section.getSource().getName()).getName();
+            int startLine = section.getStartLine();
+            return String.format("%s:%d%s", sourceName, startLine, estimated ? "~" : "");
+        }
+    }
+
+    @Override
+    public boolean isInstrumentable() {
+        return true;
+    }
+
+    @Override
+    public WrapperNode createWrapperNode() {
+        return new SLStatementWrapperNode(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLTypes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.internal.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The type system of SL, as explained in {@link SLLanguage}. Based on the {@link TypeSystem}
+ * annotation, the Truffle DSL generates the subclass {@link SLTypesGen} with type test and type
+ * conversion methods for all types. In this class, we only cover types where the automatically
+ * generated ones would not be sufficient.
+ */
+@TypeSystem({long.class, BigInteger.class, boolean.class, String.class, SLFunction.class, SLNull.class})
+@DSLOptions(useNewLayout = true)
+public abstract class SLTypes {
+
+    /**
+     * Example of a manually specified type check that replaces the automatically generated type
+     * check that the Truffle DSL would generate. For {@link SLNull}, we do not need an
+     * {@code instanceof} check, because we know that there is only a {@link SLNull#SINGLETON
+     * singleton} instance.
+     */
+    @TypeCheck(SLNull.class)
+    public static boolean isSLNull(Object value) {
+        return value == SLNull.SINGLETON;
+    }
+
+    /**
+     * Example of a manually specified type cast that replaces the automatically generated type cast
+     * that the Truffle DSL would generate. For {@link SLNull}, we do not need an actual cast,
+     * because we know that there is only a {@link SLNull#SINGLETON singleton} instance.
+     */
+    @TypeCast(SLNull.class)
+    public static SLNull asSLNull(Object value) {
+        assert isSLNull(value);
+        return SLNull.SINGLETON;
+    }
+
+    /**
+     * Informs the Truffle DSL that a primitive {@code long} value can be used in all
+     * specializations where a {@link BigInteger} is expected. This models the semantic of SL: It
+     * only has an arbitrary precision Number type (implemented as {@link BigInteger}, and
+     * {@code long} is only used as a performance optimization to avoid the costly
+     * {@link BigInteger} arithmetic for values that fit into a 64-bit primitive value.
+     */
+    @ImplicitCast
+    public static BigInteger castBigInteger(long value) {
+        return BigInteger.valueOf(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyCacheNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.access;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public abstract class SLReadPropertyCacheNode extends Node {
+
+    protected static final int CACHE_LIMIT = 3;
+
+    protected final String propertyName;
+
+    public SLReadPropertyCacheNode(String propertyName) {
+        this.propertyName = propertyName;
+    }
+
+    public static SLReadPropertyCacheNode create(String propertyName) {
+        return SLReadPropertyCacheNodeGen.create(propertyName);
+    }
+
+    public abstract Object executeObject(DynamicObject receiver);
+
+    public abstract long executeLong(DynamicObject receiver) throws UnexpectedResultException;
+
+    /*
+     * We use a separate long specialization to avoid boxing for long.
+     */
+    @Specialization(limit = "CACHE_LIMIT", guards = {"longLocation != null", "shape.check(receiver)"}, assumptions = "shape.getValidAssumption()")
+    @SuppressWarnings("unused")
+    protected long doCachedLong(DynamicObject receiver, //
+                    @Cached("receiver.getShape()") Shape shape, //
+                    @Cached("getLongLocation(shape)") LongLocation longLocation) {
+        return longLocation.getLong(receiver, true);
+    }
+
+    protected LongLocation getLongLocation(Shape shape) {
+        Property property = shape.getProperty(propertyName);
+        if (property != null && property.getLocation() instanceof LongLocation) {
+            return (LongLocation) property.getLocation();
+        }
+        return null;
+    }
+
+    /*
+     * As soon as we have seen an object read, we cannot avoid boxing long anymore therefore we can
+     * contain all long cache entries.
+     */
+    @Specialization(limit = "CACHE_LIMIT", contains = "doCachedLong", guards = "shape.check(receiver)", assumptions = "shape.getValidAssumption()")
+    protected static Object doCachedObject(DynamicObject receiver, //
+                    @Cached("receiver.getShape()") Shape shape, //
+                    @Cached("shape.getProperty(propertyName)") Property property) {
+        if (property == null) {
+            return SLNull.SINGLETON;
+        } else {
+            return property.get(receiver, shape);
+        }
+    }
+
+    /*
+     * The generic case is used if the number of shapes accessed overflows the limit.
+     */
+    @Specialization(contains = "doCachedObject")
+    @TruffleBoundary
+    protected Object doGeneric(DynamicObject receiver, @Cached("new()") LRUPropertyLookup lruCache) {
+        if (!lruCache.shape.check(receiver)) {
+            Shape receiverShape = receiver.getShape();
+            lruCache.shape = receiverShape;
+            lruCache.property = receiverShape.getProperty(propertyName);
+        }
+        if (lruCache.property != null) {
+            return lruCache.property.get(receiver, true);
+        } else {
+            return SLNull.SINGLETON;
+        }
+    }
+
+    protected static class LRUPropertyLookup {
+
+        private Shape shape;
+        private Property property;
+
+        public LRUPropertyLookup() {
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.access;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The node for accessing a property of an object. When executed, this node first evaluates the
+ * object expression on the left side of the dot operator and then reads the named property.
+ */
+@NodeInfo(shortName = ".")
+public final class SLReadPropertyNode extends SLExpressionNode {
+
+    public static SLReadPropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
+        return new SLReadPropertyNode(src, receiverNode, propertyName);
+    }
+
+    @Child private SLExpressionNode receiverNode;
+    @Child private SLReadPropertyCacheNode cacheNode;
+    private final ConditionProfile receiverTypeCondition = ConditionProfile.createBinaryProfile();
+
+    private SLReadPropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
+        super(src);
+        this.receiverNode = receiverNode;
+        this.cacheNode = SLReadPropertyCacheNodeGen.create(propertyName);
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object object = receiverNode.executeGeneric(frame);
+        if (receiverTypeCondition.profile(SLContext.isSLObject(object))) {
+            return cacheNode.executeObject(SLContext.castSLObject(object));
+        } else {
+            throw new SLException("unexpected receiver type");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyCacheNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.access;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.object.*;
+
+public abstract class SLWritePropertyCacheNode extends Node {
+
+    protected final String propertyName;
+
+    public SLWritePropertyCacheNode(String propertyName) {
+        this.propertyName = propertyName;
+    }
+
+    public abstract void executeObject(DynamicObject receiver, Object value);
+
+    @Specialization(guards = "location.isValid(receiver, value)", assumptions = "location.getAssumptions()")
+    public void writeCached(DynamicObject receiver, Object value, //
+                    @Cached("createCachedWrite(receiver, value)") CachedWriteLocation location) {
+        if (location.writeUnchecked(receiver, value)) {
+            // write successful
+        } else {
+            executeObject(receiver, value);
+        }
+    }
+
+    @Specialization(contains = "writeCached")
+    @TruffleBoundary
+    public void writeGeneric(DynamicObject receiver, Object value, //
+                    @Cached("new(createCachedWrite(receiver, value))") LRUCachedWriteLocation lru) {
+        CachedWriteLocation location = lru.location;
+        if (!location.isValid(receiver, value) || !location.areAssumptionsValid()) {
+            location = createCachedWrite(receiver, value);
+            lru.location = location;
+        }
+        if (location.writeUnchecked(receiver, value)) {
+            // write successful
+        } else {
+            executeObject(receiver, value);
+        }
+    }
+
+    protected CachedWriteLocation createCachedWrite(DynamicObject receiver, Object value) {
+        while (receiver.updateShape()) {
+            // multiple shape updates might be needed.
+        }
+
+        Shape oldShape = receiver.getShape();
+        Shape newShape;
+        Property property = oldShape.getProperty(propertyName);
+
+        if (property != null && property.getLocation().canSet(receiver, value)) {
+            newShape = oldShape;
+        } else {
+            receiver.define(propertyName, value, 0);
+            newShape = receiver.getShape();
+            property = newShape.getProperty(propertyName);
+        }
+
+        if (!oldShape.check(receiver)) {
+            return createCachedWrite(receiver, value);
+        }
+
+        return new CachedWriteLocation(oldShape, newShape, property.getLocation());
+
+    }
+
+    protected static final class CachedWriteLocation {
+
+        private final Shape oldShape;
+        private final Shape newShape;
+        private final Location location;
+        private final Assumption validLocation = Truffle.getRuntime().createAssumption();
+
+        public CachedWriteLocation(Shape oldShape, Shape newShape, Location location) {
+            this.oldShape = oldShape;
+            this.newShape = newShape;
+            this.location = location;
+        }
+
+        public boolean areAssumptionsValid() {
+            return validLocation.isValid() && oldShape.getValidAssumption().isValid() && newShape.getValidAssumption().isValid();
+        }
+
+        public Assumption[] getAssumptions() {
+            return new Assumption[]{oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation};
+        }
+
+        public boolean isValid(DynamicObject receiver, Object value) {
+            return oldShape.check(receiver) && location.canSet(receiver, value);
+        }
+
+        public boolean writeUnchecked(DynamicObject receiver, Object value) {
+            try {
+                if (oldShape == newShape) {
+                    location.set(receiver, value, oldShape);
+                } else {
+                    location.set(receiver, value, oldShape, newShape);
+                }
+                return true;
+            } catch (IncompatibleLocationException | FinalLocationException e) {
+                validLocation.invalidate();
+                return false;
+            }
+        }
+    }
+
+    protected static final class LRUCachedWriteLocation {
+
+        private CachedWriteLocation location;
+
+        public LRUCachedWriteLocation(CachedWriteLocation location) {
+            this.location = location;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.access;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The node for setting a property of an object. When executed, this node first evaluates the value
+ * expression on the right hand side of the equals operator, followed by the object expression on
+ * the left side of the dot operator, and then sets the named property of this object to the new
+ * value if the property already exists or adds a new property. Finally, it returns the new value.
+ */
+@NodeInfo(shortName = ".=")
+public final class SLWritePropertyNode extends SLExpressionNode {
+
+    public static SLWritePropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
+        return new SLWritePropertyNode(src, receiverNode, propertyName, valueNode);
+    }
+
+    @Child protected SLExpressionNode receiverNode;
+    protected final String propertyName;
+    @Child protected SLExpressionNode valueNode;
+    @Child protected SLWritePropertyCacheNode cacheNode;
+    private final ConditionProfile receiverTypeCondition = ConditionProfile.createBinaryProfile();
+
+    private SLWritePropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
+        super(src);
+        this.receiverNode = receiverNode;
+        this.propertyName = propertyName;
+        this.valueNode = valueNode;
+        this.cacheNode = SLWritePropertyCacheNodeGen.create(propertyName);
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object value = valueNode.executeGeneric(frame);
+        Object object = receiverNode.executeGeneric(frame);
+        if (receiverTypeCondition.profile(SLContext.isSLObject(object))) {
+            cacheNode.executeObject(SLContext.castSLObject(object), value);
+        } else {
+            throw new SLException("unexpected receiver type");
+        }
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDispatchNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.call;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public abstract class SLDispatchNode extends Node {
+
+    protected static final int INLINE_CACHE_SIZE = 2;
+
+    public abstract Object executeDispatch(VirtualFrame frame, SLFunction function, Object[] arguments);
+
+    @Specialization(guards = "function.getCallTarget() == null")
+    protected Object doUndefinedFunction(SLFunction function, @SuppressWarnings("unused") Object[] arguments) {
+        throw new SLUndefinedFunctionException(function.getName());
+    }
+
+    /**
+     * Inline cached specialization of the dispatch.
+     *
+     * <p>
+     * Since SL is a quite simple language, the benefit of the inline cache is quite small: after
+     * checking that the actual function to be executed is the same as the cachedFuntion, we can
+     * safely execute the cached call target. You can reasonably argue that caching the call target
+     * is overkill, since we could just retrieve it via {@code function.getCallTarget()}. However,
+     * in a more complex language the lookup of the call target is usually much more complicated
+     * than in SL. In addition, caching the call target allows method inlining.
+     * </p>
+     *
+     * <p>
+     * {@code limit = "INLINE_CACHE_SIZE"} Specifies the limit number of inline cache specialization
+     * instantiations.
+     * </p>
+     * <p>
+     * {@code guards = "function == cachedFunction"} The inline cache check. Note that
+     * cachedFunction is a final field so that the compiler can optimize the check.
+     * </p>
+     * <p>
+     * {@code assumptions = "cachedFunction.getCallTargetStable()"} Support for function
+     * redefinition: When a function is redefined, the call target maintained by the SLFunction
+     * object is change. To avoid a check for that, we use an Assumption that is invalidated by the
+     * SLFunction when the change is performed. Since checking an assumption is a no-op in compiled
+     * code, the assumption check performed by the DSL does not add any overhead during optimized
+     * execution.
+     * </p>
+     *
+     * @see Cached
+     * @see Specialization
+     *
+     * @param function the dynamically provided function
+     * @param cachedFunction the cached function of the specialization instance
+     * @param callNode the {@link DirectCallNode} specifically created for the {@link CallTarget} in
+     *            cachedFunction.
+     */
+    @Specialization(limit = "INLINE_CACHE_SIZE", guards = "function == cachedFunction", assumptions = "cachedFunction.getCallTargetStable()")
+    protected static Object doDirect(VirtualFrame frame, SLFunction function, Object[] arguments, //
+                    @Cached("function") SLFunction cachedFunction, //
+                    @Cached("create(cachedFunction.getCallTarget())") DirectCallNode callNode) {
+        /* Inline cache hit, we are safe to execute the cached call target. */
+        return callNode.call(frame, arguments);
+    }
+
+    /**
+     * Slow-path code for a call, used when the polymorphic inline cache exceeded its maximum size
+     * specified in <code>INLINE_CACHE_SIZE</code>. Such calls are not optimized any further, e.g.,
+     * no method inlining is performed.
+     */
+    @Specialization(contains = "doDirect")
+    protected static Object doIndirect(VirtualFrame frame, SLFunction function, Object[] arguments, //
+                    @Cached("create()") IndirectCallNode callNode) {
+        /*
+         * SL has a quite simple call lookup: just ask the function for the current call target, and
+         * call it.
+         */
+        return callNode.call(frame, function.getCallTarget(), arguments);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLInvokeNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.call;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The node for function invocation in SL. Since SL has first class functions, the
+ * {@link SLFunction target function} can be computed by an {@link #functionNode arbitrary
+ * expression}. This node is responsible for evaluating this expression, as well as evaluating the
+ * {@link #argumentNodes arguments}. The actual dispatch is then delegated to a chain of
+ * {@link SLDispatchNode} that form a polymorphic inline cache.
+ */
+@NodeInfo(shortName = "invoke")
+public final class SLInvokeNode extends SLExpressionNode {
+
+    public static SLInvokeNode create(SourceSection src, SLExpressionNode function, SLExpressionNode[] arguments) {
+        return new SLInvokeNode(src, function, arguments);
+    }
+
+    @Child private SLExpressionNode functionNode;
+    @Children private final SLExpressionNode[] argumentNodes;
+    @Child private SLDispatchNode dispatchNode;
+
+    private SLInvokeNode(SourceSection src, SLExpressionNode functionNode, SLExpressionNode[] argumentNodes) {
+        super(src);
+        this.functionNode = functionNode;
+        this.argumentNodes = argumentNodes;
+        this.dispatchNode = SLDispatchNodeGen.create();
+    }
+
+    @Override
+    @ExplodeLoop
+    public Object executeGeneric(VirtualFrame frame) {
+        SLFunction function = evaluateFunction(frame);
+
+        /*
+         * The number of arguments is constant for one invoke node. During compilation, the loop is
+         * unrolled and the execute methods of all arguments are inlined. This is triggered by the
+         * ExplodeLoop annotation on the method. The compiler assertion below illustrates that the
+         * array length is really constant.
+         */
+        CompilerAsserts.compilationConstant(argumentNodes.length);
+
+        Object[] argumentValues = new Object[argumentNodes.length];
+        for (int i = 0; i < argumentNodes.length; i++) {
+            argumentValues[i] = argumentNodes[i].executeGeneric(frame);
+        }
+
+        return dispatchNode.executeDispatch(frame, function, argumentValues);
+    }
+
+    private SLFunction evaluateFunction(VirtualFrame frame) {
+        try {
+            /*
+             * The function node must evaluate to a SLFunction value, so we call
+             * function-specialized method.
+             */
+            return functionNode.executeFunction(frame);
+        } catch (UnexpectedResultException ex) {
+            /*
+             * The function node evaluated to a non-function result. This is a type error in the SL
+             * program. We report it with the same exception that Truffle DSL generated nodes use to
+             * report type errors.
+             */
+            throw new UnsupportedSpecializationException(this, new Node[]{functionNode}, ex.getResult());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUndefinedFunctionException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.call;
+
+public class SLUndefinedFunctionException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String functionName;
+
+    public SLUndefinedFunctionException(String functionName) {
+        this.functionName = functionName;
+    }
+
+    public String getFunctionName() {
+        return functionName;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * A statement node that just executes a list of other statements.
+ */
+@NodeInfo(shortName = "block", description = "The node implementing a source code block")
+public final class SLBlockNode extends SLStatementNode {
+
+    /**
+     * The array of child nodes. The annotation {@link com.oracle.truffle.api.nodes.Node.Children
+     * Children} informs Truffle that the field contains multiple children. It is a Truffle
+     * requirement that the field is {@code final} and an array of nodes.
+     */
+    @Children private final SLStatementNode[] bodyNodes;
+
+    public SLBlockNode(SourceSection src, SLStatementNode... bodyNodes) {
+        super(src);
+        this.bodyNodes = bodyNodes;
+    }
+
+    /**
+     * Execute all child statements. The annotation {@link ExplodeLoop} triggers full unrolling of
+     * the loop during compilation. This allows the {@link SLStatementNode#executeVoid} method of
+     * all children to be inlined.
+     */
+    @Override
+    @ExplodeLoop
+    public void executeVoid(VirtualFrame frame) {
+        /*
+         * This assertion illustrates that the array length is really a constant during compilation.
+         */
+        CompilerAsserts.compilationConstant(bodyNodes.length);
+
+        for (SLStatementNode statement : bodyNodes) {
+            statement.executeVoid(frame);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Exception thrown by the {@link SLBreakNode break statement} and caught by the {@link SLWhileNode
+ * loop statement}. Since the exception is stateless, i.e., has no instance fields, we can use a
+ * {@link #SINGLETON} to avoid memory allocation during interpretation.
+ */
+public final class SLBreakException extends ControlFlowException {
+
+    public static final SLBreakException SINGLETON = new SLBreakException();
+
+    private static final long serialVersionUID = -91013036379258890L;
+
+    /* Prevent instantiation from outside. */
+    private SLBreakException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Implementation of the SL break statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLBreakNode} and the {@link SLWhileNode} of the loop we are
+ * breaking out. This is done by throwing an {@link SLBreakException exception} that is caught by
+ * the {@link SLWhileNode#executeVoid loop node}.
+ */
+@NodeInfo(shortName = "break", description = "The node implementing a break statement")
+public final class SLBreakNode extends SLStatementNode {
+
+    public SLBreakNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        throw SLBreakException.SINGLETON;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Exception thrown by the {@link SLContinueNode continue statement} and caught by the
+ * {@link SLWhileNode loop statement}. Since the exception is stateless, i.e., has no instance
+ * fields, we can use a {@link #SINGLETON} to avoid memory allocation during interpretation.
+ */
+public final class SLContinueException extends ControlFlowException {
+
+    public static final SLContinueException SINGLETON = new SLContinueException();
+
+    private static final long serialVersionUID = 5329687983726237188L;
+
+    /* Prevent instantiation from outside. */
+    private SLContinueException() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Implementation of the SL continue statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLContinueNode} and the {@link SLWhileNode} of the loop we
+ * are continuing. This is done by throwing an {@link SLContinueException exception} that is caught
+ * by the {@link SLWhileNode#executeVoid loop node}.
+ */
+@NodeInfo(shortName = "continue", description = "The node implementing a continue statement")
+public final class SLContinueNode extends SLStatementNode {
+
+    public SLContinueNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        throw SLContinueException.SINGLETON;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The body of a user-defined SL function. This is the node referenced by a {@link SLRootNode} for
+ * user-defined functions. It handles the return value of a function: the {@link SLReturnNode return
+ * statement} throws an {@link SLReturnException exception} with the return value. This node catches
+ * the exception. If the method ends without an explicit {@code return}, return the
+ * {@link SLNull#SINGLETON default null value}.
+ */
+@NodeInfo(shortName = "body")
+public final class SLFunctionBodyNode extends SLExpressionNode {
+
+    /** The body of the function. */
+    @Child private SLStatementNode bodyNode;
+
+    /**
+     * Profiling information, collected by the interpreter, capturing whether the function had an
+     * {@link SLReturnNode explicit return statement}. This allows the compiler to generate better
+     * code.
+     */
+    private final BranchProfile exceptionTaken = BranchProfile.create();
+    private final BranchProfile nullTaken = BranchProfile.create();
+
+    public SLFunctionBodyNode(SourceSection src, SLStatementNode bodyNode) {
+        super(src);
+        this.bodyNode = bodyNode;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        try {
+            /* Execute the function body. */
+            bodyNode.executeVoid(frame);
+
+        } catch (SLReturnException ex) {
+            /*
+             * In the interpreter, record profiling information that the function has an explicit
+             * return.
+             */
+            exceptionTaken.enter();
+            /* The exception transports the actual return value. */
+            return ex.getResult();
+        }
+
+        /*
+         * In the interpreter, record profiling information that the function ends without an
+         * explicit return.
+         */
+        nullTaken.enter();
+        /* Return the default null value. */
+        return SLNull.SINGLETON;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.nodes.*;
+
+@NodeInfo(shortName = "if", description = "The node implementing a condional statement")
+public final class SLIfNode extends SLStatementNode {
+
+    /**
+     * The condition of the {@code if}. This in a {@link SLExpressionNode} because we require a
+     * result value. We do not have a node type that can only return a {@code boolean} value, so
+     * {@link #evaluateCondition executing the condition} can lead to a type error.
+     */
+    @Child private SLExpressionNode conditionNode;
+
+    /** Statement (or {@link SLBlockNode block}) executed when the condition is true. */
+    @Child private SLStatementNode thenPartNode;
+
+    /** Statement (or {@link SLBlockNode block}) executed when the condition is false. */
+    @Child private SLStatementNode elsePartNode;
+
+    /**
+     * Profiling information, collected by the interpreter, capturing the profiling information of
+     * the condition. This allows the compiler to generate better code for conditions that are
+     * always true or always false. Additionally the {@link CountingConditionProfile} implementation
+     * (as opposed to {@link BinaryConditionProfile} implementation) transmits the probability of
+     * the condition to be true to the compiler.
+     */
+    private final ConditionProfile condition = ConditionProfile.createCountingProfile();
+
+    public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+        super(src);
+        this.conditionNode = conditionNode;
+        this.thenPartNode = thenPartNode;
+        this.elsePartNode = elsePartNode;
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        /*
+         * In the interpreter, record profiling information that the condition was executed and with
+         * which outcome.
+         */
+        if (condition.profile(evaluateCondition(frame))) {
+            /* Execute the then-branch. */
+            thenPartNode.executeVoid(frame);
+        } else {
+            /* Execute the else-branch (which is optional according to the SL syntax). */
+            if (elsePartNode != null) {
+                elsePartNode.executeVoid(frame);
+            }
+        }
+    }
+
+    private boolean evaluateCondition(VirtualFrame frame) {
+        try {
+            /*
+             * The condition must evaluate to a boolean value, so we call the boolean-specialized
+             * execute method.
+             */
+            return conditionNode.executeBoolean(frame);
+        } catch (UnexpectedResultException ex) {
+            /*
+             * The condition evaluated to a non-boolean result. This is a type error in the SL
+             * program. We report it with the same exception that Truffle DSL generated nodes use to
+             * report type errors.
+             */
+            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLRepeatingNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.nodes.*;
+
+public final class SLRepeatingNode extends Node implements RepeatingNode {
+
+    /**
+     * The condition of the loop. This in a {@link SLExpressionNode} because we require a result
+     * value. We do not have a node type that can only return a {@code boolean} value, so
+     * {@link #evaluateCondition executing the condition} can lead to a type error.
+     */
+    @Child private SLExpressionNode conditionNode;
+
+    /** Statement (or {@link SLBlockNode block}) executed as long as the condition is true. */
+    @Child private SLStatementNode bodyNode;
+
+    /**
+     * Profiling information, collected by the interpreter, capturing whether a {@code continue}
+     * statement was used in this loop. This allows the compiler to generate better code for loops
+     * without a {@code continue}.
+     */
+    private final BranchProfile continueTaken = BranchProfile.create();
+    private final BranchProfile breakTaken = BranchProfile.create();
+
+    public SLRepeatingNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        super(src);
+        this.conditionNode = conditionNode;
+        this.bodyNode = bodyNode;
+    }
+
+    public boolean executeRepeating(VirtualFrame frame) {
+        if (evaluateCondition(frame)) {
+            try {
+                /* Execute the loop body. */
+                bodyNode.executeVoid(frame);
+            } catch (SLContinueException ex) {
+                /* In the interpreter, record profiling information that the loop uses continue. */
+                continueTaken.enter();
+                /* Fall through to next loop iteration. */
+            } catch (SLBreakException ex) {
+                /* In the interpreter, record profiling information that the loop uses break. */
+                breakTaken.enter();
+                /* Done executing this loop, exit method to execute statement following the loop. */
+                return false;
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean evaluateCondition(VirtualFrame frame) {
+        try {
+            /*
+             * The condition must evaluate to a boolean value, so we call the boolean-specialized
+             * execute method.
+             */
+            return (conditionNode.executeBoolean(frame));
+        } catch (UnexpectedResultException ex) {
+            /*
+             * The condition evaluated to a non-boolean result. This is a type error in the SL
+             * program. We report it with the same exception that Truffle DSL generated nodes use to
+             * report type errors.
+             */
+            throw new UnsupportedSpecializationException(this, new Node[]{conditionNode}, ex.getResult());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return SLStatementNode.formatSourceSection(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * Exception thrown by the {@link SLReturnNode return statement} and caught by the
+ * {@link SLFunctionBodyNode function body}. The exception transports the return value in its
+ * {@link #result} field.
+ */
+public final class SLReturnException extends ControlFlowException {
+
+    private static final long serialVersionUID = 4073191346281369231L;
+
+    private final Object result;
+
+    public SLReturnException(Object result) {
+        this.result = result;
+    }
+
+    public Object getResult() {
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Implementation of the SL return statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLReturnNode} and the {@link SLFunctionBodyNode} of the
+ * method we are exiting. This is done by throwing an {@link SLReturnException exception} that is
+ * caught by the {@link SLFunctionBodyNode#executeGeneric function body}. The exception transports
+ * the return value.
+ */
+@NodeInfo(shortName = "return", description = "The node implementing a return statement")
+public final class SLReturnNode extends SLStatementNode {
+
+    @Child private SLExpressionNode valueNode;
+
+    public SLReturnNode(SourceSection src, SLExpressionNode valueNode) {
+        super(src);
+        this.valueNode = valueNode;
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        Object result;
+        if (valueNode != null) {
+            result = valueNode.executeGeneric(frame);
+        } else {
+            /* Return statement that was not followed by an expression, so return the SL null value. */
+            result = SLNull.SINGLETON;
+        }
+        throw new SLReturnException(result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.controlflow;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+@NodeInfo(shortName = "while", description = "The node implementing a while loop")
+public final class SLWhileNode extends SLStatementNode {
+
+    @Child private LoopNode loopNode;
+
+    public SLWhileNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        super(src);
+        this.loopNode = Truffle.getRuntime().createLoopNode(new SLRepeatingNode(src, conditionNode, bodyNode));
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame frame) {
+        loopNode.executeLoop(frame);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * SL node that performs the "+" operation, which performs addition on arbitrary precision numbers,
+ * as well as String concatenation if one of the operands is a String.
+ * <p>
+ * Type specialization on the input values is essential for the performance. This is achieved via
+ * node rewriting: specialized subclasses handle just a single type, so that the generic node that
+ * can handle all types is used only in cases where different types were encountered. The subclasses
+ * are automatically generated by the Truffle DSL. In addition, a {@link SLAddNodeGen factory class}
+ * is generated that provides, e.g., {@link SLAddNodeGen#create node creation}.
+ */
+@NodeInfo(shortName = "+")
+public abstract class SLAddNode extends SLBinaryNode {
+
+    public SLAddNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * Specialization for primitive {@code long} values. This is the fast path of the
+     * arbitrary-precision arithmetic. We need to check for overflows of the addition, and switch to
+     * the {@link #add(BigInteger, BigInteger) slow path}. Therefore, we use an
+     * {@link ExactMath#addExact(long, long) addition method that throws an exception on overflow}.
+     * The {@code rewriteOn} attribute on the {@link Specialization} annotation automatically
+     * triggers the node rewriting on the exception.
+     * <p>
+     * In compiled code, {@link ExactMath#addExact(long, long) addExact} is compiled to efficient
+     * machine code that uses the processor's overflow flag. Therefore, this method is compiled to
+     * only two machine code instructions on the fast path.
+     * <p>
+     * This specialization is automatically selected by the Truffle DSL if both the left and right
+     * operand are {@code long} values.
+     */
+    @Specialization(rewriteOn = ArithmeticException.class)
+    protected long add(long left, long right) {
+        return ExactMath.addExact(left, right);
+    }
+
+    /**
+     * This is the slow path of the arbitrary-precision arithmetic. The {@link BigInteger} type of
+     * Java is doing everything we need.
+     * <p>
+     * This specialization is automatically selected by the Truffle DSL if both the left and right
+     * operand are {@link BigInteger} values. Because the type system defines an
+     * {@link ImplicitCast implicit conversion} from {@code long} to {@link BigInteger} in
+     * {@link SLTypes#castBigInteger(long)}, this specialization is also taken if the left or the
+     * right operand is a {@code long} value. Because the {@link #add(long, long) long}
+     * specialization} has the {@code rewriteOn} attribute, this specialization is also taken if
+     * both input values are {@code long} values but the primitive addition overflows.
+     */
+    @Specialization
+    @TruffleBoundary
+    protected BigInteger add(BigInteger left, BigInteger right) {
+        return left.add(right);
+    }
+
+    /**
+     * Specialization for String concatenation. The SL specification says that String concatenation
+     * works if either the left or the right operand is a String. The non-string operand is
+     * converted then automatically converted to a String.
+     * <p>
+     * To implement these semantics, we tell the Truffle DSL to use a custom guard. The guard
+     * function is defined in {@link #isString this class}, but could also be in any superclass.
+     */
+    @Specialization(guards = "isString(left, right)")
+    @TruffleBoundary
+    protected String add(Object left, Object right) {
+        return left.toString() + right.toString();
+    }
+
+    /**
+     * Guard for String concatenation: returns true if either the left or the right operand is a
+     * {@link String}.
+     */
+    protected boolean isString(Object a, Object b) {
+        return a instanceof String || b instanceof String;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Constant literal for a arbitrary-precision number that exceeds the range of
+ * {@link SLLongLiteralNode}.
+ */
+@NodeInfo(shortName = "const")
+public final class SLBigIntegerLiteralNode extends SLExpressionNode {
+
+    private final BigInteger value;
+
+    public SLBigIntegerLiteralNode(SourceSection src, BigInteger value) {
+        super(src);
+        this.value = value;
+    }
+
+    @Override
+    public BigInteger executeGeneric(VirtualFrame frame) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}. Divisions by 0 throw the
+ * same {@link ArithmeticException exception} as in Java, SL has no special handling for it to keep
+ * the code simple.
+ */
+@NodeInfo(shortName = "/")
+public abstract class SLDivNode extends SLBinaryNode {
+
+    public SLDivNode(SourceSection src) {
+        super(src);
+    }
+
+    @Specialization(rewriteOn = ArithmeticException.class)
+    protected long div(long left, long right) throws ArithmeticException {
+        long result = left / right;
+        /*
+         * The division overflows if left is Long.MIN_VALUE and right is -1.
+         */
+        if ((left & right & result) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return result;
+    }
+
+    @Specialization
+    protected BigInteger div(BigInteger left, BigInteger right) {
+        return left.divide(right);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * The {@code ==} operator of SL is defined on all types. Therefore, we need a
+ * {@link #equal(Object, Object) generic implementation} that can handle all possible types. But
+ * since {@code ==} can only return {@code true} when the type of the left and right operand are the
+ * same, the specializations already cover all possible cases that can return {@code true} and the
+ * generic case is trivial.
+ * <p>
+ * Note that we do not need the analogous {@code =!} operator, because we can just
+ * {@link SLLogicalNotNode negate} the {@code ==} operator.
+ */
+@NodeInfo(shortName = "==")
+public abstract class SLEqualNode extends SLBinaryNode {
+
+    public SLEqualNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    @Specialization
+    protected boolean equal(long left, long right) {
+        return left == right;
+    }
+
+    @Specialization
+    protected boolean equal(BigInteger left, BigInteger right) {
+        return left.equals(right);
+    }
+
+    @Specialization
+    protected boolean equal(boolean left, boolean right) {
+        return left == right;
+    }
+
+    @Specialization
+    protected boolean equal(String left, String right) {
+        return left.equals(right);
+    }
+
+    @Specialization
+    protected boolean equal(SLFunction left, SLFunction right) {
+        /*
+         * Our function registry maintains one canonical SLFunction object per function name, so we
+         * do not need equals().
+         */
+        return left == right;
+    }
+
+    @Specialization
+    protected boolean equal(SLNull left, SLNull right) {
+        /* There is only the singleton instance of SLNull, so we do not need equals(). */
+        return left == right;
+    }
+
+    /**
+     * The {@link Fallback} annotation informs the Truffle DSL that this method should be executed
+     * when no {@link Specialization specialized method} matches. The operand types must be
+     * {@link Object}.
+     */
+    @Fallback
+    protected boolean equal(Object left, Object right) {
+        /*
+         * We covered all the cases that can return true in specializations. If we compare two
+         * values with different types, no specialization matches and we end up here.
+         */
+        assert !left.equals(right);
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Constant literal for a {@link SLFunction function} value, created when a function name occurs as
+ * a literal in SL source code. Note that function redefinition can change the {@link CallTarget
+ * call target} that is executed when calling the function, but the {@link SLFunction} for a name
+ * never changes. This is guaranteed by the {@link SLFunctionRegistry}.
+ */
+@NodeInfo(shortName = "func")
+public final class SLFunctionLiteralNode extends SLExpressionNode {
+
+    private final SLFunction value;
+
+    public SLFunctionLiteralNode(SourceSection src, SLFunction value) {
+        super(src);
+        this.value = value;
+    }
+
+    @Override
+    public SLFunction executeGeneric(VirtualFrame frame) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the {@link SLLessThanNode}.
+ */
+@NodeInfo(shortName = "<=")
+public abstract class SLLessOrEqualNode extends SLBinaryNode {
+
+    public SLLessOrEqualNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    @Specialization
+    protected boolean lessOrEqual(long left, long right) {
+        return left <= right;
+    }
+
+    @Specialization
+    protected boolean lessOrEqual(BigInteger left, BigInteger right) {
+        return left.compareTo(right) <= 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}. The only difference: the
+ * specialized methods return {@code boolean} instead of the input types.
+ */
+@NodeInfo(shortName = "<")
+public abstract class SLLessThanNode extends SLBinaryNode {
+
+    public SLLessThanNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    @Specialization
+    protected boolean lessThan(long left, long right) {
+        return left < right;
+    }
+
+    @Specialization
+    protected boolean lessThan(BigInteger left, BigInteger right) {
+        return left.compareTo(right) < 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class declares specializations similar to the extensively documented {@link SLAddNode}. It
+ * uses one additional feature of the Truffle DSL: {@link ShortCircuit}.
+ * <p>
+ * Logical operations in SL use short circuit evaluation: if the evaluation of the left operand
+ * already decides the result of the operation, the right operand must not be executed. This is
+ * expressed in the Truffle DSL via a method annotated with {@link ShortCircuit}, which returns
+ * whether a child needs to be executed based on the result of already executed children.
+ */
+@NodeInfo(shortName = "&&")
+@SuppressWarnings("unused")
+public abstract class SLLogicalAndNode extends SLBinaryNode {
+
+    public SLLogicalAndNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    /**
+     * This method is called after the left child was evaluated, but before the right child is
+     * evaluated. The right child is only evaluated when the return value is {code true}.
+     */
+    @ShortCircuit("rightNode")
+    protected boolean needsRightNode(boolean left) {
+        return left;
+    }
+
+    /**
+     * Similar to {@link #needsRightNode(boolean)}, but for generic cases where the type of the left
+     * child is not known.
+     */
+    @ShortCircuit("rightNode")
+    protected boolean needsRightNode(Object left) {
+        return left instanceof Boolean && needsRightNode(((Boolean) left).booleanValue());
+    }
+
+    @Specialization
+    protected boolean doBoolean(boolean left, boolean hasRight, boolean right) {
+        return left && right;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Example of a simple unary node that uses type specialization. See {@link SLAddNode} for
+ * information on specializations.
+ */
+@NodeChild("valueNode")
+@NodeInfo(shortName = "!")
+public abstract class SLLogicalNotNode extends SLExpressionNode {
+
+    public SLLogicalNotNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    @Specialization
+    protected boolean doBoolean(boolean value) {
+        return !value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the {@link SLLogicalAndNode}.
+ */
+@NodeInfo(shortName = "||")
+@SuppressWarnings("unused")
+public abstract class SLLogicalOrNode extends SLBinaryNode {
+
+    public SLLogicalOrNode(SourceSection src) {
+        super(src);
+    }
+
+    @Override
+    public abstract boolean executeBoolean(VirtualFrame frame);
+
+    @ShortCircuit("rightNode")
+    protected boolean needsRightNode(boolean left) {
+        return !left;
+    }
+
+    @ShortCircuit("rightNode")
+    protected boolean needsRightNode(Object left) {
+        return left instanceof Boolean && needsRightNode(((Boolean) left).booleanValue());
+    }
+
+    @Specialization
+    protected boolean doBoolean(boolean left, boolean hasRight, boolean right) {
+        return left || right;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Constant literal for a primitive {@code long} value. The unboxed value can be returned when the
+ * parent expects a long value and calls {@link SLLongLiteralNode#executeLong}. In the generic case,
+ * the primitive value is automatically boxed by Java.
+ */
+@NodeInfo(shortName = "const")
+public final class SLLongLiteralNode extends SLExpressionNode {
+
+    private final long value;
+
+    public SLLongLiteralNode(SourceSection src, long value) {
+        super(src);
+        this.value = value;
+    }
+
+    @Override
+    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
+        return value;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}.
+ */
+@NodeInfo(shortName = "*")
+public abstract class SLMulNode extends SLBinaryNode {
+
+    public SLMulNode(SourceSection src) {
+        super(src);
+    }
+
+    @Specialization(rewriteOn = ArithmeticException.class)
+    protected long mul(long left, long right) {
+        return ExactMath.multiplyExact(left, right);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected BigInteger mul(BigInteger left, BigInteger right) {
+        return left.multiply(right);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLParenExpressionNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * A {@link SLExpressionNode} that represents a parenthesized expression; it simply returns the
+ * value of the enclosed (child) expression. It is represented separately in the AST for the purpose
+ * of correct source attribution; this preserves the lexical relationship between the two
+ * parentheses and allows a tool to describe the expression as distinct from its contents.
+ */
+@NodeInfo(description = "A parenthesized expression")
+public class SLParenExpressionNode extends SLExpressionNode {
+
+    private final SLExpressionNode expression;
+
+    public SLParenExpressionNode(SourceSection src, SLExpressionNode expression) {
+        super(src);
+        this.expression = insert(expression);
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        return expression.executeGeneric(frame);
+    }
+
+    @Override
+    public long executeLong(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeLong(frame);
+    }
+
+    @Override
+    public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException {
+        return expression.executeBoolean(frame);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Constant literal for a String value.
+ */
+@NodeInfo(shortName = "const")
+public final class SLStringLiteralNode extends SLExpressionNode {
+
+    private final String value;
+
+    public SLStringLiteralNode(SourceSection src, String value) {
+        super(src);
+        this.value = value;
+    }
+
+    @Override
+    public String executeGeneric(VirtualFrame frame) {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression;
+
+import java.math.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}.
+ */
+@NodeInfo(shortName = "-")
+public abstract class SLSubNode extends SLBinaryNode {
+
+    public SLSubNode(SourceSection src) {
+        super(src);
+    }
+
+    @Specialization(rewriteOn = ArithmeticException.class)
+    protected long sub(long left, long right) {
+        return ExactMath.subtractExact(left, right);
+    }
+
+    @Specialization
+    protected BigInteger sub(BigInteger left, BigInteger right) {
+        return left.subtract(right);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/demo/SLAddWithoutSpecializationNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.expression.demo;
+
+import java.math.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.expression.*;
+
+/**
+ * This is an example how the add operation would be implemented without specializations and without
+ * the Truffle DSL. Do not write such code in your language! See {@link SLAddNode} how the add
+ * operation is implemented correctly.
+ */
+public class SLAddWithoutSpecializationNode extends SLExpressionNode {
+
+    @Child private SLExpressionNode leftNode;
+    @Child private SLExpressionNode rightNode;
+
+    public SLAddWithoutSpecializationNode(SLExpressionNode leftNode, SLExpressionNode rightNode) {
+        super(null);
+        this.leftNode = leftNode;
+        this.rightNode = rightNode;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        /* Evaluate the child nodes. */
+        Object left = leftNode.executeGeneric(frame);
+        Object right = rightNode.executeGeneric(frame);
+
+        if (left instanceof Long && right instanceof Long) {
+            /* Fast path of the arbitrary-precision arithmetic. We need to check for overflows */
+            try {
+                return ExactMath.addExact((Long) left, (Long) right);
+            } catch (ArithmeticException ex) {
+                /* Fall through to BigInteger case. */
+            }
+        }
+
+        /* Implicit type conversions. */
+        if (left instanceof Long) {
+            left = BigInteger.valueOf((Long) left);
+        }
+        if (right instanceof Long) {
+            right = BigInteger.valueOf((Long) right);
+        }
+        if (left instanceof BigInteger && right instanceof BigInteger) {
+            /* Slow path of the arbitrary-precision arithmetic. */
+            return ((BigInteger) left).add((BigInteger) right);
+        }
+
+        /* String concatenation if either the left or the right operand is a String. */
+        if (left instanceof String || right instanceof String) {
+            return left.toString() + right.toString();
+        }
+
+        /* Type error. */
+        throw new UnsupportedSpecializationException(this, new Node[]{leftNode, rightNode}, new Object[]{left, right});
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.instrument;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+
+/**
+ * SLASTPrinter is used to print for SL's internal Truffle AST. This is used by
+ * {@link SLDefaultVisualizer} to provide a means of displaying the internal Truffle AST
+ */
+public final class SLASTPrinter extends DefaultASTPrinter {
+
+    public SLASTPrinter() {
+    }
+
+    @Override
+    protected void printTree(PrintWriter p, Node node, int maxDepth, Node markNode, int level) {
+        if (node == null) {
+            p.print("null");
+            return;
+        }
+
+        p.print(nodeName(node));
+
+        p.print("(");
+
+        if (node instanceof InstrumentationNode) {
+            p.print(instrumentInfo((InstrumentationNode) node));
+        }
+
+        p.print(sourceInfo(node));
+
+        p.print(NodeUtil.printSyntaxTags(node));
+
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
+
+        for (NodeFieldAccessor field : NodeClass.get(node.getClass()).getFields()) {
+            if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
+                childFields.add(field);
+            } else if (field.getKind() == NodeFieldKind.DATA) {
+                // p.print(sep);
+                // sep = ", ";
+                //
+                // final String fieldName = field.getName();
+                // switch (fieldName) {
+                //
+                // }
+                // p.print(fieldName);
+                // p.print(" = ");
+                // p.print(field.loadValue(node));
+            }
+        }
+        p.print(")");
+
+        if (level <= maxDepth) {
+
+            if (childFields.size() != 0) {
+                p.print(" {");
+                for (NodeFieldAccessor field : childFields) {
+
+                    Object value = field.loadValue(node);
+                    if (value == null) {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                        p.print(" = null ");
+                    } else if (field.getKind() == NodeFieldKind.CHILD) {
+                        printChild(p, maxDepth, markNode, level, field, value);
+                    } else if (field.getKind() == NodeFieldKind.CHILDREN) {
+                        printChildren(p, maxDepth, markNode, level, field, value);
+                    } else {
+                        printNewLine(p, level);
+                        p.print(field.getName());
+                    }
+                }
+                printNewLine(p, level - 1);
+                p.print("}");
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLDefaultVisualizer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.instrument;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * SLDefaultVisualizer provides methods to get the names of SL's internal Truffle AST nodes.
+ *
+ */
+public class SLDefaultVisualizer extends DefaultVisualizer {
+
+    private final SLASTPrinter astPrinter;
+
+    public SLDefaultVisualizer() {
+        this.astPrinter = new SLASTPrinter();
+    }
+
+    @Override
+    public ASTPrinter getASTPrinter() {
+        return astPrinter;
+    }
+
+    @Override
+    public String displayMethodName(Node node) {
+
+        if (node == null) {
+            return null;
+        }
+        RootNode root = node.getRootNode();
+        if (root instanceof SLRootNode) {
+            SLRootNode slRootNode = (SLRootNode) root;
+            return slRootNode.toString();
+
+        }
+        return "unknown";
+    }
+
+    @Override
+    public String displayCallTargetName(CallTarget callTarget) {
+        if (callTarget instanceof RootCallTarget) {
+            final RootCallTarget rootCallTarget = (RootCallTarget) callTarget;
+            SLRootNode slRootNode = (SLRootNode) rootCallTarget.getRootNode();
+            return slRootNode.toString();
+        }
+        return callTarget.toString();
+    }
+
+    @Override
+    public String displayValue(Object value, int trim) {
+        if (value == SLNull.SINGLETON) {
+            return "null";
+        }
+        return trim(value.toString(), trim);
+    }
+
+    @Override
+    public String displayIdentifier(FrameSlot slot) {
+
+        final Object id = slot.getIdentifier();
+        return id.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapperNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to
+ * enable "instrumentation" of an {@link SLExpressionNode}. Tools wishing to interact with AST
+ * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the
+ * wrapper, and to which this wrapper routes execution events.
+ */
+@NodeInfo(cost = NodeCost.NONE)
+public final class SLExpressionWrapperNode extends SLExpressionNode implements WrapperNode {
+    @Child private SLExpressionNode child;
+    @Child private ProbeNode probeNode;
+
+    /**
+     * Constructor.
+     *
+     * @param child The {@link SLExpressionNode} that this wrapper is wrapping
+     */
+    public SLExpressionWrapperNode(SLExpressionNode child) {
+        super(child.getSourceSection());
+        assert !(child instanceof SLExpressionWrapperNode);
+        this.child = child;
+    }
+
+    public String instrumentationInfo() {
+        return "Wrapper node for SL Expressions";
+    }
+
+    @Override
+    public boolean isInstrumentable() {
+        return false;
+    }
+
+    @Override
+    public SLExpressionNode getNonWrapperNode() {
+        return child;
+    }
+
+    public void insertProbe(ProbeNode newProbeNode) {
+        this.probeNode = newProbeNode;
+    }
+
+    public Probe getProbe() {
+        return probeNode.getProbe();
+    }
+
+    public Node getChild() {
+        return child;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame vFrame) {
+
+        probeNode.enter(child, vFrame);
+        Object result;
+
+        try {
+            result = child.executeGeneric(vFrame);
+            probeNode.returnValue(child, vFrame, result);
+        } catch (Exception e) {
+            probeNode.returnExceptional(child, vFrame, e);
+            throw (e);
+        }
+        return result;
+    }
+
+    @Override
+    public long executeLong(VirtualFrame vFrame) throws UnexpectedResultException {
+        return SLTypesGen.expectLong(executeGeneric(vFrame));
+    }
+
+    @Override
+    public boolean executeBoolean(VirtualFrame vFrame) throws UnexpectedResultException {
+        return SLTypesGen.expectBoolean(executeGeneric(vFrame));
+    }
+
+    @Override
+    public SLFunction executeFunction(VirtualFrame vFrame) throws UnexpectedResultException {
+        probeNode.enter(child, vFrame);
+        SLFunction result;
+
+        try {
+            result = child.executeFunction(vFrame);
+            probeNode.returnValue(child, vFrame, result);
+        } catch (Exception e) {
+            probeNode.returnExceptional(child, vFrame, e);
+            throw (e);
+        }
+        return result;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStandardASTProber.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.instrument;
+
+import static com.oracle.truffle.api.instrument.StandardSyntaxTag.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.controlflow.*;
+import com.oracle.truffle.sl.nodes.local.*;
+
+/**
+ * A visitor which traverses a completely parsed Simple AST (presumed not yet executed) and enables
+ * instrumentation at a few standard kinds of nodes.
+ */
+public class SLStandardASTProber implements NodeVisitor, ASTProber {
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Instruments and tags all relevant {@link SLStatementNode}s and {@link SLExpressionNode}s.
+     * Currently, only SLStatementNodes that are not SLExpressionNodes are tagged as statements.
+     */
+    public boolean visit(Node node) {
+
+        if (!(node instanceof InstrumentationNode) && node instanceof SLStatementNode && node.getParent() != null && node.getSourceSection() != null) {
+            // All SL nodes are instrumentable, but treat expressions specially
+
+            if (node instanceof SLExpressionNode) {
+                SLExpressionNode expressionNode = (SLExpressionNode) node;
+                Probe probe = expressionNode.probe();
+                if (node instanceof SLWriteLocalVariableNode) {
+                    probe.tagAs(STATEMENT, null);
+                    probe.tagAs(ASSIGNMENT, null);
+                }
+            } else {
+                SLStatementNode statementNode = (SLStatementNode) node;
+                Probe probe = statementNode.probe();
+                probe.tagAs(STATEMENT, null);
+                if (node instanceof SLWhileNode) {
+                    probe.tagAs(START_LOOP, null);
+                }
+            }
+        }
+        return true;
+    }
+
+    public void probeAST(Node node) {
+        node.accept(this);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapperNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.instrument;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * A Truffle node that can be inserted into a Simple AST (assumed not to have executed yet) to
+ * enable "instrumentation" of a {@link SLStatementNode}. Tools wishing to interact with AST
+ * execution may attach {@link Instrument}s to the {@link Probe} uniquely associated with the
+ * wrapper, and to which this wrapper routes execution events.
+ */
+@NodeInfo(cost = NodeCost.NONE)
+public final class SLStatementWrapperNode extends SLStatementNode implements WrapperNode {
+
+    @Child private SLStatementNode child;
+    @Child private ProbeNode probeNode;
+
+    public SLStatementWrapperNode(SLStatementNode child) {
+        super(child.getSourceSection());
+        assert !(child instanceof SLStatementWrapperNode);
+        this.child = child;
+    }
+
+    public String instrumentationInfo() {
+        return "Wrapper node for SL Statements";
+    }
+
+    @Override
+    public boolean isInstrumentable() {
+        return false;
+    }
+
+    @Override
+    public SLStatementNode getNonWrapperNode() {
+        return child;
+    }
+
+    public void insertProbe(ProbeNode newProbeNode) {
+        this.probeNode = newProbeNode;
+    }
+
+    public Probe getProbe() {
+        return probeNode.getProbe();
+    }
+
+    @Override
+    public Node getChild() {
+        return child;
+    }
+
+    @Override
+    public void executeVoid(VirtualFrame vFrame) {
+        probeNode.enter(child, vFrame);
+
+        try {
+            child.executeVoid(vFrame);
+            probeNode.returnVoid(child, vFrame);
+        } catch (KillException e) {
+            throw (e);
+        } catch (Exception e) {
+            probeNode.returnExceptional(child, vFrame, e);
+            throw (e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.local;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Reads a function argument. Arguments are passed in as an object array.
+ * <p>
+ * Arguments are not type-specialized. To ensure that repeated accesses within a method are
+ * specialized and can, e.g., be accessed without unboxing, all arguments are loaded into local
+ * variables {@link SLNodeFactory#addFormalParameter in the method prologue}.
+ */
+public class SLReadArgumentNode extends SLExpressionNode {
+
+    /** The argument number, i.e., the index into the array of arguments. */
+    private final int index;
+
+    /**
+     * Profiling information, collected by the interpreter, capturing whether the function was
+     * called with fewer actual arguments than formal arguments.
+     */
+    private final BranchProfile outOfBoundsTaken = BranchProfile.create();
+
+    public SLReadArgumentNode(SourceSection src, int index) {
+        super(src);
+        this.index = index;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object[] args = frame.getArguments();
+        if (index < args.length) {
+            return args[index];
+        } else {
+            /* In the interpreter, record profiling information that the branch was used. */
+            outOfBoundsTaken.enter();
+            /* Use the default null value. */
+            return SLNull.SINGLETON;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.local;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Node to read a local variable from a function's {@link VirtualFrame frame}. The Truffle frame API
+ * allows to store primitive values of all Java primitive types, and Object values. This means that
+ * all SL types that are objects are handled by the {@link #readObject} method. When a local
+ * variable changes its type, the frame access method throws an {@link FrameSlotTypeException},
+ * which causes not rewriting. The rewriting code is generated by the Truffle DSL.
+ */
+@NodeField(name = "slot", type = FrameSlot.class)
+public abstract class SLReadLocalVariableNode extends SLExpressionNode {
+
+    public SLReadLocalVariableNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * Returns the descriptor of the accessed local variable. The implementation of this method is
+     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
+     */
+    protected abstract FrameSlot getSlot();
+
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
+    protected long readLong(VirtualFrame frame) throws FrameSlotTypeException {
+        return frame.getLong(getSlot());
+    }
+
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
+    protected boolean readBoolean(VirtualFrame frame) throws FrameSlotTypeException {
+        return frame.getBoolean(getSlot());
+    }
+
+    @Specialization(rewriteOn = FrameSlotTypeException.class)
+    protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException {
+        return frame.getObject(getSlot());
+    }
+
+    /**
+     * This is the generic case that always succeeds. Since we already have another specialization
+     * with the same signature above, we need to order them explicitly with the order attribute.
+     */
+    @Specialization(contains = {"readLong", "readBoolean", "readObject"})
+    protected Object read(VirtualFrame frame) {
+        return frame.getValue(getSlot());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes.local;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Node to write a local variable to a function's {@link VirtualFrame frame}. The Truffle frame API
+ * allows to store primitive values of all Java primitive types, and Object values.
+ */
+@NodeChild("valueNode")
+@NodeField(name = "slot", type = FrameSlot.class)
+public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
+
+    public SLWriteLocalVariableNode(SourceSection src) {
+        super(src);
+    }
+
+    /**
+     * Returns the descriptor of the accessed local variable. The implementation of this method is
+     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
+     */
+    protected abstract FrameSlot getSlot();
+
+    /**
+     * Specialized method to write a primitive {@code long} value. This is only possible if the
+     * local variable also has currently the type {@code long}, therefore a Truffle DSL
+     * {@link #isLongKind(VirtualFrame) custom guard} is specified.
+     */
+    @Specialization(guards = "isLongKind(frame)")
+    protected long writeLong(VirtualFrame frame, long value) {
+        frame.setLong(getSlot(), value);
+        return value;
+    }
+
+    @Specialization(guards = "isBooleanKind(frame)")
+    protected boolean writeBoolean(VirtualFrame frame, boolean value) {
+        frame.setBoolean(getSlot(), value);
+        return value;
+    }
+
+    /**
+     * Generic write method that works for all possible types.
+     * <p>
+     * Why is this method annotated with {@link Specialization} and not {@link Fallback}? For a
+     * {@link Fallback} method, the Truffle DSL generated code would try all other specializations
+     * first before calling this method. We know that all these specializations would fail their
+     * guards, so there is no point in calling them. Since this method takes a value of type
+     * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the
+     * node will never be re-specialized.
+     */
+    @Specialization(contains = {"writeLong", "writeBoolean"})
+    protected Object write(VirtualFrame frame, Object value) {
+        if (getSlot().getKind() != FrameSlotKind.Object) {
+            /*
+             * The local variable has still a primitive type, we need to change it to Object. Since
+             * the variable type is important when the compiler optimizes a method, we also discard
+             * compiled code.
+             */
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            getSlot().setKind(FrameSlotKind.Object);
+        }
+        frame.setObject(getSlot(), value);
+        return value;
+    }
+
+    /**
+     * Guard function that the local variable has the type {@code long}.
+     */
+    @SuppressWarnings("unused")
+    protected boolean isLongKind(VirtualFrame frame) {
+        return isKind(FrameSlotKind.Long);
+    }
+
+    @SuppressWarnings("unused")
+    protected boolean isBooleanKind(VirtualFrame frame) {
+        return isKind(FrameSlotKind.Boolean);
+    }
+
+    private boolean isKind(FrameSlotKind kind) {
+        if (getSlot().getKind() == kind) {
+            /* Success: the frame slot has the expected kind. */
+            return true;
+        } else if (getSlot().getKind() == FrameSlotKind.Illegal) {
+            /*
+             * This is the first write to this local variable. We can set the type to the one we
+             * expect. Since the variable type is important when the compiler optimizes a method, we
+             * also discard compiled code.
+             */
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            getSlot().setKind(kind);
+            return true;
+        } else {
+            /*
+             * Failure: the frame slot has the wrong kind, the Truffle DSL generated code will
+             * choose a different specialization.
+             */
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Copyright.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,207 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+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, 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.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.sl.parser;
+
+import java.util.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+// Checkstyle: stop
+// @formatter:off
+public class Parser {
+-->constants
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    private final SLNodeFactory factory;
+    -->declarations
+    public Parser(SLContext context, Source source) {
+        this.scanner = new Scanner(source.getInputStream());
+        this.factory = new SLNodeFactory(context, source);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+-->pragmas
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+-->productions
+
+    public void Parse() {
+        la = new Token();
+        la.val = "";
+        Get();
+-->parseRoot
+    }
+
+    private static final boolean[][] set = {
+-->initialization
+    };
+
+    public static void parseSL(SLContext context, Source source) {
+        Parser parser = new Parser(context, source);
+        parser.Parse();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new SLException(msg.toString());
+        }
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {-->errors
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.sl.parser;
+
+import java.util.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+// Checkstyle: stop
+// @formatter:off
+public class Parser {
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _stringLiteral = 2;
+	public static final int _numericLiteral = 3;
+	public static final int maxT = 31;
+
+    static final boolean _T = true;
+    static final boolean _x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    private final SLNodeFactory factory;
+
+    public Parser(SLContext context, Source source) {
+        this.scanner = new Scanner(source.getInputStream());
+        this.factory = new SLNodeFactory(context, source);
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+	void SimpleLanguage() {
+		Function();
+		while (la.kind == 4) {
+			Function();
+		}
+	}
+
+	void Function() {
+		Expect(4);
+		Expect(1);
+		Token identifierToken = t;
+		Expect(5);
+		int bodyStartPos = t.charPos;
+		factory.startFunction(identifierToken, bodyStartPos);
+		if (la.kind == 1) {
+			Get();
+			factory.addFormalParameter(t);
+			while (la.kind == 6) {
+				Get();
+				Expect(1);
+				factory.addFormalParameter(t);
+			}
+		}
+		Expect(7);
+		SLStatementNode body = Block(false);
+		factory.finishFunction(body);
+	}
+
+	SLStatementNode  Block(boolean inLoop) {
+		SLStatementNode  result;
+		factory.startBlock();
+		List<SLStatementNode> body = new ArrayList<>();
+		Expect(8);
+		int start = t.charPos;
+		while (StartOf(1)) {
+			SLStatementNode s = Statement(inLoop);
+			body.add(s);
+		}
+		Expect(9);
+		int length = (t.charPos + t.val.length()) - start;
+		result = factory.finishBlock(body, start, length);
+		return result;
+	}
+
+	SLStatementNode  Statement(boolean inLoop) {
+		SLStatementNode  result;
+		result = null;
+		switch (la.kind) {
+		case 13: {
+			result = WhileStatement();
+			break;
+		}
+		case 10: {
+			Get();
+			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); }
+			Expect(11);
+			break;
+		}
+		case 12: {
+			Get();
+			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); }
+			Expect(11);
+			break;
+		}
+		case 14: {
+			result = IfStatement(inLoop);
+			break;
+		}
+		case 16: {
+			result = ReturnStatement();
+			break;
+		}
+		case 1: case 2: case 3: case 5: {
+			result = Expression();
+			Expect(11);
+			break;
+		}
+		default: SynErr(32); break;
+		}
+		return result;
+	}
+
+	SLStatementNode  WhileStatement() {
+		SLStatementNode  result;
+		Expect(13);
+		Token whileToken = t;
+		Expect(5);
+		SLExpressionNode condition = Expression();
+		Expect(7);
+		SLStatementNode body = Block(true);
+		result = factory.createWhile(whileToken, condition, body);
+		return result;
+	}
+
+	SLStatementNode  IfStatement(boolean inLoop) {
+		SLStatementNode  result;
+		Expect(14);
+		Token ifToken = t;
+		Expect(5);
+		SLExpressionNode condition = Expression();
+		Expect(7);
+		SLStatementNode thenPart = Block(inLoop);
+		SLStatementNode elsePart = null;
+		if (la.kind == 15) {
+			Get();
+			elsePart = Block(inLoop);
+		}
+		result = factory.createIf(ifToken, condition, thenPart, elsePart);
+		return result;
+	}
+
+	SLStatementNode  ReturnStatement() {
+		SLStatementNode  result;
+		Expect(16);
+		Token returnToken = t;
+		SLExpressionNode value = null;
+		if (StartOf(2)) {
+			value = Expression();
+		}
+		result = factory.createReturn(returnToken, value);
+		Expect(11);
+		return result;
+	}
+
+	SLExpressionNode  Expression() {
+		SLExpressionNode  result;
+		result = LogicTerm();
+		while (la.kind == 17) {
+			Get();
+			Token op = t;
+			SLExpressionNode right = LogicTerm();
+			result = factory.createBinary(op, result, right);
+		}
+		return result;
+	}
+
+	SLExpressionNode  LogicTerm() {
+		SLExpressionNode  result;
+		result = LogicFactor();
+		while (la.kind == 18) {
+			Get();
+			Token op = t;
+			SLExpressionNode right = LogicFactor();
+			result = factory.createBinary(op, result, right);
+		}
+		return result;
+	}
+
+	SLExpressionNode  LogicFactor() {
+		SLExpressionNode  result;
+		result = Arithmetic();
+		if (StartOf(3)) {
+			switch (la.kind) {
+			case 19: {
+				Get();
+				break;
+			}
+			case 20: {
+				Get();
+				break;
+			}
+			case 21: {
+				Get();
+				break;
+			}
+			case 22: {
+				Get();
+				break;
+			}
+			case 23: {
+				Get();
+				break;
+			}
+			case 24: {
+				Get();
+				break;
+			}
+			}
+			Token op = t;
+			SLExpressionNode right = Arithmetic();
+			result = factory.createBinary(op, result, right);
+		}
+		return result;
+	}
+
+	SLExpressionNode  Arithmetic() {
+		SLExpressionNode  result;
+		result = Term();
+		while (la.kind == 25 || la.kind == 26) {
+			if (la.kind == 25) {
+				Get();
+			} else {
+				Get();
+			}
+			Token op = t;
+			SLExpressionNode right = Term();
+			result = factory.createBinary(op, result, right);
+		}
+		return result;
+	}
+
+	SLExpressionNode  Term() {
+		SLExpressionNode  result;
+		result = Factor();
+		while (la.kind == 27 || la.kind == 28) {
+			if (la.kind == 27) {
+				Get();
+			} else {
+				Get();
+			}
+			Token op = t;
+			SLExpressionNode right = Factor();
+			result = factory.createBinary(op, result, right);
+		}
+		return result;
+	}
+
+	SLExpressionNode  Factor() {
+		SLExpressionNode  result;
+		result = null;
+		if (la.kind == 1) {
+			Get();
+			if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
+				result = MemberExpression(null, null, t);
+			} else if (StartOf(4)) {
+				result = factory.createRead(t);
+			} else SynErr(33);
+		} else if (la.kind == 2) {
+			Get();
+			result = factory.createStringLiteral(t);
+		} else if (la.kind == 3) {
+			Get();
+			result = factory.createNumericLiteral(t);
+		} else if (la.kind == 5) {
+			Get();
+			int start = t.charPos;
+			result = Expression();
+			SLExpressionNode expr = result;
+			Expect(7);
+			int length = (t.charPos + t.val.length()) - start;
+			result = factory.createParenExpression(expr, start, length);
+		} else SynErr(34);
+		return result;
+	}
+
+	SLExpressionNode  MemberExpression(SLExpressionNode r, SLExpressionNode assignmentReceiver, Token assignmentName) {
+		SLExpressionNode  result;
+		result = null;
+		SLExpressionNode receiver = r;
+		Token nestedAssignmentName = null;
+		if (la.kind == 5) {
+			Get();
+			List<SLExpressionNode> parameters = new ArrayList<>();
+			SLExpressionNode parameter;
+			if (receiver == null) {
+			   receiver = factory.createRead(assignmentName);
+			}
+			if (StartOf(2)) {
+				parameter = Expression();
+				parameters.add(parameter);
+				while (la.kind == 6) {
+					Get();
+					parameter = Expression();
+					parameters.add(parameter);
+				}
+			}
+			Expect(7);
+			Token finalToken = t;
+			result = factory.createCall(receiver, parameters, finalToken);
+		} else if (la.kind == 29) {
+			Get();
+			SLExpressionNode value = Expression();
+			if (assignmentName == null) {
+			   SemErr("invalid assignment target");
+			} else if (assignmentReceiver == null) {
+			   result = factory.createAssignment(assignmentName, value);
+			} else {
+			   result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
+			}
+		} else if (la.kind == 30) {
+			Get();
+			if (receiver == null) {
+			   receiver = factory.createRead(assignmentName);
+			}
+			Expect(1);
+			result = factory.createReadProperty(receiver, t);
+			nestedAssignmentName = t;
+		} else SynErr(35);
+		if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
+			result = MemberExpression(result, receiver, nestedAssignmentName);
+		}
+		return result;
+	}
+
+
+
+    public void Parse() {
+        la = new Token();
+        la.val = "";
+        Get();
+		SimpleLanguage();
+		Expect(0);
+
+    }
+
+    private static final boolean[][] set = {
+		{_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_T,_x, _T,_T,_T,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_T,_T,_T, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x},
+		{_x,_x,_x,_x, _x,_T,_T,_T, _x,_x,_x,_T, _x,_x,_x,_x, _x,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_x, _x}
+
+    };
+
+    public static void parseSL(SLContext context, Source source) {
+        Parser parser = new Parser(context, source);
+        parser.Parse();
+        if (parser.errors.errors.size() > 0) {
+            StringBuilder msg = new StringBuilder("Error(s) parsing script:\n");
+            for (String error : parser.errors.errors) {
+                msg.append(error).append("\n");
+            }
+            throw new SLException(msg.toString());
+        }
+    }
+} // end Parser
+
+class Errors {
+
+    protected final List<String> errors = new ArrayList<>();
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errors.add(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "stringLiteral expected"; break;
+			case 3: s = "numericLiteral expected"; break;
+			case 4: s = "\"function\" expected"; break;
+			case 5: s = "\"(\" expected"; break;
+			case 6: s = "\",\" expected"; break;
+			case 7: s = "\")\" expected"; break;
+			case 8: s = "\"{\" expected"; break;
+			case 9: s = "\"}\" expected"; break;
+			case 10: s = "\"break\" expected"; break;
+			case 11: s = "\";\" expected"; break;
+			case 12: s = "\"continue\" expected"; break;
+			case 13: s = "\"while\" expected"; break;
+			case 14: s = "\"if\" expected"; break;
+			case 15: s = "\"else\" expected"; break;
+			case 16: s = "\"return\" expected"; break;
+			case 17: s = "\"||\" expected"; break;
+			case 18: s = "\"&&\" expected"; break;
+			case 19: s = "\"<\" expected"; break;
+			case 20: s = "\"<=\" expected"; break;
+			case 21: s = "\">\" expected"; break;
+			case 22: s = "\">=\" expected"; break;
+			case 23: s = "\"==\" expected"; break;
+			case 24: s = "\"!=\" expected"; break;
+			case 25: s = "\"+\" expected"; break;
+			case 26: s = "\"-\" expected"; break;
+			case 27: s = "\"*\" expected"; break;
+			case 28: s = "\"/\" expected"; break;
+			case 29: s = "\"=\" expected"; break;
+			case 30: s = "\".\" expected"; break;
+			case 31: s = "??? expected"; break;
+			case 32: s = "invalid Statement"; break;
+			case 33: s = "invalid Factor"; break;
+			case 34: s = "invalid Factor"; break;
+			case 35: s = "invalid MemberExpression"; break;
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void SemErr(String s) {
+        errors.add(s);
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errors.add(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.parser;
+
+import java.math.*;
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.access.*;
+import com.oracle.truffle.sl.nodes.call.*;
+import com.oracle.truffle.sl.nodes.controlflow.*;
+import com.oracle.truffle.sl.nodes.expression.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Helper class used by the SL {@link Parser} to create nodes. The code is factored out of the
+ * automatically generated parser to keep the attributed grammar of SL small.
+ */
+public class SLNodeFactory {
+
+    /**
+     * Local variable names that are visible in the current block. Variables are not visible outside
+     * of their defining block, to prevent the usage of undefined variables. Because of that, we can
+     * decide during parsing if a name references a local variable or is a function name.
+     */
+    static class LexicalScope {
+        protected final LexicalScope outer;
+        protected final Map<String, FrameSlot> locals;
+
+        public LexicalScope(LexicalScope outer) {
+            this.outer = outer;
+            this.locals = new HashMap<>();
+            if (outer != null) {
+                locals.putAll(outer.locals);
+            }
+        }
+    }
+
+    /* State while parsing a source unit. */
+    private final SLContext context;
+    private final Source source;
+
+    /* State while parsing a function. */
+    private int functionStartPos;
+    private String functionName;
+    private int functionBodyStartPos; // includes parameter list
+    private int parameterCount;
+    private FrameDescriptor frameDescriptor;
+    private List<SLStatementNode> methodNodes;
+
+    /* State while parsing a block. */
+    private LexicalScope lexicalScope;
+
+    public SLNodeFactory(SLContext context, Source source) {
+        this.context = context;
+        this.source = source;
+    }
+
+    public void startFunction(Token nameToken, int bodyStartPos) {
+        assert functionStartPos == 0;
+        assert functionName == null;
+        assert functionBodyStartPos == 0;
+        assert parameterCount == 0;
+        assert frameDescriptor == null;
+        assert lexicalScope == null;
+
+        functionStartPos = nameToken.charPos;
+        functionName = nameToken.val;
+        functionBodyStartPos = bodyStartPos;
+        frameDescriptor = new FrameDescriptor();
+        methodNodes = new ArrayList<>();
+        startBlock();
+    }
+
+    public void addFormalParameter(Token nameToken) {
+        /*
+         * Method parameters are assigned to local variables at the beginning of the method. This
+         * ensures that accesses to parameters are specialized the same way as local variables are
+         * specialized.
+         */
+        final SourceSection src = srcFromToken(nameToken);
+        final SLReadArgumentNode readArg = new SLReadArgumentNode(src, parameterCount);
+        methodNodes.add(createAssignment(nameToken, readArg));
+        parameterCount++;
+    }
+
+    public void finishFunction(SLStatementNode bodyNode) {
+        methodNodes.add(bodyNode);
+        final int bodyEndPos = bodyNode.getSourceSection().getCharEndIndex();
+        final SourceSection functionSrc = source.createSection(functionName, functionStartPos, bodyEndPos - functionStartPos);
+        final SLStatementNode methodBlock = finishBlock(methodNodes, functionBodyStartPos, bodyEndPos - functionBodyStartPos);
+        assert lexicalScope == null : "Wrong scoping of blocks in parser";
+
+        final SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(functionSrc, methodBlock);
+        final SLRootNode rootNode = new SLRootNode(this.context, frameDescriptor, functionBodyNode, functionName);
+        rootNode.assignSourceSection(functionSrc);
+
+        context.getFunctionRegistry().register(functionName, rootNode);
+
+        functionStartPos = 0;
+        functionName = null;
+        functionBodyStartPos = 0;
+        parameterCount = 0;
+        frameDescriptor = null;
+        lexicalScope = null;
+    }
+
+    public void startBlock() {
+        lexicalScope = new LexicalScope(lexicalScope);
+    }
+
+    public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes, int startPos, int length) {
+        lexicalScope = lexicalScope.outer;
+
+        List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size());
+        flattenBlocks(bodyNodes, flattenedNodes);
+
+        final SourceSection src = source.createSection("block", startPos, length);
+        return new SLBlockNode(src, flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()]));
+    }
+
+    private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) {
+        for (Node n : bodyNodes) {
+            if (n instanceof SLBlockNode) {
+                flattenBlocks(n.getChildren(), flattenedNodes);
+            } else {
+                flattenedNodes.add((SLStatementNode) n);
+            }
+        }
+    }
+
+    /**
+     * Returns an {@link SLBreakNode} for the given token.
+     *
+     * @param breakToken The token containing the break node's info.
+     * @return A SLBreakNode for the given token.
+     */
+    public SLStatementNode createBreak(Token breakToken) {
+        final SLBreakNode breakNode = new SLBreakNode(srcFromToken(breakToken));
+        return breakNode;
+    }
+
+    /**
+     * Returns an {@link SLContinueNode} for the given token.
+     *
+     * @param continueToken The token containing the continue node's info.
+     * @return A SLContinueNode built using the given token.
+     */
+    public SLStatementNode createContinue(Token continueToken) {
+        final SLContinueNode continueNode = new SLContinueNode(srcFromToken(continueToken));
+        return continueNode;
+    }
+
+    /**
+     * Returns an {@link SLWhileNode} for the given parameters.
+     *
+     * @param whileToken The token containing the while node's info
+     * @param conditionNode The conditional node for this while loop
+     * @param bodyNode The body of the while loop
+     * @return A SLWhileNode built using the given parameters.
+     */
+    public SLStatementNode createWhile(Token whileToken, SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        final int start = whileToken.charPos;
+        final int end = bodyNode.getSourceSection().getCharEndIndex();
+        final SLWhileNode whileNode = new SLWhileNode(source.createSection(whileToken.val, start, end - start), conditionNode, bodyNode);
+        return whileNode;
+    }
+
+    /**
+     * Returns an {@link SLIfNode} for the given parameters.
+     *
+     * @param ifToken The token containing the if node's info
+     * @param conditionNode The condition node of this if statement
+     * @param thenPartNode The then part of the if
+     * @param elsePartNode The else part of the if
+     * @return An SLIfNode for the given parameters.
+     */
+    public SLStatementNode createIf(Token ifToken, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+        final int start = ifToken.charPos;
+        final int end = elsePartNode == null ? thenPartNode.getSourceSection().getCharEndIndex() : elsePartNode.getSourceSection().getCharEndIndex();
+        final SLIfNode ifNode = new SLIfNode(source.createSection(ifToken.val, start, end - start), conditionNode, thenPartNode, elsePartNode);
+        return ifNode;
+    }
+
+    /**
+     * Returns an {@link SLReturnNode} for the given parameters.
+     *
+     * @param t The token containing the return node's info
+     * @param valueNode The value of the return
+     * @return An SLReturnNode for the given parameters.
+     */
+    public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) {
+        final int start = t.charPos;
+        final int length = valueNode == null ? t.val.length() : valueNode.getSourceSection().getCharEndIndex() - start;
+        final SLReturnNode returnNode = new SLReturnNode(source.createSection(t.val, start, length), valueNode);
+        return returnNode;
+    }
+
+    /**
+     * Returns the corresponding subclass of {@link SLExpressionNode} for binary expressions.
+     * </br>These nodes are currently not instrumented.
+     *
+     * @param opToken The operator of the binary expression
+     * @param leftNode The left node of the expression
+     * @param rightNode The right node of the expression
+     * @return A subclass of SLExpressionNode using the given parameters based on the given opToken.
+     */
+    public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) {
+        int start = leftNode.getSourceSection().getCharIndex();
+        int length = rightNode.getSourceSection().getCharEndIndex() - start;
+        final SourceSection src = source.createSection(opToken.val, start, length);
+        switch (opToken.val) {
+            case "+":
+                return SLAddNodeGen.create(src, leftNode, rightNode);
+            case "*":
+                return SLMulNodeGen.create(src, leftNode, rightNode);
+            case "/":
+                return SLDivNodeGen.create(src, leftNode, rightNode);
+            case "-":
+                return SLSubNodeGen.create(src, leftNode, rightNode);
+            case "<":
+                return SLLessThanNodeGen.create(src, leftNode, rightNode);
+            case "<=":
+                return SLLessOrEqualNodeGen.create(src, leftNode, rightNode);
+            case ">":
+                return SLLogicalNotNodeGen.create(src, SLLessOrEqualNodeGen.create(null, leftNode, rightNode));
+            case ">=":
+                return SLLogicalNotNodeGen.create(src, SLLessThanNodeGen.create(null, leftNode, rightNode));
+            case "==":
+                return SLEqualNodeGen.create(src, leftNode, rightNode);
+            case "!=":
+                return SLLogicalNotNodeGen.create(src, SLEqualNodeGen.create(null, leftNode, rightNode));
+            case "&&":
+                return SLLogicalAndNodeGen.create(src, leftNode, rightNode);
+            case "||":
+                return SLLogicalOrNodeGen.create(src, leftNode, rightNode);
+            default:
+                throw new RuntimeException("unexpected operation: " + opToken.val);
+        }
+    }
+
+    /**
+     * Returns an {@link SLInvokeNode} for the given parameters.
+     *
+     * @param functionNode The function being called
+     * @param parameterNodes The parameters of the function call
+     * @param finalToken A token used to determine the end of the sourceSelection for this call
+     * @return An SLInvokeNode for the given parameters.
+     */
+    public SLExpressionNode createCall(SLExpressionNode functionNode, List<SLExpressionNode> parameterNodes, Token finalToken) {
+        final int startPos = functionNode.getSourceSection().getCharIndex();
+        final int endPos = finalToken.charPos + finalToken.val.length();
+        final SourceSection src = source.createSection(functionNode.getSourceSection().getIdentifier(), startPos, endPos - startPos);
+        return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
+    }
+
+    /**
+     * Returns an {@link SLWriteLocalVariableNode} for the given parameters.
+     *
+     * @param nameToken The name of the variable being assigned
+     * @param valueNode The value to be assigned
+     * @return An SLExpressionNode for the given parameters.
+     */
+    public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) {
+        FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val);
+        lexicalScope.locals.put(nameToken.val, frameSlot);
+        final int start = nameToken.charPos;
+        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
+        return SLWriteLocalVariableNodeGen.create(source.createSection("=", start, length), valueNode, frameSlot);
+    }
+
+    /**
+     * Returns a {@link SLReadLocalVariableNode} if this read is a local variable or a
+     * {@link SLFunctionLiteralNode} if this read is global. In Simple, the only global names are
+     * functions. </br> There is currently no instrumentation for this node.
+     *
+     * @param nameToken The name of the variable/function being read
+     * @return either:
+     *         <ul>
+     *         <li>A SLReadLocalVariableNode representing the local variable being read.</li>
+     *         <li>A SLFunctionLiteralNode representing the function definition</li>
+     *         </ul>
+     */
+    public SLExpressionNode createRead(Token nameToken) {
+        final FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val);
+        final SourceSection src = srcFromToken(nameToken);
+        if (frameSlot != null) {
+            /* Read of a local variable. */
+            return SLReadLocalVariableNodeGen.create(src, frameSlot);
+        } else {
+            /* Read of a global name. In our language, the only global names are functions. */
+            return new SLFunctionLiteralNode(src, context.getFunctionRegistry().lookup(nameToken.val));
+        }
+    }
+
+    public SLExpressionNode createStringLiteral(Token literalToken) {
+        /* Remove the trailing and ending " */
+        String literal = literalToken.val;
+        assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\"");
+        final SourceSection src = srcFromToken(literalToken);
+        literal = literal.substring(1, literal.length() - 1);
+
+        return new SLStringLiteralNode(src, literal);
+    }
+
+    public SLExpressionNode createNumericLiteral(Token literalToken) {
+        final SourceSection src = srcFromToken(literalToken);
+        try {
+            /* Try if the literal is small enough to fit into a long value. */
+            return new SLLongLiteralNode(src, Long.parseLong(literalToken.val));
+        } catch (NumberFormatException ex) {
+            /* Overflow of long value, so fall back to BigInteger. */
+            return new SLBigIntegerLiteralNode(src, new BigInteger(literalToken.val));
+        }
+    }
+
+    public SLExpressionNode createParenExpression(SLExpressionNode expressionNode, int start, int length) {
+        final SourceSection src = source.createSection("()", start, length);
+        return new SLParenExpressionNode(src, expressionNode);
+    }
+
+    /**
+     * Returns an {@link SLReadPropertyNode} for the given parameters.
+     *
+     * @param receiverNode The receiver of the property access
+     * @param nameToken The name of the property being accessed
+     * @return An SLExpressionNode for the given parameters.
+     */
+    public SLExpressionNode createReadProperty(SLExpressionNode receiverNode, Token nameToken) {
+        final int startPos = receiverNode.getSourceSection().getCharIndex();
+        final int endPos = nameToken.charPos + nameToken.val.length();
+        final SourceSection src = source.createSection(".", startPos, endPos - startPos);
+        return SLReadPropertyNode.create(src, receiverNode, nameToken.val);
+    }
+
+    /**
+     * Returns an {@link SLWritePropertyNode} for the given parameters.
+     *
+     * @param receiverNode The receiver object of the property assignment
+     * @param nameToken The name of the property being assigned
+     * @param valueNode The value to be assigned
+     * @return An SLExpressionNode for the given parameters.
+     */
+    public SLExpressionNode createWriteProperty(SLExpressionNode receiverNode, Token nameToken, SLExpressionNode valueNode) {
+        final int start = receiverNode.getSourceSection().getCharIndex();
+        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
+        SourceSection src = source.createSection("=", start, length);
+        return SLWritePropertyNode.create(src, receiverNode, nameToken.val, valueNode);
+    }
+
+    /**
+     * Creates source description of a single token.
+     */
+    private SourceSection srcFromToken(Token token) {
+        return source.createSection(token.val, token.charPos, token.val.length());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,515 @@
+/*-------------------------------------------------------------------------
+Compiler Generator Coco/R,
+Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
+extended by M. Loeberbauer & A. Woess, Univ. of Linz
+ported from C# to Java by Wolfgang Ahorner
+with improvements by Pat Terry, Rhodes University
+
+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, 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.
+
+As an exception, it is allowed to write an extension of Coco/R that is
+used as a plugin in non-free software.
+
+If not otherwise stated, any source code generated by Coco/R (other than 
+Coco/R itself) does not fall under the GNU General Public License.
+------------------------------------------------------------------------*/
+-->begin
+package com.oracle.truffle.sl.parser;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+-->declarations
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+-->initialization
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+-->casing
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+-->casing2
+            NextCh();
+        }
+    }
+
+-->comments
+
+    void CheckLiteral() {
+        String val = t.val;
+-->casing3
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' || 
+-->scan1
+        ) NextCh();
+-->scan2
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+-->scan3
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+    // The following methods are used for the CLNG Editor and will be called with java.Reflection.
+    // If the editor won't be used these 3 functions are obsolete,
+    // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly
+// anymore.
+
+    // get the offset of the next Token
+    public int getPeekTokenOffset() {
+        return pt.pos;
+    }
+
+    // get the String value of the Token
+    public String getPeekTokenVal() {
+        return pt.val;
+    }
+
+    // get the Kind value of the Token
+    public int getPeekTokenKind() {
+        return pt.kind;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,654 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// The content of this file is automatically generated. DO NOT EDIT.
+
+package com.oracle.truffle.sl.parser;
+
+import java.io.*;
+import java.util.*;
+
+// Checkstyle: stop
+// @formatter:off
+class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+	static final int maxT = 31;
+	static final int noSym = 31;
+
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+		for (int i = 65; i <= 90; ++i) start.set(i, 1);
+		for (int i = 97; i <= 122; ++i) start.set(i, 1);
+		for (int i = 49; i <= 57; ++i) start.set(i, 4);
+		start.set(34, 2);
+		start.set(48, 5);
+		start.set(40, 6);
+		start.set(44, 7);
+		start.set(41, 8);
+		start.set(123, 9);
+		start.set(125, 10);
+		start.set(59, 11);
+		start.set(124, 12);
+		start.set(38, 14);
+		start.set(60, 26);
+		start.set(62, 27);
+		start.set(61, 28);
+		start.set(33, 19);
+		start.set(43, 21);
+		start.set(45, 22);
+		start.set(42, 23);
+		start.set(47, 24);
+		start.set(46, 25);
+		start.set(Buffer.EOF, -1);
+		literals.put("function", new Integer(4));
+		literals.put("break", new Integer(10));
+		literals.put("continue", new Integer(12));
+		literals.put("while", new Integer(13));
+		literals.put("if", new Integer(14));
+		literals.put("else", new Integer(15));
+		literals.put("return", new Integer(16));
+
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+			tval[tlen++] = (char)ch;
+
+            NextCh();
+        }
+    }
+
+
+	boolean Comment0() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '/') {
+			NextCh();
+			for(;;) {
+				if (ch == 10) {
+					level--;
+					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+					NextCh();
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
+
+	boolean Comment1() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '*') {
+			NextCh();
+			for(;;) {
+				if (ch == '*') {
+					NextCh();
+					if (ch == '/') {
+						level--;
+						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+						NextCh();
+					}
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
+
+
+    void CheckLiteral() {
+        String val = t.val;
+
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' ||
+			ch >= 9 && ch <= 10 || ch == 13
+        ) NextCh();
+		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+				case 1:
+					recEnd = pos; recKind = 1;
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
+				case 2:
+					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
+					else if (ch == '"') {AddCh(); state = 3; break;}
+					else {state = 0; break;}
+				case 3:
+					{t.kind = 2; break loop;}
+				case 4:
+					recEnd = pos; recKind = 3;
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
+					else {t.kind = 3; break loop;}
+				case 5:
+					{t.kind = 3; break loop;}
+				case 6:
+					{t.kind = 5; break loop;}
+				case 7:
+					{t.kind = 6; break loop;}
+				case 8:
+					{t.kind = 7; break loop;}
+				case 9:
+					{t.kind = 8; break loop;}
+				case 10:
+					{t.kind = 9; break loop;}
+				case 11:
+					{t.kind = 11; break loop;}
+				case 12:
+					if (ch == '|') {AddCh(); state = 13; break;}
+					else {state = 0; break;}
+				case 13:
+					{t.kind = 17; break loop;}
+				case 14:
+					if (ch == '&') {AddCh(); state = 15; break;}
+					else {state = 0; break;}
+				case 15:
+					{t.kind = 18; break loop;}
+				case 16:
+					{t.kind = 20; break loop;}
+				case 17:
+					{t.kind = 22; break loop;}
+				case 18:
+					{t.kind = 23; break loop;}
+				case 19:
+					if (ch == '=') {AddCh(); state = 20; break;}
+					else {state = 0; break;}
+				case 20:
+					{t.kind = 24; break loop;}
+				case 21:
+					{t.kind = 25; break loop;}
+				case 22:
+					{t.kind = 26; break loop;}
+				case 23:
+					{t.kind = 27; break loop;}
+				case 24:
+					{t.kind = 28; break loop;}
+				case 25:
+					{t.kind = 30; break loop;}
+				case 26:
+					recEnd = pos; recKind = 19;
+					if (ch == '=') {AddCh(); state = 16; break;}
+					else {t.kind = 19; break loop;}
+				case 27:
+					recEnd = pos; recKind = 21;
+					if (ch == '=') {AddCh(); state = 17; break;}
+					else {t.kind = 21; break loop;}
+				case 28:
+					recEnd = pos; recKind = 29;
+					if (ch == '=') {AddCh(); state = 18; break;}
+					else {t.kind = 29; break loop;}
+
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+    // The following methods are used for the CLNG Editor and will be called with java.Reflection.
+    // If the editor won't be used these 3 functions are obsolete,
+    // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly
+// anymore.
+
+    // get the offset of the next Token
+    public int getPeekTokenOffset() {
+        return pt.pos;
+    }
+
+    // get the String value of the Token
+    public String getPeekTokenVal() {
+        return pt.val;
+    }
+
+    // get the Kind value of the Token
+    public int getPeekTokenKind() {
+        return pt.kind;
+    }
+
+} // end Scanner
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This is the grammar of SL that is used to automatically generate the Parser.java and Scanner.java
+ * files. You can download the parser generator Coco/R from http://ssw.jku.at/coco/. Then run
+ * "java -jar Coco.jar SimpleLanguage.atg"
+ */
+
+COMPILER SimpleLanguage
+
+CHARACTERS
+
+letter = 'A'..'Z' + 'a'..'z'.
+nonZeroDigit = "123456789".
+digit = "0123456789".
+cr = '\r'.
+lf = '\n'.
+tab = '\t'.
+stringChar = ANY - "\"" - '\\' - cr - lf.
+
+TOKENS
+
+identifier = letter {letter | digit}.
+stringLiteral = "\"" { stringChar } "\"".
+numericLiteral = "0" | nonZeroDigit { digit }.
+
+PRAGMAS
+
+COMMENTS FROM "/*" TO "*/"
+COMMENTS FROM "//" TO lf
+IGNORE cr + lf + tab
+
+PRODUCTIONS
+
+
+SimpleLanguage
+=
+Function
+{
+     Function
+}
+.
+
+
+Function
+=
+"function"
+identifier                                      (. Token identifierToken = t; .)
+"("                                             (. int bodyStartPos = t.charPos; .)
+                                                (. factory.startFunction(identifierToken, bodyStartPos); .)
+[
+    identifier                                  (. factory.addFormalParameter(t); .)
+    {
+        ","
+        identifier                              (. factory.addFormalParameter(t); .)
+    }
+]
+")"
+Block<out SLStatementNode body, false>          (. factory.finishFunction(body); .)
+.
+
+
+
+Block<out SLStatementNode result, boolean inLoop>
+=                                               (. factory.startBlock();
+                                                   List<SLStatementNode> body = new ArrayList<>(); .)
+"{"                                             (. int start = t.charPos; .)
+{
+    Statement<out SLStatementNode s, inLoop>    (. body.add(s); .)
+}
+"}"                                             (. int length = (t.charPos + t.val.length()) - start; .)
+                                                (. result = factory.finishBlock(body, start, length); .)
+.
+
+
+Statement<out SLStatementNode result, boolean inLoop>
+=                                               (. result = null; .)
+(
+    WhileStatement<out result>
+|
+    "break"                                     (. if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } .)
+    ";"
+|
+    "continue"                                  (. if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } .)
+    ";"
+|
+    IfStatement<out result, inLoop>
+|
+    ReturnStatement<out result>
+|
+    Expression<out result> ";"
+)
+.
+
+
+WhileStatement<out SLStatementNode result>
+=
+"while"                                         (. Token whileToken = t; .)
+"("
+Expression<out SLExpressionNode condition>
+")"
+Block<out SLStatementNode body, true>           (. result = factory.createWhile(whileToken, condition, body); .)
+.
+
+
+IfStatement<out SLStatementNode result, boolean inLoop>
+=
+"if"                                            (. Token ifToken = t; .)
+"("
+Expression<out SLExpressionNode condition>
+")"
+Block<out SLStatementNode thenPart, inLoop>     (. SLStatementNode elsePart = null; .)
+[
+    "else"
+    Block<out elsePart, inLoop>
+]                                               (. result = factory.createIf(ifToken, condition, thenPart, elsePart); .)
+.
+
+
+ReturnStatement<out SLStatementNode result>
+=
+"return"                                        (. Token returnToken = t;
+                                                   SLExpressionNode value = null; .)
+[
+    Expression<out value>
+]                                               (. result = factory.createReturn(returnToken, value); .)
+";"
+.
+
+
+Expression<out SLExpressionNode result>
+=
+LogicTerm<out result>
+{
+    "||"                                        (. Token op = t; .)
+    LogicTerm<out SLExpressionNode right>       (. result = factory.createBinary(op, result, right); .)
+}
+.
+
+
+LogicTerm<out SLExpressionNode result>
+=
+LogicFactor<out result>
+{
+    "&&"                                        (. Token op = t; .)
+    LogicFactor<out SLExpressionNode right>     (. result = factory.createBinary(op, result, right); .)
+}
+.
+
+
+LogicFactor<out SLExpressionNode result>
+=
+Arithmetic<out result>
+[
+    ("<" | "<=" | ">" | ">=" | "==" | "!=" )    (. Token op = t; .)
+    Arithmetic<out SLExpressionNode right>      (.  result = factory.createBinary(op, result, right); .)
+]
+.
+
+
+Arithmetic<out SLExpressionNode result>
+=
+Term<out result>
+{
+    ("+" | "-")                                 (. Token op = t; .)
+    Term<out SLExpressionNode right>            (. result = factory.createBinary(op, result, right); .)
+}
+.
+
+
+Term<out SLExpressionNode result>
+=
+Factor<out result>
+{
+    ("*" | "/")                                 (. Token op = t; .)
+    Factor<out SLExpressionNode right>          (. result = factory.createBinary(op, result, right); .)
+}
+.
+
+
+Factor<out SLExpressionNode result>
+=                                               (. result = null; .)
+(
+    identifier
+    (
+        MemberExpression<out result, null, null, t>
+    |
+                                                (. result = factory.createRead(t); .)
+    )
+|
+    stringLiteral                               (. result = factory.createStringLiteral(t); .)
+|
+    numericLiteral                              (. result = factory.createNumericLiteral(t); .)
+|
+    "("                                         (. int start = t.charPos; .)
+    Expression<out result>                      (. SLExpressionNode expr = result; .)
+    ")"                                         (. int length = (t.charPos + t.val.length()) - start; .)
+                                                (. result = factory.createParenExpression(expr, start, length); .)
+)
+.
+
+
+MemberExpression<out SLExpressionNode result, SLExpressionNode r, SLExpressionNode assignmentReceiver, Token assignmentName>
+=                                               (. result = null;
+                                                   SLExpressionNode receiver = r;
+                                                   Token nestedAssignmentName = null; .)
+(
+    "("                                         (. List<SLExpressionNode> parameters = new ArrayList<>();
+                                                   SLExpressionNode parameter;
+                                                   if (receiver == null) {
+                                                       receiver = factory.createRead(assignmentName); 
+                                                   } .)
+    [
+        Expression<out parameter>               (. parameters.add(parameter); .)
+        {
+            ","
+            Expression<out parameter>           (. parameters.add(parameter); .)
+        }
+    ]
+    ")"                                         (. Token finalToken = t; .)
+                                                (. result = factory.createCall(receiver, parameters, finalToken); .)
+|
+    "="
+    Expression<out SLExpressionNode value>      (. if (assignmentName == null) {
+                                                       SemErr("invalid assignment target");
+                                                   } else if (assignmentReceiver == null) {
+                                                       result = factory.createAssignment(assignmentName, value);
+                                                   } else {
+                                                       result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
+                                                   } .)
+|
+    "."                                         (. if (receiver == null) {
+                                                       receiver = factory.createRead(assignmentName); 
+                                                   } .)
+    identifier
+                                                (. result = factory.createReadProperty(receiver, t); .)
+                                                (. nestedAssignmentName = t; .)
+)
+[
+    MemberExpression<out result, result, receiver, nestedAssignmentName>
+]
+.
+
+
+END SimpleLanguage.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import java.io.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.object.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.builtins.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.local.*;
+import com.oracle.truffle.sl.parser.*;
+
+/**
+ * The run-time state of SL during execution. One context is instantiated before any source code is
+ * parsed, and this context is passed around to all methods that need access to it. For example, the
+ * context is used during {@link SLNodeFactory parsing} and by {@link SLBuiltinNode#getContext()
+ * builtin functions}.
+ * <p>
+ * It would be an error to have two different context instances during the execution of one script.
+ * However, if two separate scripts run in one Java VM at the same time, they have a different
+ * context. Therefore, the context is not a singleton.
+ */
+public final class SLContext extends ExecutionContext {
+    private static final Layout LAYOUT = Layout.createLayout();
+
+    private final BufferedReader input;
+    private final PrintWriter output;
+    private final SLFunctionRegistry functionRegistry;
+    private final Shape emptyShape;
+
+    public SLContext(BufferedReader input, PrintWriter output) {
+        this.input = input;
+        this.output = output;
+        this.functionRegistry = new SLFunctionRegistry();
+        installBuiltins();
+
+        this.emptyShape = LAYOUT.createShape(new ObjectType());
+    }
+
+    /**
+     * Returns the default input, i.e., the source for the {@link SLReadlnBuiltin}. To allow unit
+     * testing, we do not use {@link System#in} directly.
+     */
+    public BufferedReader getInput() {
+        return input;
+    }
+
+    /**
+     * The default default, i.e., the output for the {@link SLPrintlnBuiltin}. To allow unit
+     * testing, we do not use {@link System#out} directly.
+     */
+    public PrintWriter getOutput() {
+        return output;
+    }
+
+    /**
+     * Returns the registry of all functions that are currently defined.
+     */
+    public SLFunctionRegistry getFunctionRegistry() {
+        return functionRegistry;
+    }
+
+    /**
+     * Adds all builtin functions to the {@link SLFunctionRegistry}. This method lists all
+     * {@link SLBuiltinNode builtin implementation classes}.
+     */
+    private void installBuiltins() {
+        installBuiltin(SLReadlnBuiltinFactory.getInstance());
+        installBuiltin(SLPrintlnBuiltinFactory.getInstance());
+        installBuiltin(SLNanoTimeBuiltinFactory.getInstance());
+        installBuiltin(SLDefineFunctionBuiltinFactory.getInstance());
+        installBuiltin(SLStackTraceBuiltinFactory.getInstance());
+        installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
+        installBuiltin(SLAssertTrueBuiltinFactory.getInstance());
+        installBuiltin(SLAssertFalseBuiltinFactory.getInstance());
+        installBuiltin(SLNewObjectBuiltinFactory.getInstance());
+    }
+
+    public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {
+        /*
+         * The builtin node factory is a class that is automatically generated by the Truffle DSL.
+         * The signature returned by the factory reflects the signature of the @Specialization
+         * methods in the builtin classes.
+         */
+        int argumentCount = factory.getExecutionSignature().size();
+        SLExpressionNode[] argumentNodes = new SLExpressionNode[argumentCount];
+        /*
+         * Builtin functions are like normal functions, i.e., the arguments are passed in as an
+         * Object[] array encapsulated in SLArguments. A SLReadArgumentNode extracts a parameter
+         * from this array.
+         */
+        for (int i = 0; i < argumentCount; i++) {
+            argumentNodes[i] = new SLReadArgumentNode(null, i);
+        }
+        /* Instantiate the builtin node. This node performs the actual functionality. */
+        SLBuiltinNode builtinBodyNode = factory.createNode(argumentNodes, this);
+        /* The name of the builtin function is specified via an annotation on the node class. */
+        String name = lookupNodeInfo(builtinBodyNode.getClass()).shortName();
+        /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */
+        SLRootNode rootNode = new SLRootNode(this, new FrameDescriptor(), builtinBodyNode, name);
+
+        /* Register the builtin function in our function registry. */
+        getFunctionRegistry().register(name, rootNode);
+    }
+
+    public static NodeInfo lookupNodeInfo(Class<?> clazz) {
+        if (clazz == null) {
+            return null;
+        }
+        NodeInfo info = clazz.getAnnotation(NodeInfo.class);
+        if (info != null) {
+            return info;
+        } else {
+            return lookupNodeInfo(clazz.getSuperclass());
+        }
+    }
+
+    /**
+     * Evaluate a source, causing any definitions to be registered (but not executed).
+     *
+     * @param source The {@link Source} to parse.
+     */
+    public void evalSource(Source source) {
+        Parser.parseSL(this, source);
+    }
+
+    public DynamicObject createObject() {
+        return LAYOUT.newInstance(emptyShape);
+    }
+
+    public static boolean isSLObject(Object value) {
+        return LAYOUT.getType().isInstance(value);
+    }
+
+    public static DynamicObject castSLObject(Object value) {
+        return LAYOUT.getType().cast(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.interop.*;
+import com.oracle.truffle.api.utilities.*;
+
+/**
+ * Represents a SL function. On the Truffle level, a callable element is represented by a
+ * {@link RootCallTarget call target}. This class encapsulates a call target, and adds version
+ * support: functions in SL can be redefined, i.e. changed at run time. When a function is
+ * redefined, the call target managed by this function object is changed (and {@link #callTarget} is
+ * therefore not a final field).
+ * <p>
+ * Function redefinition is expected to be rare, therefore optimized call nodes want to speculate
+ * that the call target is stable. This is possible with the help of a Truffle {@link Assumption}: a
+ * call node can keep the call target returned by {@link #getCallTarget()} cached until the
+ * assumption returned by {@link #getCallTargetStable()} is valid.
+ * <p>
+ * The {@link #callTarget} can be {@code null}. To ensure that only one {@link SLFunction} instance
+ * per name exists, the {@link SLFunctionRegistry} creates an instance also when performing name
+ * lookup. A function that has been looked up, i.e., used, but not defined, has no call target.
+ */
+public final class SLFunction implements TruffleObject {
+
+    /** The name of the function. */
+    private final String name;
+
+    /** The current implementation of this function. */
+    private RootCallTarget callTarget;
+
+    /**
+     * Manages the assumption that the {@link #callTarget} is stable. We use the utility class
+     * {@link CyclicAssumption}, which automatically creates a new {@link Assumption} when the old
+     * one gets invalidated.
+     */
+    private final CyclicAssumption callTargetStable;
+
+    protected SLFunction(String name) {
+        this.name = name;
+        this.callTargetStable = new CyclicAssumption(name);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    protected void setCallTarget(RootCallTarget callTarget) {
+        this.callTarget = callTarget;
+        /*
+         * We have a new call target. Invalidate all code that speculated that the old call target
+         * was stable.
+         */
+        callTargetStable.invalidate();
+    }
+
+    public RootCallTarget getCallTarget() {
+        return callTarget;
+    }
+
+    public Assumption getCallTargetStable() {
+        return callTargetStable.getAssumption();
+    }
+
+    /**
+     * This method is, e.g., called when using a function literal in a string concatenation. So
+     * changing it has an effect on SL programs.
+     */
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    /**
+     * In case you want some of your objects to co-operate with other languages, you need to make
+     * them implement {@link TruffleObject} and provide additional {@link SLFunctionForeignAccess
+     * foreign access implementation}.
+     */
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return SLFunctionForeignAccess.INSTANCE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionForeignAccess.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.sl.nodes.call.SLDispatchNode;
+import com.oracle.truffle.sl.nodes.call.SLDispatchNodeGen;
+import java.math.BigInteger;
+import java.util.List;
+
+/**
+ * Implementation of foreign access for {@link SLFunction}.
+ */
+final class SLFunctionForeignAccess implements ForeignAccess.Factory {
+    public static final ForeignAccess INSTANCE = ForeignAccess.create(new SLFunctionForeignAccess());
+
+    private SLFunctionForeignAccess() {
+    }
+
+    @Override
+    public boolean canHandle(TruffleObject o) {
+        return o instanceof SLFunction;
+    }
+
+    @Override
+    public CallTarget accessMessage(Message tree) {
+        if (Message.createExecute(0).equals(tree)) {
+            return Truffle.getRuntime().createCallTarget(new SLForeignCallerRootNode());
+        } else if (Message.IS_NULL.equals(tree)) {
+            return Truffle.getRuntime().createCallTarget(new SLForeignNullCheckNode());
+        } else {
+            throw new IllegalArgumentException(tree.toString() + " not supported");
+        }
+    }
+
+    private static class SLForeignCallerRootNode extends RootNode {
+        @Child private SLDispatchNode dispatch = SLDispatchNodeGen.create();
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            SLFunction function = (SLFunction) ForeignAccess.getReceiver(frame);
+            // the calling convention of interop passes the receiver of a
+            // function call (the this object)
+            // as an implicit 1st argument; we need to ignore this argument for SL
+            List<Object> args = ForeignAccess.getArguments(frame);
+            Object[] arr = args.subList(1, args.size()).toArray();
+            for (int i = 0; i < arr.length; i++) {
+                Object a = arr[i];
+                if (a instanceof Long) {
+                    continue;
+                }
+                if (a instanceof BigInteger) {
+                    continue;
+                }
+                if (a instanceof Number) {
+                    arr[i] = ((Number) a).longValue();
+                }
+            }
+            return dispatch.executeDispatch(frame, function, arr);
+        }
+
+    }
+
+    private static class SLForeignNullCheckNode extends RootNode {
+        @Override
+        public Object execute(VirtualFrame frame) {
+            Object receiver = ForeignAccess.getReceiver(frame);
+            return SLNull.SINGLETON == receiver;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * Manages the mapping from function names to {@link SLFunction function objects}.
+ */
+public final class SLFunctionRegistry {
+
+    private final Map<String, SLFunction> functions = new HashMap<>();
+
+    /**
+     * Returns the canonical {@link SLFunction} object for the given name. If it does not exist yet,
+     * it is created.
+     */
+    public SLFunction lookup(String name) {
+        SLFunction result = functions.get(name);
+        if (result == null) {
+            result = new SLFunction(name);
+            functions.put(name, result);
+        }
+        return result;
+    }
+
+    /**
+     * Associates the {@link SLFunction} with the given name with the given implementation root
+     * node. If the function did not exist before, it defines the function. If the function existed
+     * before, it redefines the function and the old implementation is discarded.
+     */
+    public void register(String name, SLRootNode rootNode) {
+        SLFunction function = lookup(name);
+        RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
+        function.setCallTarget(callTarget);
+    }
+
+    /**
+     * Returns the sorted list of all functions, for printing purposes only.
+     */
+    public List<SLFunction> getFunctions() {
+        List<SLFunction> result = new ArrayList<>(functions.values());
+        Collections.sort(result, new Comparator<SLFunction>() {
+            public int compare(SLFunction f1, SLFunction f2) {
+                return f1.toString().compareTo(f2.toString());
+            }
+        });
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+
+/**
+ * The SL type for a {@code null} (i.e., undefined) value. In Truffle, it is generally discouraged
+ * to use the Java {@code null} value to represent the guest language {@code null} value. It is not
+ * possible to specialize on Java {@code null} (since you cannot ask it for the Java class), and
+ * there is always the danger of a spurious {@link NullPointerException}. Representing the guest
+ * language {@code null} as a singleton, as in {@link #SINGLETON this class}, is the recommended
+ * practice.
+ */
+public final class SLNull implements TruffleObject {
+
+    /**
+     * The canonical value to represent {@code null} in SL.
+     */
+    public static final SLNull SINGLETON = new SLNull();
+
+    /**
+     * Disallow instantiation from outside to ensure that the {@link #SINGLETON} is the only
+     * instance.
+     */
+    private SLNull() {
+    }
+
+    /**
+     * This method is, e.g., called when using the {@code null} value in a string concatenation. So
+     * changing it has an effect on SL programs.
+     */
+    @Override
+    public String toString() {
+        return "null";
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return SLFunctionForeignAccess.INSTANCE;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/EagerStackTraceDecorator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import org.junit.runner.notification.*;
+
+class EagerStackTraceDecorator extends TruffleJUnitRunListenerDecorator {
+
+    public EagerStackTraceDecorator(TruffleJUnitRunListener l) {
+        super(l);
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        super.testFailed(failure);
+        failure.getException().printStackTrace(getWriter());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/GCAfterTestDecorator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import org.junit.runner.*;
+
+final class GCAfterTestDecorator extends TruffleJUnitRunListenerDecorator {
+
+    public GCAfterTestDecorator(TruffleJUnitRunListener l) {
+        super(l);
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        System.gc();
+        super.testFinished(description);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TimingDecorator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import org.junit.runner.*;
+
+/**
+ * Timing support for JUnit test runs.
+ */
+class TimingDecorator extends TruffleJUnitRunListenerDecorator {
+
+    private long startTime;
+    private long classStartTime;
+
+    public TimingDecorator(TruffleJUnitRunListener l) {
+        super(l);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        classStartTime = System.nanoTime();
+        super.testClassStarted(clazz);
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        long totalTime = System.nanoTime() - classStartTime;
+        super.testClassFinished(clazz);
+        getWriter().print(' ' + valueToString(totalTime));
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        startTime = System.nanoTime();
+        super.testStarted(description);
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        long totalTime = System.nanoTime() - startTime;
+        super.testFinished(description);
+        getWriter().print(" " + valueToString(totalTime));
+    }
+
+    private static String valueToString(long value) {
+        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitCore.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.nio.charset.Charset;
+import java.nio.file.*;
+import java.util.*;
+
+import junit.runner.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+import org.junit.runners.*;
+import org.junit.runners.model.*;
+
+final class TruffleJUnitCore {
+
+    /**
+     * Run the tests contained in the classes named in the <code>args</code>. A single test method
+     * can be specified by adding #method after the class name. Only a single test can be run in
+     * this way. If all tests run successfully, exit with a status of 0. Otherwise exit with a
+     * status of 1. Write feedback while tests are running and write stack traces for all failed
+     * tests after the tests all complete.
+     *
+     * @param args names of classes in which to find tests to run
+     */
+    public static void main(String... args) {
+        JUnitSystem system = new RealSystem();
+        JUnitCore junitCore = new JUnitCore();
+        system.out().println("TruffleJUnitCore");
+        system.out().println("JUnit version " + Version.id());
+        List<Class<?>> classes = new ArrayList<>();
+        String methodName = null;
+        List<Failure> missingClasses = new ArrayList<>();
+        boolean verbose = false;
+        boolean enableTiming = false;
+        boolean failFast = false;
+        boolean eagerStackTrace = false;
+        boolean gcAfterTest = false;
+
+        String[] expandedArgs = expandArgs(args);
+        for (int i = 0; i < expandedArgs.length; i++) {
+            String each = expandedArgs[i];
+            if (each.charAt(0) == '-') {
+                // command line arguments
+                if (each.contentEquals("-JUnitVerbose")) {
+                    verbose = true;
+                } else if (each.contentEquals("-JUnitFailFast")) {
+                    failFast = true;
+                } else if (each.contentEquals("-JUnitEnableTiming")) {
+                    enableTiming = true;
+                } else if (each.contentEquals("-JUnitEagerStackTrace")) {
+                    eagerStackTrace = true;
+                } else if (each.contentEquals("-JUnitGCAfterTest")) {
+                    gcAfterTest = true;
+                } else {
+                    system.out().println("Unknown command line argument: " + each);
+                }
+
+            } else {
+                /*
+                 * Entries of the form class#method are handled specially. Only one can be specified
+                 * on the command line as there's no obvious way to build a runner for multiple
+                 * ones.
+                 */
+                if (methodName != null) {
+                    system.out().println("Only a single class and method can be specified: " + each);
+                    System.exit(1);
+                } else if (each.contains("#")) {
+                    String[] pair = each.split("#");
+                    if (pair.length != 2) {
+                        system.out().println("Malformed class and method request: " + each);
+                        System.exit(1);
+                    } else if (classes.size() != 0) {
+                        system.out().println("Only a single class and method can be specified: " + each);
+                        System.exit(1);
+                    } else {
+                        methodName = pair[1];
+                        each = pair[0];
+                    }
+                }
+                try {
+                    Class<?> cls = Class.forName(each, false, TruffleJUnitCore.class.getClassLoader());
+                    if ((cls.getModifiers() & Modifier.ABSTRACT) == 0) {
+                        classes.add(cls);
+                    }
+                } catch (ClassNotFoundException e) {
+                    system.out().println("Could not find class: " + each);
+                    Description description = Description.createSuiteDescription(each);
+                    Failure failure = new Failure(description, e);
+                    missingClasses.add(failure);
+                }
+            }
+        }
+        final TruffleTextListener textListener;
+        if (!verbose) {
+            textListener = new TruffleTextListener(system);
+        } else {
+            textListener = new TruffleVerboseTextListener(system);
+        }
+        TruffleJUnitRunListener listener = textListener;
+        if (enableTiming) {
+            listener = new TimingDecorator(listener);
+        }
+        if (eagerStackTrace) {
+            listener = new EagerStackTraceDecorator(listener);
+        }
+        if (gcAfterTest) {
+            listener = new GCAfterTestDecorator(listener);
+        }
+        junitCore.addListener(TruffleTextListener.createRunListener(listener));
+        Request request;
+        if (methodName == null) {
+            request = Request.classes(classes.toArray(new Class[0]));
+            if (failFast) {
+                Runner runner = request.getRunner();
+                if (runner instanceof ParentRunner) {
+                    ParentRunner<?> parentRunner = (ParentRunner<?>) runner;
+                    parentRunner.setScheduler(new RunnerScheduler() {
+                        public void schedule(Runnable childStatement) {
+                            if (textListener.getLastFailure() == null) {
+                                childStatement.run();
+                            }
+                        }
+
+                        public void finished() {
+                        }
+                    });
+                } else {
+                    system.out().println("Unexpected Runner subclass " + runner.getClass().getName() + " - fail fast not supported");
+                }
+            }
+        } else {
+            if (failFast) {
+                system.out().println("Single method selected - fail fast not supported");
+            }
+            request = Request.method(classes.get(0), methodName);
+        }
+        Result result = junitCore.run(request);
+        for (Failure each : missingClasses) {
+            result.getFailures().add(each);
+        }
+        System.exit(result.wasSuccessful() ? 0 : 1);
+    }
+
+    /**
+     * Gets the command line for the current process.
+     *
+     * @return the command line arguments for the current process or {@code null} if they are not
+     *         available
+     */
+    public static List<String> getProcessCommandLine() {
+        String processArgsFile = System.getenv().get("MX_SUBPROCESS_COMMAND_FILE");
+        if (processArgsFile != null) {
+            try {
+                return Files.readAllLines(new File(processArgsFile).toPath(), Charset.forName("UTF-8"));
+            } catch (IOException e) {
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Expand any arguments starting with @ and return the resulting argument array.
+     *
+     * @param args
+     * @return the expanded argument array
+     */
+    private static String[] expandArgs(String[] args) {
+        List<String> result = null;
+        for (int i = 0; i < args.length; i++) {
+            String arg = args[i];
+            if (arg.length() > 0 && arg.charAt(0) == '@') {
+                if (result == null) {
+                    result = new ArrayList<>();
+                    for (int j = 0; j < i; j++) {
+                        result.add(args[j]);
+                    }
+                    expandArg(arg.substring(1), result);
+                }
+            } else if (result != null) {
+                result.add(arg);
+            }
+        }
+        return result != null ? result.toArray(new String[0]) : args;
+    }
+
+    /**
+     * Add each line from {@code filename} to the list {@code args}.
+     *
+     * @param filename
+     * @param args
+     */
+    private static void expandArg(String filename, List<String> args) {
+        BufferedReader br = null;
+        try {
+            br = new BufferedReader(new FileReader(filename));
+
+            String buf;
+            while ((buf = br.readLine()) != null) {
+                args.add(buf);
+            }
+            br.close();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+            System.exit(2);
+        } finally {
+            try {
+                if (br != null) {
+                    br.close();
+                }
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+                System.exit(3);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+interface TruffleJUnitRunListener {
+
+    /**
+     * Called before any tests have been run.
+     *
+     * @param description describes the tests to be run
+     */
+    void testRunStarted(Description description);
+
+    /**
+     * Called when all tests have finished.
+     *
+     * @param result the summary of the test run, including all the tests that failed
+     */
+    void testRunFinished(Result result);
+
+    /**
+     * Called when a test class is about to be started.
+     *
+     * @param clazz the test class
+     */
+    void testClassStarted(Class<?> clazz);
+
+    /**
+     * Called when all tests of a test class have finished.
+     *
+     * @param clazz the test class
+     */
+    void testClassFinished(Class<?> clazz);
+
+    /**
+     * Called when an atomic test is about to be started. This is also called for ignored tests.
+     *
+     * @param description the description of the test that is about to be run (generally a class and
+     *            method name)
+     */
+    void testStarted(Description description);
+
+    /**
+     * Called when an atomic test has finished, whether the test succeeds, fails or is ignored.
+     *
+     * @param description the description of the test that just ran
+     */
+    void testFinished(Description description);
+
+    /**
+     * Called when an atomic test fails.
+     *
+     * @param failure describes the test that failed and the exception that was thrown
+     */
+    void testFailed(Failure failure);
+
+    /**
+     * Called when a test will not be run, generally because a test method is annotated with
+     * {@link org.junit.Ignore}.
+     *
+     * @param description describes the test that will not be run
+     */
+    void testIgnored(Description description);
+
+    /**
+     * Called when an atomic test succeeds.
+     *
+     * @param description describes the test that will not be run
+     */
+    void testSucceeded(Description description);
+
+    /**
+     * Called when an atomic test flags that it assumes a condition that is false.
+     *
+     * @param failure describes the test that failed and the {@link AssumptionViolatedException}
+     *            that was thrown
+     */
+    void testAssumptionFailure(Failure failure);
+
+    /**
+     * Called after {@link #testClassFinished(Class)}.
+     */
+    void testClassFinishedDelimiter();
+
+    /**
+     * Called after {@link #testClassStarted(Class)}.
+     */
+    void testClassStartedDelimiter();
+
+    /**
+     * Called after {@link #testStarted(Description)}.
+     */
+    void testStartedDelimiter();
+
+    /**
+     * Called after {@link #testFailed(Failure)}.
+     */
+    void testFinishedDelimiter();
+
+    PrintStream getWriter();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleJUnitRunListenerDecorator.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import java.io.*;
+
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+class TruffleJUnitRunListenerDecorator implements TruffleJUnitRunListener {
+
+    private final TruffleJUnitRunListener l;
+
+    public TruffleJUnitRunListenerDecorator(TruffleJUnitRunListener l) {
+        this.l = l;
+    }
+
+    @Override
+    public void testRunStarted(Description description) {
+        l.testRunStarted(description);
+    }
+
+    @Override
+    public void testRunFinished(Result result) {
+        l.testRunFinished(result);
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+        l.testAssumptionFailure(failure);
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        l.testIgnored(description);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        l.testClassStarted(clazz);
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        l.testClassFinished(clazz);
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        l.testStarted(description);
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        l.testFinished(description);
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        l.testFailed(failure);
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+        l.testSucceeded(description);
+    }
+
+    @Override
+    public PrintStream getWriter() {
+        return l.getWriter();
+    }
+
+    public void testClassFinishedDelimiter() {
+        l.testClassFinishedDelimiter();
+    }
+
+    public void testClassStartedDelimiter() {
+        l.testClassStartedDelimiter();
+    }
+
+    public void testStartedDelimiter() {
+        l.testStartedDelimiter();
+    }
+
+    public void testFinishedDelimiter() {
+        l.testFinishedDelimiter();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import com.oracle.truffle.api.vm.TruffleVM;
+import java.io.IOException;
+import java.util.Random;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ * A collection of tests that can certify language implementation to be compliant with most recent
+ * requirements of the Truffle infrastructure and tooling. Subclass, implement abstract methods and
+ * include in your test suite.
+ */
+public abstract class TruffleTCK {
+    private TruffleVM tckVM;
+
+    protected TruffleTCK() {
+    }
+
+    /**
+     * This methods is called before first test is executed. It's purpose is to set a TruffleVM with
+     * your language up, so it is ready for testing.
+     * {@link TruffleVM#eval(java.lang.String, java.lang.String) Execute} any scripts you need, and
+     * prepare global symbols with proper names. The symbols will then be looked up by the
+     * infrastructure (using the names provided by you from methods like {@link #plusInt()}) and
+     * used for internal testing.
+     *
+     * @return initialized Truffle virtual machine
+     * @throws java.lang.Exception thrown when the VM preparation fails
+     */
+    protected abstract TruffleVM prepareVM() throws Exception;
+
+    /**
+     * Mimetype associated with your language. The mimetype will be passed to
+     * {@link TruffleVM#eval(java.lang.String, java.lang.String)} method of the {@link #prepareVM()
+     * created TruffleVM}.
+     *
+     * @return mime type of the tested language
+     */
+    protected abstract String mimeType();
+
+    /**
+     * Name of function which will return value 42 as a number. The return value of the method
+     * should be instance of {@link Number} and its {@link Number#intValue()} should return
+     * <code>42</code>.
+     *
+     * @return name of globally exported symbol
+     */
+    protected abstract String fourtyTwo();
+
+    /**
+     * Name of a function that returns <code>null</code>. Truffle languages are encouraged to have
+     * their own type representing <code>null</code>, but when such value is returned from
+     * {@link TruffleVM#eval}, it needs to be converted to real Java <code>null</code> by sending a
+     * foreign access <em>isNull</em> message. There is a test to verify it is really true.
+     *
+     * @return name of globally exported symbol
+     */
+    protected abstract String returnsNull();
+
+    /**
+     * Name of function to add two integer values together. The symbol will be invoked with two
+     * parameters of type {@link Integer} and expects result of type {@link Number} which's
+     * {@link Number#intValue()} is equivalent of <code>param1 + param2</code>.
+     *
+     * @return name of globally exported symbol
+     */
+    protected abstract String plusInt();
+
+    /**
+     * Return a code snippet that is invalid in your language. Its
+     * {@link TruffleVM#eval(java.lang.String, java.lang.String) evaluation} should fail and yield
+     * an exception.
+     *
+     * @return code snippet invalid in the tested language
+     */
+    protected abstract String invalidCode();
+
+    private TruffleVM vm() throws Exception {
+        if (tckVM == null) {
+            tckVM = prepareVM();
+        }
+        return tckVM;
+    }
+
+    //
+    // The tests
+    //
+
+    @Test
+    public void testFortyTwo() throws Exception {
+        TruffleVM.Symbol fourtyTwo = findGlobalSymbol(fourtyTwo());
+
+        Object res = fourtyTwo.invoke(null);
+
+        assert res instanceof Number : "should yield a number, but was: " + res;
+
+        Number n = (Number) res;
+
+        assert 42 == n.intValue() : "The value is 42 =  " + n.intValue();
+    }
+
+    @Test
+    public void testNull() throws Exception {
+        if (getClass() == TruffleTCK.class) {
+            return;
+        }
+        TruffleVM.Symbol retNull = findGlobalSymbol(returnsNull());
+
+        Object res = retNull.invoke(null);
+
+        assertNull("Should yield real Java null", res);
+    }
+
+    @Test
+    public void testPlusWithInts() throws Exception {
+        Random r = new Random();
+        int a = r.nextInt(100);
+        int b = r.nextInt(100);
+
+        TruffleVM.Symbol plus = findGlobalSymbol(plusInt());
+
+        Object res = plus.invoke(null, a, b);
+
+        assert res instanceof Number : "+ on two ints should yield a number, but was: " + res;
+
+        Number n = (Number) res;
+
+        assert a + b == n.intValue() : "The value is correct: (" + a + " + " + b + ") =  " + n.intValue();
+    }
+
+    @Test(expected = IOException.class)
+    public void testInvalidTestMethod() throws Exception {
+        String mime = mimeType();
+        String code = invalidCode();
+        Object ret = vm().eval(mime, code);
+        fail("Should yield IOException, but returned " + ret);
+    }
+
+    private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception {
+        TruffleVM.Symbol s = vm().findGlobalSymbol(name);
+        assert s != null : "Symbol " + name + " is not found!";
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTextListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+class TruffleTextListener implements TruffleJUnitRunListener {
+
+    private final PrintStream fWriter;
+    protected Failure lastFailure;
+
+    public TruffleTextListener(JUnitSystem system) {
+        this(system.out());
+    }
+
+    public TruffleTextListener(PrintStream writer) {
+        fWriter = writer;
+    }
+
+    @Override
+    public PrintStream getWriter() {
+        return fWriter;
+    }
+
+    public Failure getLastFailure() {
+        return lastFailure;
+    }
+
+    @Override
+    public void testRunStarted(Description description) {
+    }
+
+    @Override
+    public void testRunFinished(Result result) {
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        getWriter().print('.');
+    }
+
+    @Override
+    public void testFinished(Description description) {
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        getWriter().print('E');
+        lastFailure = failure;
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        getWriter().print('I');
+    }
+
+    @Override
+    public void testClassFinishedDelimiter() {
+    }
+
+    @Override
+    public void testClassStartedDelimiter() {
+    }
+
+    @Override
+    public void testStartedDelimiter() {
+    }
+
+    @Override
+    public void testFinishedDelimiter() {
+    }
+
+    public static RunListener createRunListener(final TruffleJUnitRunListener l) {
+        return new TextListener(l.getWriter()) {
+            private Class<?> lastClass;
+            private boolean failed;
+
+            @Override
+            public final void testStarted(Description description) {
+                Class<?> currentClass = description.getTestClass();
+                if (currentClass != lastClass) {
+                    if (lastClass != null) {
+                        l.testClassFinished(lastClass);
+                        l.testClassFinishedDelimiter();
+                    }
+                    lastClass = currentClass;
+                    l.testClassStarted(currentClass);
+                    l.testClassStartedDelimiter();
+                }
+                failed = false;
+                l.testStarted(description);
+                l.testStartedDelimiter();
+            }
+
+            @Override
+            public final void testFailure(Failure failure) {
+                failed = true;
+                l.testFailed(failure);
+            }
+
+            @Override
+            public final void testFinished(Description description) {
+                // we have to do this because there is no callback for successful tests
+                if (!failed) {
+                    l.testSucceeded(description);
+                }
+                l.testFinished(description);
+                l.testFinishedDelimiter();
+            }
+
+            @Override
+            public void testIgnored(Description description) {
+                l.testStarted(description);
+                l.testStartedDelimiter();
+                l.testIgnored(description);
+                l.testFinished(description);
+                l.testFinishedDelimiter();
+            }
+
+            @Override
+            public void testRunStarted(Description description) {
+                l.testRunStarted(description);
+            }
+
+            @Override
+            public void testRunFinished(Result result) {
+                if (lastClass != null) {
+                    l.testClassFinished(lastClass);
+                }
+                l.testRunFinished(result);
+                super.testRunFinished(result);
+            }
+
+            @Override
+            public void testAssumptionFailure(Failure failure) {
+                l.testAssumptionFailure(failure);
+            }
+
+        };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleVerboseTextListener.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tck;
+
+import java.io.*;
+
+import org.junit.internal.*;
+import org.junit.runner.*;
+import org.junit.runner.notification.*;
+
+class TruffleVerboseTextListener extends TruffleTextListener {
+
+    public TruffleVerboseTextListener(JUnitSystem system) {
+        this(system.out());
+    }
+
+    public TruffleVerboseTextListener(PrintStream writer) {
+        super(writer);
+    }
+
+    @Override
+    public void testClassStarted(Class<?> clazz) {
+        getWriter().print(clazz.getName() + " started");
+    }
+
+    @Override
+    public void testClassFinished(Class<?> clazz) {
+        getWriter().print(clazz.getName() + " finished");
+    }
+
+    @Override
+    public void testStarted(Description description) {
+        getWriter().print("  " + description.getMethodName() + ": ");
+    }
+
+    @Override
+    public void testIgnored(Description description) {
+        getWriter().print("Ignored");
+    }
+
+    @Override
+    public void testSucceeded(Description description) {
+        getWriter().print("Passed");
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+        getWriter().printf("(%s) ", failure.getMessage());
+    }
+
+    @Override
+    public void testFailed(Failure failure) {
+        getWriter().print("FAILED");
+        lastFailure = failure;
+    }
+
+    @Override
+    public void testClassFinishedDelimiter() {
+        getWriter().println();
+    }
+
+    @Override
+    public void testClassStartedDelimiter() {
+        getWriter().println();
+    }
+
+    @Override
+    public void testFinishedDelimiter() {
+        getWriter().println();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/Breakpoint.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+public abstract class Breakpoint {
+
+    /**
+     * A general model of the states occupied by a breakpoint during its lifetime.
+     */
+    public enum BreakpointState {
+
+        /**
+         * Not attached, enabled.
+         * <p>
+         * Created for a source location but not yet attached: perhaps just created and the source
+         * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
+         * probed so a breakpoint cannot be attached. Can be either enabled or disabled.
+         */
+        ENABLED_UNRESOLVED("Enabled/Unresolved"),
+
+        /**
+         * Not attached, disabled.
+         * <p>
+         * Created for a source location but not yet attached: perhaps just created and the source
+         * hasn't been loaded yet; perhaps source has been loaded, but the line location isn't
+         * probed so a breakpoint cannot be attached.
+         */
+        DISABLED_UNRESOLVED("Disabled/Unresolved"),
+
+        /**
+         * Attached, instrument enabled.
+         * <p>
+         * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
+         * at a specific node in the AST, and the breakpoint is enabled.
+         */
+        ENABLED("Enabled"),
+
+        /**
+         * Attached, instrument disabled.
+         * <p>
+         * Is currently implemented by some {@link Instrument}, which is attached to a {@link Probe}
+         * at a specific node in the AST, and the breakpoint is disabled.
+         */
+        DISABLED("Disabled"),
+
+        /**
+         * Not attached, instrument is permanently disabled.
+         */
+        DISPOSED("Disposed");
+
+        private final String name;
+
+        BreakpointState(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String toString() {
+            return name;
+        }
+
+    }
+
+    private static int nextBreakpointId = 0;
+
+    private final int id;
+    private final int groupId;
+    private final boolean isOneShot;
+
+    private int ignoreCount;
+
+    private int hitCount = 0;
+
+    private BreakpointState state;
+
+    Breakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
+        this.state = state;
+        this.id = nextBreakpointId++;
+        this.groupId = groupId;
+        this.isOneShot = isOneShot;
+        this.ignoreCount = ignoreCount;
+    }
+
+    /**
+     * Unique ID.
+     */
+    public final int getId() {
+        return id;
+    }
+
+    /**
+     * Group ID, set when created.
+     */
+    public final int getGroupId() {
+        return groupId;
+    }
+
+    /**
+     * Enables or disables this breakpoint's AST instrumentation. The breakpoint is enabled by
+     * default.
+     *
+     * @param enabled <code>true</code> to activate the instrumentation, <code>false</code> to
+     *            deactivate the instrumentation so that it has no effect.
+     */
+    public abstract void setEnabled(boolean enabled);
+
+    /**
+     * Is this breakpoint active?
+     */
+    public abstract boolean isEnabled();
+
+    /**
+     * Sets the condition on this breakpoint, {@code null} to make it unconditional.
+     *
+     * @param expr if non{@code -null}, a boolean expression, expressed in the guest language, to be
+     *            evaluated in the lexical context at the breakpoint location.
+     * @throws DebugException if condition is invalid
+     * @throws UnsupportedOperationException if the breakpoint does not support conditions
+     */
+    public abstract void setCondition(String expr) throws DebugException;
+
+    /**
+     * Gets the string, expressed in the Guest Language, that defines the current condition on this
+     * breakpoint; {@code null} if this breakpoint is currently unconditional.
+     */
+    public String getCondition() {
+        return null;
+    }
+
+    /**
+     * Does this breakpoint remove itself after first activation?
+     */
+    public final boolean isOneShot() {
+        return isOneShot;
+    }
+
+    /**
+     * Gets the number of hits left to be ignored before halting.
+     */
+    public final int getIgnoreCount() {
+        return ignoreCount;
+    }
+
+    /**
+     * Change the threshold for when this breakpoint should start causing a break. When both an
+     * ignore count and a {@linkplain #setCondition(String) condition} are specified, the condition
+     * is evaluated first: if {@code false} it is not considered to be a hit. In other words, the
+     * ignore count is for successful conditions only.
+     */
+    public final void setIgnoreCount(int ignoreCount) {
+        this.ignoreCount = ignoreCount;
+    }
+
+    /**
+     * Number of times this breakpoint has reached, with one exception; if the breakpoint has a
+     * condition that evaluates to {@code false}, it does not count as a hit.
+     */
+    public final int getHitCount() {
+        return hitCount;
+    }
+
+    /**
+     * Disables this breakpoint and removes any associated instrumentation; it becomes permanently
+     * inert.
+     */
+    public abstract void dispose();
+
+    /**
+     * Gets a human-sensible description of this breakpoint's location in a {@link Source}.
+     */
+    public abstract String getLocationDescription();
+
+    public final BreakpointState getState() {
+        return state;
+    }
+
+    final void assertState(BreakpointState s) {
+        assert state == s;
+    }
+
+    final void setState(BreakpointState state) {
+        this.state = state;
+    }
+
+    /**
+     * Assumes that all conditions for causing the break have been satisfied, so increments the
+     * <em>hit count</em>. Then checks if the <em>ignore count</em> has been exceeded, and if so
+     * returns {@code true}. If not, it still counts as a <em>hit</em> but should be ignored.
+     *
+     * @return whether to proceed
+     */
+    final boolean incrHitCountCheckIgnore() {
+        return ++hitCount > ignoreCount;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(getClass().getSimpleName());
+        sb.append(" state=");
+        sb.append(getState() == null ? "<none>" : getState().getName());
+        if (isOneShot()) {
+            sb.append(", " + "One-Shot");
+        }
+        if (getCondition() != null) {
+            sb.append(", condition=\"" + getCondition() + "\"");
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugClient.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+
+/**
+ * A client of the debugger where certain events should be posted.
+ *
+ * @see DebugEngine
+ */
+public interface DebugClient {
+
+    /**
+     * Notifies client that program execution has been halted at some location; execution will
+     * resume when this method returns.
+     *
+     * @param astNode AST node that is just about to be executed
+     * @param mFrame frame that will be passed to the node when executed
+     * @param warnings any warnings generated since the most recent halt.
+     */
+    void haltedAt(Node astNode, MaterializedFrame mFrame, List<String> warnings);
+
+    /**
+     * Gets information and services for the language being debugged.
+     */
+    Language getLanguage();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugEngine.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+import com.oracle.truffle.tools.debug.engine.DebugExecutionSupport.DebugExecutionListener;
+
+/**
+ * Language-agnostic engine for running Truffle languages under debugging control.
+ */
+public final class DebugEngine {
+
+    private static final boolean TRACE = false;
+    private static final String TRACE_PREFIX = "DEBUG ENGINE: ";
+
+    private static final PrintStream OUT = System.out;
+
+    private static final SyntaxTag STEPPING_TAG = StandardSyntaxTag.STATEMENT;
+    private static final SyntaxTag CALL_TAG = StandardSyntaxTag.CALL;
+
+    private static void trace(String format, Object... args) {
+        if (TRACE) {
+            OUT.println(TRACE_PREFIX + String.format(format, args));
+        }
+    }
+
+    interface BreakpointCallback {
+
+        /**
+         * Passes control to the debugger with execution suspended.
+         */
+        void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason);
+    }
+
+    interface WarningLog {
+
+        /**
+         * Logs a warning that is kept until the start of the next execution.
+         */
+        void addWarning(String warning);
+    }
+
+    private final Language language;
+
+    /**
+     * The client of this engine.
+     */
+    private final DebugClient debugClient;
+
+    private final DebugExecutionSupport executionSupport;
+
+    /**
+     * Implementation of line-oriented breakpoints.
+     */
+    private final LineBreakpointFactory lineBreaks;
+
+    /**
+     * Implementation of tag-oriented breakpoints.
+     */
+    private final TagBreakpointFactory tagBreaks;
+
+    /**
+     * Head of the stack of executions.
+     */
+    private DebugExecutionContext debugContext;
+
+    /**
+     * @param debugClient
+     * @param language
+     */
+    private DebugEngine(DebugClient debugClient, Language language) {
+        this.debugClient = debugClient;
+        this.language = language;
+        this.executionSupport = new DebugExecutionSupport(language.getShortName(), language.getDebugSupport());
+
+        Source.setFileCaching(true);
+
+        // Initialize execution context stack
+        debugContext = new DebugExecutionContext(null, null);
+        prepareContinue();
+        debugContext.contextTrace("START EXEC DEFAULT");
+
+        executionSupport.addExecutionListener(new DebugExecutionListener() {
+
+            public void executionStarted(Source source, boolean stepInto) {
+                // Push a new execution context onto stack
+                DebugEngine.this.debugContext = new DebugExecutionContext(source, DebugEngine.this.debugContext);
+                if (stepInto) {
+                    DebugEngine.this.prepareStepInto(1);
+                } else {
+                    DebugEngine.this.prepareContinue();
+                }
+                DebugEngine.this.debugContext.contextTrace("START EXEC ");
+            }
+
+            public void executionEnded() {
+                DebugEngine.this.lineBreaks.disposeOneShots();
+                DebugEngine.this.tagBreaks.disposeOneShots();
+                DebugEngine.this.debugContext.clearStrategy();
+                DebugEngine.this.debugContext.contextTrace("END EXEC ");
+                // Pop the stack of execution contexts.
+                DebugEngine.this.debugContext = DebugEngine.this.debugContext.predecessor;
+            }
+        });
+
+        final BreakpointCallback breakpointCallback = new BreakpointCallback() {
+
+            @TruffleBoundary
+            public void haltedAt(Node astNode, MaterializedFrame mFrame, String haltReason) {
+                debugContext.halt(astNode, mFrame, true, haltReason);
+            }
+        };
+
+        final WarningLog warningLog = new WarningLog() {
+
+            public void addWarning(String warning) {
+                assert debugContext != null;
+                debugContext.logWarning(warning);
+            }
+        };
+
+        this.lineBreaks = new LineBreakpointFactory(executionSupport, breakpointCallback, warningLog);
+
+        this.tagBreaks = new TagBreakpointFactory(executionSupport, breakpointCallback, warningLog);
+    }
+
+    public static DebugEngine create(DebugClient debugClient, Language language) {
+        return new DebugEngine(debugClient, language);
+    }
+
+    /**
+     * Runs a script. If "StepInto" is requested, halts at the first location tagged as a
+     * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}.
+     *
+     * @throws DebugException if an unexpected failure occurs
+     */
+    public void run(Source source, boolean stepInto) throws DebugException {
+        executionSupport.run(source, stepInto);
+    }
+
+    /**
+     * Sets a breakpoint to halt at a source line.
+     *
+     * @param groupId
+     * @param ignoreCount number of hits to ignore before halting
+     * @param lineLocation where to set the breakpoint (source, line number)
+     * @param oneShot breakpoint disposes itself after fist hit, if {@code true}
+     * @return a new breakpoint, initially enabled
+     * @throws DebugException if the breakpoint can not be set.
+     */
+    @TruffleBoundary
+    public LineBreakpoint setLineBreakpoint(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) throws DebugException {
+        return lineBreaks.create(groupId, ignoreCount, lineLocation, oneShot);
+    }
+
+    /**
+     * Sets a breakpoint to halt at any node holding a specified {@link SyntaxTag}.
+     *
+     * @param groupId
+     * @param ignoreCount number of hits to ignore before halting
+     * @param oneShot if {@code true} breakpoint removes it self after a hit
+     * @return a new breakpoint, initially enabled
+     * @throws DebugException if the breakpoint already set
+     */
+    @TruffleBoundary
+    public Breakpoint setTagBreakpoint(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) throws DebugException {
+        return tagBreaks.create(groupId, ignoreCount, tag, oneShot);
+    }
+
+    /**
+     * Finds a breakpoint created by this engine, but not yet disposed, by id.
+     */
+    @TruffleBoundary
+    public Breakpoint findBreakpoint(long id) {
+        final Breakpoint breakpoint = lineBreaks.find(id);
+        return breakpoint == null ? tagBreaks.find(id) : breakpoint;
+    }
+
+    /**
+     * Gets all existing breakpoints, whatever their status, in natural sorted order. Modification
+     * save.
+     */
+    @TruffleBoundary
+    public Collection<Breakpoint> getBreakpoints() {
+        final Collection<Breakpoint> result = new ArrayList<>();
+        result.addAll(lineBreaks.getAll());
+        result.addAll(tagBreaks.getAll());
+        return result;
+    }
+
+    /**
+     * Prepare to execute in Continue mode when guest language program execution resumes. In this
+     * mode:
+     * <ul>
+     * <li>Execution will continue until either:
+     * <ol>
+     * <li>execution arrives at a node to which an enabled breakpoint is attached,
+     * <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * </ul>
+     */
+    @TruffleBoundary
+    public void prepareContinue() {
+        debugContext.setStrategy(new Continue());
+    }
+
+    /**
+     * Prepare to execute in StepInto mode when guest language program execution resumes. In this
+     * mode:
+     * <ul>
+     * <li>User breakpoints are disabled.</li>
+     * <li>Execution will continue until either:
+     * <ol>
+     * <li>execution arrives at a node with the tag {@linkplain StandardSyntaxTag#STATEMENT
+     * STATMENT}, <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * <li>
+     * StepInto mode persists only through one resumption (i.e. {@code stepIntoCount} steps), and
+     * reverts by default to Continue mode.</li>
+     * </ul>
+     *
+     * @param stepCount the number of times to perform StepInto before halting
+     * @throws IllegalArgumentException if the specified number is {@code <= 0}
+     */
+    @TruffleBoundary
+    public void prepareStepInto(int stepCount) {
+        if (stepCount <= 0) {
+            throw new IllegalArgumentException();
+        }
+        debugContext.setStrategy(new StepInto(stepCount));
+    }
+
+    /**
+     * Prepare to execute in StepOut mode when guest language program execution resumes. In this
+     * mode:
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution will continue until either:
+     * <ol>
+     * <li>execution arrives at the nearest enclosing call site on the stack, <strong>or</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * <li>StepOut mode persists only through one resumption, and reverts by default to Continue
+     * mode.</li>
+     * </ul>
+     */
+    @TruffleBoundary
+    public void prepareStepOut() {
+        debugContext.setStrategy(new StepOut());
+    }
+
+    /**
+     * Prepare to execute in StepOver mode when guest language program execution resumes. In this
+     * mode:
+     * <ul>
+     * <li>Execution will continue until either:
+     * <ol>
+     * <li>execution arrives at a node with the tag {@linkplain StandardSyntaxTag#STATEMENT
+     * STATEMENT} when not nested in one or more function/method calls, <strong>or:</strong></li>
+     * <li>execution arrives at a node to which a breakpoint is attached and when nested in one or
+     * more function/method calls, <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * <li>StepOver mode persists only through one resumption (i.e. {@code stepOverCount} steps),
+     * and reverts by default to Continue mode.</li>
+     * </ul>
+     *
+     * @param stepCount the number of times to perform StepInto before halting
+     * @throws IllegalArgumentException if the specified number is {@code <= 0}
+     */
+    @TruffleBoundary
+    public void prepareStepOver(int stepCount) {
+        if (stepCount <= 0) {
+            throw new IllegalArgumentException();
+        }
+        debugContext.setStrategy(new StepOver(stepCount));
+    }
+
+    /**
+     * Gets the stack frames from the (topmost) halted Truffle execution; {@code null} null if no
+     * execution.
+     */
+    @TruffleBoundary
+    public List<FrameDebugDescription> getStack() {
+        return debugContext == null ? null : debugContext.getFrames();
+    }
+
+    /**
+     * Evaluates code in a halted execution context, at top-level if <code>mFrame==null</code>.
+     *
+     * @throws DebugException
+     */
+    public Object eval(Source source, Node node, MaterializedFrame mFrame) throws DebugException {
+        return executionSupport.evalInContext(source, node, mFrame);
+    }
+
+    /**
+     * A mode of user navigation from a current code location to another, e.g "step in" vs.
+     * "step over".
+     */
+    private abstract class StepStrategy {
+
+        private DebugExecutionContext context;
+        protected final String strategyName;
+
+        protected StepStrategy() {
+            this.strategyName = getClass().getSimpleName();
+        }
+
+        final String getName() {
+            return strategyName;
+        }
+
+        /**
+         * Reconfigure the debugger so that when execution continues the program will halt at the
+         * location specified by this strategy.
+         */
+        final void enable(DebugExecutionContext c, int stackDepth) {
+            this.context = c;
+            setStrategy(stackDepth);
+        }
+
+        /**
+         * Return the debugger to the default navigation mode.
+         */
+        final void disable() {
+            unsetStrategy();
+        }
+
+        @TruffleBoundary
+        final void halt(Node astNode, MaterializedFrame mFrame, boolean before) {
+            context.halt(astNode, mFrame, before, this.getClass().getSimpleName());
+        }
+
+        @TruffleBoundary
+        final void replaceStrategy(StepStrategy newStrategy) {
+            context.setStrategy(newStrategy);
+        }
+
+        @TruffleBoundary
+        protected final void strategyTrace(String action, String format, Object... args) {
+            if (TRACE) {
+                context.contextTrace("%s (%s) %s", action, strategyName, String.format(format, args));
+            }
+        }
+
+        @TruffleBoundary
+        protected final void suspendUserBreakpoints() {
+            lineBreaks.setActive(false);
+            tagBreaks.setActive(false);
+        }
+
+        @SuppressWarnings("unused")
+        protected final void restoreUserBreakpoints() {
+            lineBreaks.setActive(true);
+            tagBreaks.setActive(true);
+        }
+
+        /**
+         * Reconfigure the debugger so that when execution continues, it will do so using this mode
+         * of navigation.
+         */
+        protected abstract void setStrategy(int stackDepth);
+
+        /**
+         * Return to the debugger to the default mode of navigation.
+         */
+        protected abstract void unsetStrategy();
+    }
+
+    /**
+     * Strategy: the null stepping strategy.
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution continues until either:
+     * <ol>
+     * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * </ul>
+     */
+    private final class Continue extends StepStrategy {
+
+        @Override
+        protected void setStrategy(int stackDepth) {
+        }
+
+        @Override
+        protected void unsetStrategy() {
+        }
+    }
+
+    /**
+     * Strategy: per-statement stepping.
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution continues until either:
+     * <ol>
+     * <li>execution <em>arrives</em> at a STATEMENT node, <strong>or:</strong></li>
+     * <li>execution <em>returns</em> to a CALL node and the call stack is smaller then when
+     * execution started, <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * </ul>
+     *
+     * @see DebugEngine#prepareStepInto(int)
+     */
+    private final class StepInto extends StepStrategy {
+        private int unfinishedStepCount;
+
+        StepInto(int stepCount) {
+            super();
+            this.unfinishedStepCount = stepCount;
+        }
+
+        @Override
+        protected void setStrategy(final int stackDepth) {
+            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
+
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    // HALT: just before statement
+                    --unfinishedStepCount;
+                    strategyTrace("TRAP BEFORE", "unfinished steps=%d", unfinishedStepCount);
+                    // Should run in fast path
+                    if (unfinishedStepCount <= 0) {
+                        halt(node, mFrame, true);
+                    }
+                    strategyTrace("RESUME BEFORE", "");
+                }
+            });
+            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
+
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    --unfinishedStepCount;
+                    strategyTrace(null, "TRAP AFTER unfinished steps=%d", unfinishedStepCount);
+                    if (currentStackDepth() < stackDepth) {
+                        // HALT: just "stepped out"
+                        if (unfinishedStepCount <= 0) {
+                            halt(node, mFrame, false);
+                        }
+                    }
+                    strategyTrace("RESUME AFTER", "");
+                }
+            });
+        }
+
+        @Override
+        protected void unsetStrategy() {
+            Probe.setBeforeTagTrap(null);
+            Probe.setAfterTagTrap(null);
+        }
+    }
+
+    /**
+     * Strategy: execution to nearest enclosing call site.
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution continues until either:
+     * <ol>
+     * <li>execution arrives at a node with attached user breakpoint, <strong>or:</strong></li>
+     * <li>execution <em>returns</em> to a CALL node and the call stack is smaller than when
+     * execution started, <strong>or:</strong></li>
+     * <li>execution completes.</li>
+     * </ol>
+     * </ul>
+     *
+     * @see DebugEngine#prepareStepOut()
+     */
+    private final class StepOut extends StepStrategy {
+
+        @Override
+        protected void setStrategy(final int stackDepth) {
+            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
+
+                @TruffleBoundary
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    // HALT:
+                    final int currentStackDepth = currentStackDepth();
+                    strategyTrace("TRAP AFTER", "stackDepth: start=%d current=%d", stackDepth, currentStackDepth);
+                    if (currentStackDepth < stackDepth) {
+                        halt(node, mFrame, false);
+                    }
+                    strategyTrace("RESUME AFTER", "");
+                }
+            });
+        }
+
+        @Override
+        protected void unsetStrategy() {
+            Probe.setAfterTagTrap(null);
+        }
+    }
+
+    /**
+     * Strategy: per-statement stepping, so long as not nested in method calls (i.e. at original
+     * stack depth).
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution continues until either:
+     * <ol>
+     * <li>execution arrives at a STATEMENT node with stack depth no more than when started
+     * <strong>or:</strong></li>
+     * <li>the program completes.</li>
+     * </ol>
+     * </ul>
+     */
+    private final class StepOver extends StepStrategy {
+        private int unfinishedStepCount;
+
+        StepOver(int stepCount) {
+            this.unfinishedStepCount = stepCount;
+        }
+
+        @Override
+        protected void setStrategy(int stackDepth) {
+            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
+
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    final int currentStackDepth = currentStackDepth();
+                    if (currentStackDepth <= stackDepth) {
+                        // HALT: stack depth unchanged or smaller; treat like StepInto
+                        --unfinishedStepCount;
+                        if (TRACE) {
+                            strategyTrace("TRAP BEFORE", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
+                        }
+                        // Test should run in fast path
+                        if (unfinishedStepCount <= 0) {
+                            halt(node, mFrame, true);
+                        }
+                    } else {
+                        // CONTINUE: Stack depth increased; don't count as a step
+                        strategyTrace("STEP INTO", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
+                        // Stop treating like StepInto, start treating like StepOut
+                        replaceStrategy(new StepOverNested(unfinishedStepCount, stackDepth));
+                    }
+                    strategyTrace("RESUME BEFORE", "");
+                }
+            });
+
+            Probe.setAfterTagTrap(new SyntaxTagTrap(CALL_TAG) {
+
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    final int currentStackDepth = currentStackDepth();
+                    if (currentStackDepth < stackDepth) {
+                        // HALT: just "stepped out"
+                        --unfinishedStepCount;
+                        strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth: start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
+                        // Should run in fast path
+                        if (unfinishedStepCount <= 0) {
+                            halt(node, mFrame, false);
+                        }
+                        strategyTrace("RESUME AFTER", "");
+                    }
+                }
+            });
+        }
+
+        @Override
+        protected void unsetStrategy() {
+            Probe.setBeforeTagTrap(null);
+            Probe.setAfterTagTrap(null);
+        }
+    }
+
+    /**
+     * Strategy: per-statement stepping, not into method calls, in effect while at increased stack
+     * depth
+     * <ul>
+     * <li>User breakpoints are enabled.</li>
+     * <li>Execution continues until either:
+     * <ol>
+     * <li>execution arrives at a STATEMENT node with stack depth no more than when started
+     * <strong>or:</strong></li>
+     * <li>the program completes <strong>or:</strong></li>
+     * </ol>
+     * </ul>
+     */
+    private final class StepOverNested extends StepStrategy {
+        private int unfinishedStepCount;
+        private final int startStackDepth;
+
+        StepOverNested(int stepCount, int startStackDepth) {
+            this.unfinishedStepCount = stepCount;
+            this.startStackDepth = startStackDepth;
+        }
+
+        @Override
+        protected void setStrategy(int stackDepth) {
+            Probe.setBeforeTagTrap(new SyntaxTagTrap(STEPPING_TAG) {
+
+                @Override
+                public void tagTrappedAt(Node node, MaterializedFrame mFrame) {
+                    final int currentStackDepth = currentStackDepth();
+                    if (currentStackDepth <= startStackDepth) {
+                        // At original step depth (or smaller) after being nested
+                        --unfinishedStepCount;
+                        strategyTrace("TRAP AFTER", "unfinished steps=%d stackDepth start=%d current=%d", unfinishedStepCount, stackDepth, currentStackDepth);
+                        if (unfinishedStepCount <= 0) {
+                            halt(node, mFrame, false);
+                        }
+                        // TODO (mlvdv) fixme for multiple steps
+                        strategyTrace("RESUME BEFORE", "");
+                    }
+                }
+            });
+        }
+
+        @Override
+        protected void unsetStrategy() {
+            Probe.setBeforeTagTrap(null);
+        }
+    }
+
+    /**
+     * Information and debugging state for a single Truffle execution (which make take place over
+     * one or more suspended executions). This holds interaction state, for example what is
+     * executing (e.g. some {@link Source}), what the execution mode is ("stepping" or
+     * "continuing"). When not running, this holds a cache of the Truffle stack for this particular
+     * execution, effectively hiding the Truffle stack for any currently suspended executions (down
+     * the stack).
+     */
+    private final class DebugExecutionContext {
+
+        // Previous halted context in stack
+        private final DebugExecutionContext predecessor;
+
+        // The current execution level; first is 0.
+        private final int level;  // Number of contexts suspended below
+        private final Source source;
+        private final int contextStackBase;  // Where the stack for this execution starts
+        private final List<String> warnings = new ArrayList<>();
+
+        private boolean running;
+
+        /**
+         * The stepping strategy currently configured in the debugger.
+         */
+        private StepStrategy strategy;
+
+        /**
+         * Where halted; null if running.
+         */
+        private Node haltedNode;
+
+        /**
+         * Where halted; null if running.
+         */
+        private MaterializedFrame haltedFrame;
+
+        /**
+         * Cached list of stack frames when halted; null if running.
+         */
+        private List<FrameDebugDescription> frames = new ArrayList<>();
+
+        private DebugExecutionContext(Source executionSource, DebugExecutionContext previousContext) {
+            this.source = executionSource;
+            this.predecessor = previousContext;
+            this.level = previousContext == null ? 0 : previousContext.level + 1;
+
+            // "Base" is the number of stack frames for all nested (halted) executions.
+            this.contextStackBase = currentStackDepth();
+            this.running = true;
+            contextTrace("NEW CONTEXT");
+        }
+
+        /**
+         * Sets up a strategy for the next resumption of execution.
+         *
+         * @param stepStrategy
+         */
+        void setStrategy(StepStrategy stepStrategy) {
+            if (this.strategy == null) {
+                this.strategy = stepStrategy;
+                this.strategy.enable(this, currentStackDepth());
+                if (TRACE) {
+                    contextTrace("SET MODE <none>-->" + stepStrategy.getName());
+                }
+            } else {
+                strategy.disable();
+                strategy = stepStrategy;
+                strategy.enable(this, currentStackDepth());
+                contextTrace("SWITCH MODE %s-->%s", strategy.getName(), stepStrategy.getName());
+            }
+        }
+
+        void clearStrategy() {
+            if (strategy != null) {
+                final StepStrategy oldStrategy = strategy;
+                strategy.disable();
+                strategy = null;
+                contextTrace("CLEAR MODE %s--><none>", oldStrategy.getName());
+            }
+        }
+
+        /**
+         * Handle a program halt, caused by a breakpoint, stepping strategy, or other cause.
+         *
+         * @param astNode the guest language node at which execution is halted
+         * @param mFrame the current execution frame where execution is halted
+         * @param before {@code true} if halted <em>before</em> the node, else <em>after</em>.
+         */
+        @TruffleBoundary
+        void halt(Node astNode, MaterializedFrame mFrame, boolean before, String haltReason) {
+            assert running;
+            assert frames.isEmpty();
+            assert haltedNode == null;
+            assert haltedFrame == null;
+
+            haltedNode = astNode;
+            haltedFrame = mFrame;
+            running = false;
+
+            clearStrategy();
+
+            // Clean up, just in cased the one-shot breakpoints got confused
+            lineBreaks.disposeOneShots();
+
+            // Map the Truffle stack for this execution, ignore nested executions
+            // The top (current) frame is not produced by the iterator.
+            frames.add(new FrameDebugDescription(0, haltedNode, Truffle.getRuntime().getCurrentFrame()));
+            final int contextStackDepth = currentStackDepth() - contextStackBase;
+            final int[] frameCount = {1};
+            Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<FrameInstance>() {
+                @Override
+                public FrameInstance visitFrame(FrameInstance frameInstance) {
+                    if (frameCount[0] < contextStackDepth) {
+                        frames.add(new FrameDebugDescription(frameCount[0], frameInstance.getCallNode(), frameInstance));
+                        frameCount[0] = frameCount[0] + 1;
+                        return null;
+                    }
+                    return frameInstance;
+                }
+            });
+
+            if (TRACE) {
+                final String reason = haltReason == null ? "" : haltReason + "";
+                final String where = before ? "BEFORE" : "AFTER";
+                contextTrace("HALT %s : (%s) stack base=%d", where, reason, contextStackBase);
+                contextTrace("CURRENT STACK:");
+                printStack(OUT);
+            }
+
+            final List<String> recentWarnings = new ArrayList<>(warnings);
+            warnings.clear();
+
+            try {
+                // Pass control to the debug client with current execution suspended
+                debugClient.haltedAt(astNode, mFrame, recentWarnings);
+                // Debug client finished normally, execution resumes
+                // Presume that the client has set a new strategy (or default to Continue)
+                running = true;
+            } catch (KillException e) {
+                contextTrace("KILL");
+                throw e;
+            } finally {
+                haltedNode = null;
+                haltedFrame = null;
+                frames.clear();
+            }
+
+        }
+
+        List<FrameDebugDescription> getFrames() {
+            return Collections.unmodifiableList(frames);
+        }
+
+        void logWarning(String warning) {
+            warnings.add(warning);
+        }
+
+        // For tracing
+        private void printStack(PrintStream stream) {
+            getFrames();
+            if (frames == null) {
+                stream.println("<empty stack>");
+            } else {
+                final Visualizer visualizer = language.getDebugSupport().getVisualizer();
+                for (FrameDebugDescription frameDesc : frames) {
+                    final StringBuilder sb = new StringBuilder("    frame " + Integer.toString(frameDesc.index()));
+                    sb.append(":at " + visualizer.displaySourceLocation(frameDesc.node()));
+                    sb.append(":in '" + visualizer.displayMethodName(frameDesc.node()) + "'");
+                    stream.println(sb.toString());
+                }
+            }
+        }
+
+        void contextTrace(String format, Object... args) {
+            if (TRACE) {
+                final String srcName = (source != null) ? source.getName() : "no source";
+                DebugEngine.trace("<%d> %s (%s)", level, String.format(format, args), srcName);
+            }
+        }
+    }
+
+    // TODO (mlvdv) wish there were fast-path access to stack depth
+    /**
+     * Depth of current Truffle stack, including nested executions. Includes the top/current frame,
+     * which the standard iterator does not count: {@code 0} if no executions.
+     */
+    @TruffleBoundary
+    private static int currentStackDepth() {
+        final int[] count = {0};
+        Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Void>() {
+            @Override
+            public Void visitFrame(FrameInstance frameInstance) {
+                count[0] = count[0] + 1;
+                return null;
+            }
+        });
+        return count[0] == 0 ? 0 : count[0] + 1;
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+/**
+ * An unexpected failure in the operation of the {@link DebugEngine}.
+ */
+public class DebugException extends Exception {
+
+    public DebugException(String string) {
+        super(string);
+    }
+
+    public DebugException(Exception ex) {
+        super(ex);
+    }
+
+    private static final long serialVersionUID = 3307454453821997224L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/DebugExecutionSupport.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import java.util.*;
+
+import com.oracle.truffle.api.debug.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Access to language-specific support for debugging.
+ */
+final class DebugExecutionSupport {
+
+    interface DebugExecutionListener {
+
+        /**
+         * Notifies that execution is about to start and requests initial execution mode.
+         */
+        void executionStarted(Source source, boolean stepInto);
+
+        /**
+         * Notification that the current execution has just ended.
+         */
+        void executionEnded();
+    }
+
+    private final String languageName;
+    private final DebugSupportProvider provider;
+    private final List<DebugExecutionListener> listeners = new ArrayList<>();
+
+    DebugExecutionSupport(String languageName, DebugSupportProvider provider) {
+        this.languageName = languageName;
+        this.provider = provider;
+    }
+
+    void addExecutionListener(DebugExecutionListener listener) {
+        assert listener != null;
+        listeners.add(listener);
+    }
+
+    String getLanguageName() {
+        return languageName;
+    }
+
+    Visualizer getVisualizer() {
+        return provider.getVisualizer();
+    }
+
+    /**
+     * Runs a script. If "StepInto" is specified, halts at the first location tagged as a
+     * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT}.
+     */
+    void run(Source source, boolean stepInto) throws DebugException {
+        for (DebugExecutionListener listener : listeners) {
+            listener.executionStarted(source, stepInto);
+        }
+        try {
+            provider.run(source);
+        } catch (DebugSupportException ex) {
+            throw new DebugException(ex);
+        } finally {
+            for (DebugExecutionListener listener : listeners) {
+                listener.executionEnded();
+            }
+        }
+    }
+
+    /**
+     * Evaluates string of language code in a halted execution context, at top level if
+     * <code>mFrame==null</code>.
+     *
+     * @throws DebugException
+     */
+    Object evalInContext(Source source, Node node, MaterializedFrame mFrame) throws DebugException {
+        for (DebugExecutionListener listener : listeners) {
+            listener.executionStarted(source, false);
+        }
+        try {
+            return provider.evalInContext(source, node, mFrame);
+        } catch (DebugSupportException ex) {
+            throw new DebugException(ex);
+        } finally {
+            for (DebugExecutionListener listener : listeners) {
+                listener.executionEnded();
+            }
+        }
+    }
+
+    /**
+     * Creates a language-specific factory to produce instances of {@link AdvancedInstrumentRoot}
+     * that, when executed, computes the result of a textual expression in the language; used to
+     * create an
+     * {@linkplain Instrument#create(AdvancedInstrumentResultListener, AdvancedInstrumentRootFactory, Class, String)
+     * Advanced Instrument}.
+     *
+     * @param expr a guest language expression
+     * @param resultListener optional listener for the result of each evaluation.
+     * @return a new factory
+     * @throws DebugException if the factory cannot be created, for example if the expression is
+     *             badly formed.
+     */
+    AdvancedInstrumentRootFactory createAdvancedInstrumentRootFactory(String expr, AdvancedInstrumentResultListener resultListener) throws DebugException {
+        try {
+            return provider.createAdvancedInstrumentRootFactory(expr, resultListener);
+        } catch (DebugSupportException ex) {
+            throw new DebugException(ex);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/FrameDebugDescription.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * A summary description of a Truffle {@link Frame} in a particular stack context.
+ *
+ * @see DebugEngine
+ */
+public final class FrameDebugDescription {
+
+    private final int index;
+    private final Node node;
+    private final FrameInstance frameInstance;
+
+    FrameDebugDescription(int index, Node node, FrameInstance frameInstance) {
+        this.index = index;
+        this.node = node;
+        this.frameInstance = frameInstance;
+    }
+
+    /**
+     * Position in the current stack: {@code 0} at the top.
+     */
+    public int index() {
+        return index;
+    }
+
+    /**
+     * AST location.
+     */
+    public Node node() {
+        return node;
+    }
+
+    /**
+     * Access to the Truffle {@link Frame}.
+     */
+    public FrameInstance frameInstance() {
+        return frameInstance;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpoint.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import com.oracle.truffle.api.source.*;
+
+// TODO (mlvdv) generic?
+/**
+ * A breakpoint associated with a {@linkplain LineLocation source line location}.
+ *
+ * @see DebugEngine
+ */
+public abstract class LineBreakpoint extends Breakpoint {
+
+    LineBreakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
+        super(state, groupId, ignoreCount, isOneShot);
+    }
+
+    /**
+     * Gets the {@linkplain LineLocation source line location} that specifies where this breakpoint
+     * will trigger.
+     */
+    public abstract LineLocation getLineLocation();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/LineBreakpointFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import static com.oracle.truffle.tools.debug.engine.Breakpoint.BreakpointState.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.tools.*;
+import com.oracle.truffle.tools.debug.engine.DebugEngine.BreakpointCallback;
+import com.oracle.truffle.tools.debug.engine.DebugEngine.WarningLog;
+
+//TODO (mlvdv) some common functionality could be factored out of this and TagBreakpointSupport
+
+/**
+ * Support class for creating and managing all existing ordinary (user visible) line breakpoints.
+ * <p>
+ * Notes:
+ * <ol>
+ * <li>Line breakpoints can only be set at nodes tagged as {@link StandardSyntaxTag#STATEMENT}.</li>
+ * <li>A newly created breakpoint looks for probes matching the location, attaches to them if found
+ * by installing an {@link Instrument} that calls back to the breakpoint.</li>
+ * <li>When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be
+ * copied along with the rest of the AST and will call back to the same breakpoint.</li>
+ * <li>When notification is received of a new Node being tagged as a statement, and if a
+ * breakpoint's line location matches the Probe's line location, then the breakpoint will attach a
+ * new Instrument at the probe to activate the breakpoint at that location.</li>
+ * <li>A breakpoint may have multiple Instruments deployed, one attached to each Probe that matches
+ * the breakpoint's line location; this might happen when a source is reloaded.</li>
+ * </ol>
+ *
+ */
+final class LineBreakpointFactory {
+
+    private static final boolean TRACE = false;
+    private static final PrintStream OUT = System.out;
+
+    private static final String BREAKPOINT_NAME = "LINE BREAKPOINT";
+
+    private static void trace(String format, Object... args) {
+        if (TRACE) {
+            OUT.println(String.format("%s: %s", BREAKPOINT_NAME, String.format(format, args)));
+        }
+    }
+
+    private static final Comparator<Entry<LineLocation, LineBreakpointImpl>> BREAKPOINT_COMPARATOR = new Comparator<Entry<LineLocation, LineBreakpointImpl>>() {
+
+        @Override
+        public int compare(Entry<LineLocation, LineBreakpointImpl> entry1, Entry<LineLocation, LineBreakpointImpl> entry2) {
+            final LineLocation line1 = entry1.getKey();
+            final LineLocation line2 = entry2.getKey();
+            final int nameOrder = line1.getSource().getShortName().compareTo(line2.getSource().getShortName());
+            if (nameOrder != 0) {
+                return nameOrder;
+            }
+            return Integer.compare(line1.getLineNumber(), line2.getLineNumber());
+        }
+    };
+
+    private final DebugExecutionSupport executionSupport;
+    private final BreakpointCallback breakpointCallback;
+    private final WarningLog warningLog;
+
+    /**
+     * Map: Source lines ==> attached breakpoints. There may be no more than one line breakpoint
+     * associated with a line.
+     */
+    private final Map<LineLocation, LineBreakpointImpl> lineToBreakpoint = new HashMap<>();
+
+    /**
+     * A map of {@link LineLocation} to a collection of {@link Probe}s. This list must be
+     * initialized and filled prior to being used by this class.
+     */
+    private final LineToProbesMap lineToProbesMap;
+
+    /**
+     * Globally suspends all line breakpoint activity when {@code false}, ignoring whether
+     * individual breakpoints are enabled.
+     */
+    @CompilationFinal private boolean breakpointsActive = true;
+    private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active");
+
+    LineBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) {
+        this.executionSupport = executionSupport;
+        this.breakpointCallback = breakpointCallback;
+        this.warningLog = warningLog;
+
+        lineToProbesMap = new LineToProbesMap();
+        lineToProbesMap.install();
+
+        Probe.addProbeListener(new DefaultProbeListener() {
+
+            @Override
+            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+                if (tag == StandardSyntaxTag.STATEMENT) {
+                    final SourceSection sourceSection = probe.getProbedSourceSection();
+                    if (sourceSection != null) {
+                        final LineLocation lineLocation = sourceSection.getLineLocation();
+                        if (lineLocation != null) {
+                            // A Probe with line location tagged STATEMENT we haven't seen before.
+                            final LineBreakpointImpl breakpoint = lineToBreakpoint.get(lineLocation);
+                            if (breakpoint != null) {
+                                try {
+                                    breakpoint.attach(probe);
+                                } catch (DebugException e) {
+                                    warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
+                                    if (TRACE) {
+                                        OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Globally enables line breakpoint activity; all breakpoints are ignored when set to
+     * {@code false}. When set to {@code true}, the enabled/disabled status of each breakpoint
+     * determines whether it will trigger when flow of execution reaches it.
+     *
+     * @param breakpointsActive
+     */
+    void setActive(boolean breakpointsActive) {
+        if (this.breakpointsActive != breakpointsActive) {
+            breakpointsActiveUnchanged.invalidate();
+            this.breakpointsActive = breakpointsActive;
+        }
+    }
+
+    /**
+     * Returns the (not yet disposed) breakpoint by id; null if none.
+     */
+    LineBreakpoint find(long id) {
+        for (LineBreakpoint breakpoint : lineToBreakpoint.values()) {
+            if (breakpoint.getId() == id) {
+                return breakpoint;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets all current line breakpoints,regardless of status; sorted and modification safe.
+     */
+    List<LineBreakpoint> getAll() {
+        ArrayList<Entry<LineLocation, LineBreakpointImpl>> entries = new ArrayList<>(lineToBreakpoint.entrySet());
+        Collections.sort(entries, BREAKPOINT_COMPARATOR);
+
+        final ArrayList<LineBreakpoint> breakpoints = new ArrayList<>(entries.size());
+        for (Entry<LineLocation, LineBreakpointImpl> entry : entries) {
+            breakpoints.add(entry.getValue());
+        }
+        return breakpoints;
+    }
+
+    /**
+     * Creates a new line breakpoint if one doesn't already exist. If one does exist, then resets
+     * the <em>ignore count</em>.
+     *
+     * @param lineLocation where to set the breakpoint
+     * @param ignoreCount number of initial hits before the breakpoint starts causing breaks.
+     * @param oneShot whether the breakpoint should dispose itself after one hit
+     * @return a possibly new breakpoint
+     * @throws DebugException if a breakpoint already exists at the location and the ignore count is
+     *             the same
+     */
+    LineBreakpoint create(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) throws DebugException {
+
+        LineBreakpointImpl breakpoint = lineToBreakpoint.get(lineLocation);
+
+        if (breakpoint == null) {
+            breakpoint = new LineBreakpointImpl(groupId, ignoreCount, lineLocation, oneShot);
+
+            if (TRACE) {
+                trace("NEW " + breakpoint.getShortDescription());
+            }
+
+            lineToBreakpoint.put(lineLocation, breakpoint);
+
+            for (Probe probe : lineToProbesMap.findProbes(lineLocation)) {
+                if (probe.isTaggedAs(StandardSyntaxTag.STATEMENT)) {
+                    breakpoint.attach(probe);
+                    break;
+                }
+            }
+        } else {
+            if (ignoreCount == breakpoint.getIgnoreCount()) {
+                throw new DebugException(BREAKPOINT_NAME + " already set at line " + lineLocation);
+            }
+            breakpoint.setIgnoreCount(ignoreCount);
+            if (TRACE) {
+                trace("CHANGED ignoreCount %s", breakpoint.getShortDescription());
+            }
+        }
+        return breakpoint;
+    }
+
+    /**
+     * Returns the {@link LineBreakpoint} for a given line. There should only ever be one breakpoint
+     * per line.
+     *
+     * @param lineLocation The {@link LineLocation} to get the breakpoint for.
+     * @return The breakpoint for the given line.
+     */
+    LineBreakpoint get(LineLocation lineLocation) {
+        return lineToBreakpoint.get(lineLocation);
+    }
+
+    /**
+     * Removes the associated instrumentation for all one-shot breakpoints only.
+     */
+    void disposeOneShots() {
+        List<LineBreakpointImpl> breakpoints = new ArrayList<>(lineToBreakpoint.values());
+        for (LineBreakpointImpl breakpoint : breakpoints) {
+            if (breakpoint.isOneShot()) {
+                breakpoint.dispose();
+            }
+        }
+    }
+
+    /**
+     * Removes all knowledge of a breakpoint, presumed disposed.
+     */
+    private void forget(LineBreakpointImpl breakpoint) {
+        lineToBreakpoint.remove(breakpoint.getLineLocation());
+    }
+
+    /**
+     * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
+     * probe at the designated source location.
+     */
+    private final class LineBreakpointImpl extends LineBreakpoint implements AdvancedInstrumentResultListener {
+
+        private static final String SHOULD_NOT_HAPPEN = "LineBreakpointImpl:  should not happen";
+
+        private final LineLocation lineLocation;
+
+        // Cached assumption that the global status of line breakpoint activity has not changed.
+        private Assumption breakpointsActiveAssumption;
+
+        // Whether this breakpoint is enable/disabled
+        @CompilationFinal private boolean isEnabled;
+        private Assumption enabledUnchangedAssumption;
+
+        private String conditionExpr;
+
+        /**
+         * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
+         * {@code null} if not attached.
+         */
+        private List<Instrument> instruments = new ArrayList<>();
+
+        public LineBreakpointImpl(int groupId, int ignoreCount, LineLocation lineLocation, boolean oneShot) {
+            super(ENABLED_UNRESOLVED, groupId, ignoreCount, oneShot);
+            this.lineLocation = lineLocation;
+
+            this.breakpointsActiveAssumption = LineBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
+            this.isEnabled = true;
+            this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption(BREAKPOINT_NAME + " enabled state unchanged");
+        }
+
+        @Override
+        public boolean isEnabled() {
+            return isEnabled;
+        }
+
+        @Override
+        public void setEnabled(boolean enabled) {
+            if (enabled != isEnabled) {
+                switch (getState()) {
+                    case ENABLED:
+                        assert !enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(false);
+                        changeState(DISABLED);
+                        break;
+                    case ENABLED_UNRESOLVED:
+                        assert !enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(false);
+                        changeState(DISABLED_UNRESOLVED);
+                        break;
+                    case DISABLED:
+                        assert enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(true);
+                        changeState(ENABLED);
+                        break;
+                    case DISABLED_UNRESOLVED:
+                        assert enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(true);
+                        changeState(DISABLED_UNRESOLVED);
+                        break;
+                    case DISPOSED:
+                        assert false : "breakpoint disposed";
+                        break;
+                    default:
+                        assert false : SHOULD_NOT_HAPPEN;
+                        break;
+                }
+            }
+        }
+
+        @Override
+        public void setCondition(String expr) throws DebugException {
+            if (this.conditionExpr != null || expr != null) {
+                // De-instrument the Probes instrumented by this breakpoint
+                final ArrayList<Probe> probes = new ArrayList<>();
+                for (Instrument instrument : instruments) {
+                    probes.add(instrument.getProbe());
+                    instrument.dispose();
+                }
+                instruments.clear();
+                this.conditionExpr = expr;
+                // Re-instrument the probes previously instrumented
+                for (Probe probe : probes) {
+                    attach(probe);
+                }
+            }
+        }
+
+        @Override
+        public String getCondition() {
+            return conditionExpr;
+        }
+
+        @Override
+        public void dispose() {
+            if (getState() != DISPOSED) {
+                for (Instrument instrument : instruments) {
+                    instrument.dispose();
+                }
+                changeState(DISPOSED);
+                LineBreakpointFactory.this.forget(this);
+            }
+        }
+
+        private void attach(Probe newProbe) throws DebugException {
+            if (getState() == DISPOSED) {
+                throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
+            }
+            Instrument newInstrument = null;
+            if (conditionExpr == null) {
+                newInstrument = Instrument.create(new UnconditionalLineBreakInstrumentListener(), BREAKPOINT_NAME);
+            } else {
+                newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
+            }
+            newProbe.attach(newInstrument);
+            instruments.add(newInstrument);
+            changeState(isEnabled ? ENABLED : DISABLED);
+        }
+
+        private void doSetEnabled(boolean enabled) {
+            if (this.isEnabled != enabled) {
+                enabledUnchangedAssumption.invalidate();
+                this.isEnabled = enabled;
+            }
+        }
+
+        private String getShortDescription() {
+            return BREAKPOINT_NAME + "@" + getLineLocation().getShortDescription();
+        }
+
+        private void changeState(BreakpointState after) {
+            if (TRACE) {
+                trace("STATE %s-->%s %s", getState().getName(), after.getName(), getShortDescription());
+            }
+            setState(after);
+        }
+
+        private void doBreak(Node node, VirtualFrame vFrame) {
+            if (incrHitCountCheckIgnore()) {
+                breakpointCallback.haltedAt(node, vFrame.materialize(), BREAKPOINT_NAME);
+            }
+        }
+
+        /**
+         * Receives notification from the attached instrument that execution is about to enter node
+         * where the breakpoint is set. Designed so that when in the fast path, there is either an
+         * unconditional "halt" call to the debugger or nothing.
+         */
+        private void nodeEnter(Node astNode, VirtualFrame vFrame) {
+
+            // Deopt if the global active/inactive flag has changed
+            try {
+                this.breakpointsActiveAssumption.check();
+            } catch (InvalidAssumptionException ex) {
+                this.breakpointsActiveAssumption = LineBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
+            }
+
+            // Deopt if the enabled/disabled state of this breakpoint has changed
+            try {
+                this.enabledUnchangedAssumption.check();
+            } catch (InvalidAssumptionException ex) {
+                this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption("LineBreakpoint enabled state unchanged");
+            }
+
+            if (LineBreakpointFactory.this.breakpointsActive && this.isEnabled) {
+                if (isOneShot()) {
+                    dispose();
+                }
+                LineBreakpointImpl.this.doBreak(astNode, vFrame);
+            }
+        }
+
+        public void notifyResult(Node node, VirtualFrame vFrame, Object result) {
+            final boolean condition = (Boolean) result;
+            if (TRACE) {
+                trace("breakpoint condition = %b  %s", condition, getShortDescription());
+            }
+            if (condition) {
+                nodeEnter(node, vFrame);
+            }
+        }
+
+        @TruffleBoundary
+        public void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
+            warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
+            if (TRACE) {
+                trace("breakpoint failure = %s  %s", ex.toString(), getShortDescription());
+            }
+            // Take the breakpoint if evaluation fails.
+            nodeEnter(node, vFrame);
+        }
+
+        @Override
+        public String getLocationDescription() {
+            return "Line: " + lineLocation.getShortDescription();
+        }
+
+        @Override
+        public LineLocation getLineLocation() {
+            return lineLocation;
+        }
+
+        private final class UnconditionalLineBreakInstrumentListener extends DefaultStandardInstrumentListener {
+
+            @Override
+            public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+                LineBreakpointImpl.this.nodeEnter(node, vFrame);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpoint.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import com.oracle.truffle.api.instrument.*;
+
+// TODO (mlvdv) generic?
+/**
+ * A breakpoint associated with a {@link SyntaxTag}.
+ *
+ * @see DebugEngine
+ */
+public abstract class TagBreakpoint extends Breakpoint {
+
+    TagBreakpoint(BreakpointState state, int groupId, int ignoreCount, boolean isOneShot) {
+        super(state, groupId, ignoreCount, isOneShot);
+    }
+
+    /**
+     * Gets the tag that specifies where this breakpoint will trigger.
+     */
+    public abstract SyntaxTag getTag();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/TagBreakpointFactory.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.engine;
+
+import static com.oracle.truffle.tools.debug.engine.Breakpoint.BreakpointState.*;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.tools.debug.engine.DebugEngine.BreakpointCallback;
+import com.oracle.truffle.tools.debug.engine.DebugEngine.WarningLog;
+
+// TODO (mlvdv) some common functionality could be factored out of this and LineBreakpointSupport
+
+/**
+ * Support class for creating and managing "Tag Breakpoints". A Tag Breakpoint halts execution just
+ * before reaching any node whose Probe carries a specified {@linkplain SyntaxTag Tag}.
+ * <p>
+ * The {@linkplain Probe#setBeforeTagTrap(SyntaxTagTrap) Tag Trap}, which is built directly into the
+ * Instrumentation Framework, does the same thing more efficiently, but there may only be one Tag
+ * Trap active at a time. Any number of tag breakpoints may coexist with the Tag Trap, but it would
+ * be confusing to have a Tag Breakpoint set for the same Tag as the current Tag Trap.
+ * <p>
+ * Notes:
+ * <ol>
+ * <li>Only one Tag Breakpoint can be active for a specific {@linkplain SyntaxTag Tag}.</li>
+ * <li>A newly created breakpoint looks for probes matching the tag, attaches to them if found by
+ * installing an {@link Instrument}.</li>
+ * <li>When Truffle "splits" or otherwise copies an AST, any attached {@link Instrument} will be
+ * copied along with the rest of the AST and will call back to the same breakpoint.</li>
+ * <li>When notification is received that the breakpoint's Tag has been newly added to a Node, then
+ * the breakpoint will attach a new Instrument at the probe to activate the breakpoint at that
+ * location.</li>
+ * <li>A breakpoint may have multiple Instruments deployed, one attached to each Probe that holds
+ * the breakpoint's tag; this might happen when a source is reloaded.</li>
+ * </ol>
+ */
+final class TagBreakpointFactory {
+
+    private static final boolean TRACE = false;
+    private static final PrintStream OUT = System.out;
+
+    private static final String BREAKPOINT_NAME = "TAG BREAKPOINT";
+
+    private static void trace(String format, Object... args) {
+        if (TRACE) {
+            OUT.println(String.format("%s: %s", BREAKPOINT_NAME, String.format(format, args)));
+        }
+    }
+
+    private static final Comparator<Entry<SyntaxTag, TagBreakpointImpl>> BREAKPOINT_COMPARATOR = new Comparator<Entry<SyntaxTag, TagBreakpointImpl>>() {
+
+        @Override
+        public int compare(Entry<SyntaxTag, TagBreakpointImpl> entry1, Entry<SyntaxTag, TagBreakpointImpl> entry2) {
+            return entry1.getKey().name().compareTo(entry2.getKey().name());
+        }
+    };
+
+    private final DebugExecutionSupport executionSupport;
+    private final BreakpointCallback breakpointCallback;
+    private final WarningLog warningLog;
+
+    /**
+     * Map: Tags ==> Tag Breakpoints. There may be no more than one breakpoint per Tag.
+     */
+    private final Map<SyntaxTag, TagBreakpointImpl> tagToBreakpoint = new HashMap<>();
+
+    /**
+     * Globally suspends all line breakpoint activity when {@code false}, ignoring whether
+     * individual breakpoints are enabled.
+     */
+    @CompilationFinal private boolean breakpointsActive = true;
+    private final CyclicAssumption breakpointsActiveUnchanged = new CyclicAssumption(BREAKPOINT_NAME + " globally active");
+
+    TagBreakpointFactory(DebugExecutionSupport executionSupport, BreakpointCallback breakpointCallback, WarningLog warningLog) {
+        this.executionSupport = executionSupport;
+        this.breakpointCallback = breakpointCallback;
+        this.warningLog = warningLog;
+
+        Probe.addProbeListener(new DefaultProbeListener() {
+
+            @Override
+            public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+                final TagBreakpointImpl breakpoint = tagToBreakpoint.get(tag);
+                if (breakpoint != null) {
+                    try {
+                        breakpoint.attach(probe);
+                    } catch (DebugException e) {
+                        warningLog.addWarning(BREAKPOINT_NAME + " failure attaching to newly tagged Probe: " + e.getMessage());
+                        if (TRACE) {
+                            OUT.println(BREAKPOINT_NAME + " failure: " + e.getMessage());
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Globally enables tag breakpoint activity; all breakpoints are ignored when set to
+     * {@code false}. When set to {@code true}, the enabled/disabled status of each breakpoint
+     * determines whether it will trigger when flow of execution reaches it.
+     *
+     * @param breakpointsActive
+     */
+    void setActive(boolean breakpointsActive) {
+        if (this.breakpointsActive != breakpointsActive) {
+            breakpointsActiveUnchanged.invalidate();
+            this.breakpointsActive = breakpointsActive;
+        }
+    }
+
+    /**
+     * Returns the (not yet disposed) breakpoint by id, if any; null if none.
+     */
+    TagBreakpoint find(long id) {
+        for (TagBreakpointImpl breakpoint : tagToBreakpoint.values()) {
+            if (breakpoint.getId() == id) {
+                return breakpoint;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets all current tag breakpoints,regardless of status; sorted and modification safe.
+     */
+    List<TagBreakpoint> getAll() {
+        ArrayList<Entry<SyntaxTag, TagBreakpointImpl>> entries = new ArrayList<>(tagToBreakpoint.entrySet());
+        Collections.sort(entries, BREAKPOINT_COMPARATOR);
+
+        final ArrayList<TagBreakpoint> breakpoints = new ArrayList<>(entries.size());
+        for (Entry<SyntaxTag, TagBreakpointImpl> entry : entries) {
+            breakpoints.add(entry.getValue());
+        }
+        return breakpoints;
+    }
+
+    /**
+     * Creates a new tag breakpoint if one doesn't already exist. If one does exist, then resets the
+     * <em>ignore count</em>.
+     *
+     * @param tag where to set the breakpoint
+     * @param ignoreCount number of initial hits before the breakpoint starts causing breaks.
+     * @param oneShot whether the breakpoint should dispose itself after one hit
+     * @return a possibly new breakpoint
+     * @throws DebugException if a breakpoint already exists for the tag and the ignore count is the
+     *             same
+     */
+    TagBreakpoint create(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) throws DebugException {
+
+        TagBreakpointImpl breakpoint = tagToBreakpoint.get(tag);
+
+        if (breakpoint == null) {
+            breakpoint = new TagBreakpointImpl(groupId, ignoreCount, tag, oneShot);
+
+            if (TRACE) {
+                trace("NEW " + breakpoint.getShortDescription());
+            }
+
+            tagToBreakpoint.put(tag, breakpoint);
+
+            for (Probe probe : Probe.findProbesTaggedAs(tag)) {
+                breakpoint.attach(probe);
+            }
+        } else {
+            if (ignoreCount == breakpoint.getIgnoreCount()) {
+                throw new DebugException(BREAKPOINT_NAME + " already set for tag " + tag.name());
+            }
+            breakpoint.setIgnoreCount(ignoreCount);
+            if (TRACE) {
+                trace("CHANGED ignoreCount %s", breakpoint.getShortDescription());
+            }
+        }
+        return breakpoint;
+    }
+
+    /**
+     * Returns the {@link TagBreakpoint} for a given tag, {@code null} if none.
+     */
+    TagBreakpoint get(SyntaxTag tag) {
+        return tagToBreakpoint.get(tag);
+    }
+
+    /**
+     * Removes the associated instrumentation for all one-shot breakpoints only.
+     */
+    void disposeOneShots() {
+        List<TagBreakpointImpl> breakpoints = new ArrayList<>(tagToBreakpoint.values());
+        for (TagBreakpointImpl breakpoint : breakpoints) {
+            if (breakpoint.isOneShot()) {
+                breakpoint.dispose();
+            }
+        }
+    }
+
+    /**
+     * Removes all knowledge of a breakpoint, presumed disposed.
+     */
+    private void forget(TagBreakpointImpl breakpoint) {
+        tagToBreakpoint.remove(breakpoint.getTag());
+    }
+
+    /**
+     * Concrete representation of a line breakpoint, implemented by attaching an instrument to a
+     * probe at the designated source location.
+     */
+    private final class TagBreakpointImpl extends TagBreakpoint implements AdvancedInstrumentResultListener {
+
+        private static final String SHOULD_NOT_HAPPEN = "TagBreakpointImpl:  should not happen";
+
+        private final SyntaxTag tag;
+
+        // Cached assumption that the global status of tag breakpoint activity has not changed.
+        private Assumption breakpointsActiveAssumption;
+
+        // Whether this breakpoint is enable/disabled
+        @CompilationFinal private boolean isEnabled;
+        private Assumption enabledUnchangedAssumption;
+
+        private String conditionExpr;
+
+        /**
+         * The instrument(s) that this breakpoint currently has attached to a {@link Probe}:
+         * {@code null} if not attached.
+         */
+        private List<Instrument> instruments = new ArrayList<>();
+
+        private TagBreakpointImpl(int groupId, int ignoreCount, SyntaxTag tag, boolean oneShot) {
+            super(ENABLED, groupId, ignoreCount, oneShot);
+            this.tag = tag;
+            this.breakpointsActiveAssumption = TagBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
+            this.isEnabled = true;
+            this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption(BREAKPOINT_NAME + " enabled state unchanged");
+        }
+
+        @Override
+        public boolean isEnabled() {
+            return isEnabled;
+        }
+
+        @Override
+        public void setEnabled(boolean enabled) {
+            // Tag Breakpoints are never unresolved
+            if (enabled != isEnabled) {
+                switch (getState()) {
+                    case ENABLED:
+                        assert !enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(false);
+                        changeState(DISABLED);
+                        break;
+                    case DISABLED:
+                        assert enabled : SHOULD_NOT_HAPPEN;
+                        doSetEnabled(true);
+                        changeState(ENABLED);
+                        break;
+                    case DISPOSED:
+                        assert false : "breakpoint disposed";
+                        break;
+                    case ENABLED_UNRESOLVED:
+                    case DISABLED_UNRESOLVED:
+                    default:
+                        assert false : SHOULD_NOT_HAPPEN;
+                        break;
+                }
+            }
+        }
+
+        @Override
+        public void setCondition(String expr) throws DebugException {
+            if (this.conditionExpr != null || expr != null) {
+                // De-instrument the Probes instrumented by this breakpoint
+                final ArrayList<Probe> probes = new ArrayList<>();
+                for (Instrument instrument : instruments) {
+                    probes.add(instrument.getProbe());
+                    instrument.dispose();
+                }
+                instruments.clear();
+                this.conditionExpr = expr;
+                // Re-instrument the probes previously instrumented
+                for (Probe probe : probes) {
+                    attach(probe);
+                }
+            }
+        }
+
+        @Override
+        public String getCondition() {
+            return conditionExpr;
+        }
+
+        @Override
+        public void dispose() {
+            if (getState() != DISPOSED) {
+                for (Instrument instrument : instruments) {
+                    instrument.dispose();
+                }
+                changeState(DISPOSED);
+                TagBreakpointFactory.this.forget(this);
+            }
+        }
+
+        private void attach(Probe newProbe) throws DebugException {
+            if (getState() == DISPOSED) {
+                throw new IllegalStateException("Attempt to attach a disposed " + BREAKPOINT_NAME);
+            }
+            Instrument newInstrument = null;
+            if (conditionExpr == null) {
+                newInstrument = Instrument.create(new UnconditionalTagBreakInstrumentListener(), BREAKPOINT_NAME);
+            } else {
+                newInstrument = Instrument.create(this, executionSupport.createAdvancedInstrumentRootFactory(conditionExpr, this), Boolean.class, BREAKPOINT_NAME);
+            }
+            newProbe.attach(newInstrument);
+            instruments.add(newInstrument);
+            changeState(isEnabled ? ENABLED : DISABLED);
+        }
+
+        private void doSetEnabled(boolean enabled) {
+            if (this.isEnabled != enabled) {
+                enabledUnchangedAssumption.invalidate();
+                this.isEnabled = enabled;
+            }
+        }
+
+        private String getShortDescription() {
+            return BREAKPOINT_NAME + "@" + tag.name();
+        }
+
+        private void changeState(BreakpointState after) {
+            if (TRACE) {
+                trace("STATE %s-->%s %s", getState().getName(), after.getName(), getShortDescription());
+            }
+            setState(after);
+        }
+
+        private void doBreak(Node node, VirtualFrame vFrame) {
+            if (incrHitCountCheckIgnore()) {
+                breakpointCallback.haltedAt(node, vFrame.materialize(), BREAKPOINT_NAME);
+            }
+        }
+
+        /**
+         * Receives notification from the attached instrument that execution is about to enter node
+         * where the breakpoint is set. Designed so that when in the fast path, there is either an
+         * unconditional "halt" call to the debugger or nothing.
+         */
+        private void nodeEnter(Node astNode, VirtualFrame vFrame) {
+
+            // Deopt if the global active/inactive flag has changed
+            try {
+                this.breakpointsActiveAssumption.check();
+            } catch (InvalidAssumptionException ex) {
+                this.breakpointsActiveAssumption = TagBreakpointFactory.this.breakpointsActiveUnchanged.getAssumption();
+            }
+
+            // Deopt if the enabled/disabled state of this breakpoint has changed
+            try {
+                this.enabledUnchangedAssumption.check();
+            } catch (InvalidAssumptionException ex) {
+                this.enabledUnchangedAssumption = Truffle.getRuntime().createAssumption("LineBreakpoint enabled state unchanged");
+            }
+
+            if (TagBreakpointFactory.this.breakpointsActive && this.isEnabled) {
+                if (isOneShot()) {
+                    dispose();
+                }
+                TagBreakpointImpl.this.doBreak(astNode, vFrame);
+            }
+
+        }
+
+        public void notifyResult(Node node, VirtualFrame vFrame, Object result) {
+            final boolean condition = (Boolean) result;
+            if (TRACE) {
+                trace("breakpoint condition = %b  %s", condition, getShortDescription());
+            }
+            if (condition) {
+                nodeEnter(node, vFrame);
+            }
+        }
+
+        public void notifyFailure(Node node, VirtualFrame vFrame, RuntimeException ex) {
+            warningLog.addWarning(String.format("Exception in %s:  %s", getShortDescription(), ex.getMessage()));
+            if (TRACE) {
+                trace("breakpoint failure = %s  %s", ex.toString(), getShortDescription());
+            }
+            // Take the breakpoint if evaluation fails.
+            nodeEnter(node, vFrame);
+        }
+
+        @Override
+        public String getLocationDescription() {
+            return "Tag " + tag.name();
+        }
+
+        @Override
+        public SyntaxTag getTag() {
+            return tag;
+        }
+
+        private final class UnconditionalTagBreakInstrumentListener extends DefaultStandardInstrumentListener {
+
+            @Override
+            public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+                TagBreakpointImpl.this.nodeEnter(node, vFrame);
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.engine/src/com/oracle/truffle/tools/debug/engine/package-info.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This package contains the shared (language-agnostic) support for implementing debuggers
+ * that work with Truffle-implemented languages.
+ * <p>
+ * This implementation is made possible by the general purpose Instrumentation Framework built
+ * into the Truffle platform.  Some online documentation for the Instrumentation Framework is available
+ * online:
+ * <quote>
+ * <a href="https://wiki.openjdk.java.net/display/Graal/Instrumentation+API">https://wiki.openjdk.java.net/display/Graal/Instrumentation+API</a>
+ * </quote>
+ * <p>
+ * Debugging services for a Truffle-implemented language are provided by creating an instance
+ * of {@link com.oracle.truffle.tools.debug.engine.DebugEngine} specialized for a specific language.  The DebugEngine can:
+ * <ul>
+ * <li>Load and run sources in the language</li>
+ * <li>Set breakpoints possibly with conditions and other attributes, on source lines</li>
+ * <li>Navigate by Continue, StepIn, StepOver, or StepOut</li>
+ * <li>Examine the execution stack</li>
+ * <li>Examine the contents of a stack frame</li>
+ * <li>Evaluate a code fragment in the context of a stack frame</li>
+ * </ul>
+ * <p>
+ * Specialization of the DebugEngine for a Truffle-implemented language takes several forms:
+ * <ol>
+ * <li>A specification from the language implementor that adds Instrumentation "tags" to the nodes
+ * that a debugger should know about, for example Statements, Calls, and Throws</li>
+ * <li>Methods to run programs/scripts generally, and more specifically run text fragments in the context of
+ * a particular frame/Node in a halted Truffle execution</li>
+ * <li>Utility methods, such as providing textual displays of Objects that represent values in the language</li>
+ * </ol>
+ * <p>
+ * <strong>Note:</strong> Both the functionality and API for this package are under active development.
+ * <p>
+ * @see com.oracle.truffle.api.instrument
+ */
+package com.oracle.truffle.tools.debug.engine;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLClient.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell;
+
+/**
+ * The client side of a simple message-based protocol for a possibly remote language
+ * Read-Eval-Print-Loop.
+ */
+public interface REPLClient {
+
+    /**
+     * Accepts a reply from the server; there may be more than one reply in response to a request.
+     */
+    REPLMessage receive(REPLMessage reply);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLMessage.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * A message for communication between a Read-Eval-Print-Loop server associated with a language
+ * implementation and a possibly remote client.
+ *
+ * @see REPLClient
+ * @see REPLServer
+ */
+public final class REPLMessage {
+
+    // Some standard keys and values
+    public static final String AST = "ast";
+    public static final String AST_DEPTH = "show-max-depth";
+    public static final String BACKTRACE = "backtrace";
+    public static final String BREAK_AT_LINE = "break-at-line";
+    public static final String BREAK_AT_LINE_ONCE = "break-at-line-once";
+    public static final String BREAK_AT_THROW = "break-at-throw";
+    public static final String BREAK_AT_THROW_ONCE = "break-at-throw-once";
+    public static final String BREAKPOINT_CONDITION = "breakpoint-condition";
+    public static final String BREAKPOINT_GROUP_ID = "breakpoint-group-id";
+    public static final String BREAKPOINT_HIT_COUNT = "breakpoint-hit-count";
+    public static final String BREAKPOINT_ID = "breakpoint-id";
+    public static final String BREAKPOINT_IGNORE_COUNT = "breakpoint-ignore-count";
+    public static final String BREAKPOINT_INFO = "breakpoint-info";
+    public static final String BREAKPOINT_STATE = "breakpoint-state";
+    public static final String CLEAR_BREAK = "clear-breakpoint";
+    public static final String CODE = "code";
+    public static final String CONTINUE = "continue";
+    public static final String DEBUG_LEVEL = "debug-level";
+    public static final String DELETE_BREAK = "delete-breakpoint";
+    public static final String DISABLE_BREAK = "disable-breakpoint";
+    public static final String DISPLAY_MSG = "displayable-message";
+    public static final String DOWN = "down";
+    public static final String ENABLE_BREAK = "enable-breakpoint";
+    public static final String EVAL = "eval";
+    public static final String FAILED = "failed";
+    public static final String FILE = "file";
+    public static final String FILE_PATH = "path";
+    public static final String FRAME = "frame";
+    public static final String FRAME_INFO = "frame-info";
+    public static final String FRAME_NUMBER = "frame-number";
+    public static final String INFO = "info";
+    public static final String INFO_KEY = "info-key";
+    public static final String INFO_VALUE = "info-value";
+    public static final String KILL = "kill";
+    public static final String LANGUAGE = "language";
+    public static final String LINE_NUMBER = "line-number";
+    public static final String LIST = "list";
+    public static final String LOAD_RUN = "load-run-source";
+    public static final String LOAD_STEP = "load-step-into-source";
+    public static final String METHOD_NAME = "method-name";
+    public static final String OP = "op";
+    public static final String OPTION = "option";
+    public static final String QUIT = "quit";
+    public static final String REPEAT = "repeat";
+    public static final String SET = "set";
+    public static final String SET_BREAK_CONDITION = "set-breakpoint-condition";
+    public static final String SOURCE_LINE_TEXT = "source-line-text";
+    public static final String SOURCE_LOCATION = "source-location";
+    public static final String SOURCE_NAME = "source-name";
+    public static final String SOURCE_TEXT = "source-text";
+    public static final String STACK_SIZE = "stack-size";
+    public static final String STATUS = "status";
+    public static final String STEP_INTO = "step-into";
+    public static final String STEP_OUT = "step-out";
+    public static final String STEP_OVER = "step-over";
+    public static final String STOPPED = "stopped";
+    public static final String SUB = "sub";
+    public static final String SUBTREE = "subtree";
+    public static final String SUCCEEDED = "succeeded";
+    public static final String TOPIC = "topic";
+    public static final String TRUFFLE = "truffle";
+    public static final String TRUFFLE_AST = "truffle-ast";
+    public static final String TRUFFLE_NODE = "truffle-node";
+    public static final String TRUFFLE_SUBTREE = "truffle-subtree";
+    public static final String UNSET_BREAK_CONDITION = "unset-breakpoint-condition";
+    public static final String UP = "up";
+    public static final String VALUE = "value";
+    public static final String WARNINGS = "warnings";
+    private final Map<String, String> map;
+
+    /**
+     * Creates an empty REPL message.
+     */
+    public REPLMessage() {
+        this.map = new TreeMap<>();
+    }
+
+    /**
+     * Creates a REPL message with an initial entry.
+     */
+    public REPLMessage(String key, String value) {
+        this();
+        map.put(key, value);
+    }
+
+    public REPLMessage(REPLMessage message) {
+        this.map = new TreeMap<>(message.map);
+    }
+
+    public String get(String key) {
+        return map.get(key);
+    }
+
+    /**
+     * Returns the specified key value as an integer; {@code null} if missing or non-numeric.
+     */
+    public Integer getIntValue(String key) {
+        final String value = map.get(key);
+        if (value != null) {
+            try {
+                return Integer.parseInt(value);
+            } catch (NumberFormatException e) {
+
+            }
+        }
+        return null;
+    }
+
+    public String put(String key, String value) {
+        return map.put(key, value);
+    }
+
+    public String remove(String key) {
+        return map.remove(key);
+    }
+
+    public Set<String> keys() {
+        return map.keySet();
+    }
+
+    public void print(PrintStream out, String linePrefix) {
+        map.keySet();
+
+        for (Entry<String, String> entry : map.entrySet()) {
+            String value = entry.getValue();
+            if (value != null && value.length() > 50) {
+                value = value.substring(0, 50) + " ...";
+            }
+            out.println(linePrefix + entry.getKey() + " = \"" + value + "\"");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/REPLServer.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell;
+
+/**
+ * The server side of a simple message-based protocol for a possibly remote language
+ * Read-Eval-Print-Loop.
+ */
+public interface REPLServer {
+
+    /**
+     * Starts up a server; status returned in a message.
+     */
+    REPLMessage start();
+
+    /**
+     * Ask the server to handle a request. Return a non-empty array of messages to simulate remote
+     * operation where the protocol has possibly multiple messages being returned asynchronously in
+     * response to each request.
+     */
+    REPLMessage[] receive(REPLMessage request);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLClientContext.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+import java.util.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+/**
+ * Client context for interaction with a program halted by the {@link REPLServer}.
+ */
+public interface REPLClientContext {
+
+    /**
+     * The source code halted in this context.
+     */
+    Source source();
+
+    /**
+     * The 1-based line at which execution is halted in this context; 0 means unknown.
+     */
+    int lineNumber();
+
+    /**
+     * The Truffle stack where execution is halted in this context.
+     */
+    List<REPLFrame> frames();
+
+    /**
+     * The nesting level of the execution context: 0 means evaluating shell commands outside any
+     * executing program.
+     */
+    int level();
+
+    /**
+     * The source currently selected by the user; defaults to where halted.
+     */
+    Source getSelectedSource();
+
+    /**
+     * The frame number in this execution context currently selected by the user; defaults to 0.
+     */
+    int getSelectedFrameNumber();
+
+    /**
+     * Issue a command to the REPLServer that
+     * <ul>
+     * <li>can be specified by a single "op",</li>
+     * <li>produces information in the form of a single string, and</li>
+     * <li>has no effect on the execution state.</li>
+     * </ul>
+     */
+    String stringQuery(String op);
+
+    /**
+     * Sets a new "default" frame number for frame-related commands.
+     */
+    void selectFrameNumber(int frameNumber);
+
+    /**
+     * Sends an information message.
+     */
+    void displayInfo(String message);
+
+    void displayStack();
+
+    /**
+     * Send a message related to handling a command in this context.
+     */
+    void displayReply(String message);
+
+    /**
+     * Send a message related to failure while handling a command in this context.
+     */
+    void displayFailReply(String message);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLCommand.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+// TODO (mlvdv)  write a real command line parser
+abstract class REPLCommand {
+
+    private final String command;
+    private final String abbreviation;
+    private final String description;
+
+    public REPLCommand(String command, String abbreviation, String description) {
+        this.command = command;
+        this.abbreviation = abbreviation;
+        this.description = description;
+    }
+
+    public final String getCommand() {
+        return command;
+    }
+
+    public final String getAbbreviation() {
+        return abbreviation;
+    }
+
+    public final String getDescription() {
+        return description;
+    }
+
+    public String[] getHelp() {
+        return new String[]{getCommand() + ": " + getDescription()};
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLContinueException.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+class REPLContinueException extends RuntimeException {
+
+    private static final long serialVersionUID = 4763527450877123326L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLFrame.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+/**
+ * Information about a stack frame in the current {@link REPLClientContext}.
+ */
+interface REPLFrame {
+
+    /**
+     * Index of the frame.
+     */
+    int index();
+
+    /**
+     * File path; null if unknown.
+     */
+    String locationFilePath();
+
+    /**
+     * Line number of frame location; null if unknown.
+     */
+    Integer locationLineNumber();
+
+    /**
+     * Short description of the code location.
+     */
+    String locationDescription();
+
+    /**
+     * Name of the method body containing the location.
+     */
+    String name();
+
+    /**
+     * The line of text at the code location.
+     */
+    String sourceLineText();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLRemoteCommand.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,696 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+// TODO (mlvdv)  write a real command line parser
+public abstract class REPLRemoteCommand extends REPLCommand {
+
+    public REPLRemoteCommand(String command, String abbreviation, String description) {
+        super(command, abbreviation, description);
+    }
+
+    protected abstract REPLMessage createRequest(REPLClientContext context, String[] args);
+
+    void processReply(REPLClientContext context, REPLMessage[] replies) {
+        REPLMessage firstReply = replies[0];
+
+        if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+            final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
+            context.displayFailReply(result != null ? result : firstReply.toString());
+        } else {
+            final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
+            context.displayReply(result != null ? result : firstReply.toString());
+        }
+
+        for (int i = 1; i < replies.length; i++) {
+            REPLMessage reply = replies[i];
+            final String result = reply.get(REPLMessage.DISPLAY_MSG);
+            context.displayInfo(result != null ? result : reply.toString());
+        }
+    }
+
+    public static final REPLRemoteCommand BREAK_AT_LINE_CMD = new REPLRemoteCommand("break-at-line", "break", "Set a breakpoint") {
+
+        private final String[] help = {"break <n> [ignore=<n>] : set breakpoint at line <n> in current file", "break <filename>:<n> [ignore=<n>] : set breakpoint at line <n> in <filename>",
+                        " optionally ignore first <n> hits (default 0)"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            try {
+                final REPLineLocation lineLocation = REPLineLocation.parse(context, args);
+                final REPLMessage requestMessage = lineLocation.createMessage(REPLMessage.BREAK_AT_LINE);
+                int ignoreCount = 0;
+                if (args.length > 2) {
+                    final String ignoreText = args[2];
+                    if (ignoreText.equals("ignore")) {
+                        throw new IllegalArgumentException("No ignore count specified");
+                    }
+                    final String[] split = ignoreText.split("=");
+                    if (split.length == 2 && split[0].equals("ignore")) {
+                        try {
+                            ignoreCount = Integer.parseInt(split[1]);
+                            if (ignoreCount < 0) {
+                                throw new IllegalArgumentException("Illegal ignore count: " + split[1]);
+                            }
+                        } catch (NumberFormatException e) {
+                            throw new IllegalArgumentException("No ignore count specified");
+                        }
+                    } else {
+                        throw new IllegalArgumentException("Unrecognized argument \"" + ignoreText + "\"");
+                    }
+                }
+                requestMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(ignoreCount));
+                return requestMessage;
+            } catch (IllegalArgumentException ex) {
+                context.displayFailReply(ex.getMessage());
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final String number = firstReply.get(REPLMessage.BREAKPOINT_ID);
+                final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
+                final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
+                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + number + " set at " + fileName + ":" + lineNumber);
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand BREAK_AT_LINE_ONCE_CMD = new REPLRemoteCommand("break-at-line-once", "break1", "Set a one-shot breakpoint") {
+
+        private final String[] help = {"break <n>: set one-shot breakpoint at line <n> in current file", "break <filename>:<n>: set one-shot breakpoint at line <n> in current file"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            try {
+                return REPLineLocation.parse(context, args).createMessage(REPLMessage.BREAK_AT_LINE_ONCE);
+            } catch (IllegalArgumentException ex) {
+                context.displayFailReply(ex.getMessage());
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
+                final String lineNumber = firstReply.get(REPLMessage.LINE_NUMBER);
+                firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint set at " + fileName + ":" + lineNumber);
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand BREAK_AT_THROW_CMD = new REPLRemoteCommand("break-at-throw", "breakthrow", "Break at any throw") {
+
+        private final String[] help = {"break-at-throw: set breakpoint on any throw"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint at any throw set");
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand BREAK_AT_THROW_ONCE_CMD = new REPLRemoteCommand("break-at-throw-once", "break1throw", "Break once at any throw") {
+
+        private final String[] help = {"break-at-throw: set one-short breakpoint on any throw"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.BREAK_AT_THROW_ONCE);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                firstReply.put(REPLMessage.DISPLAY_MSG, "one-shot breakpoint at any throw set");
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand CLEAR_BREAK_CMD = new REPLRemoteCommand("clear", null, "Clear a breakpoint") {
+
+        private final String[] help = {"clear <n>: clear breakpoint number <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length == 1) {
+                context.displayFailReply("breakpoint number not speciified:  \"break <n>\"");
+            } else if (args.length > 2) {
+                context.displayFailReply("breakpoint number not understood:  \"break <n>\"");
+            } else {
+                try {
+                    final int breakpointNumber = Integer.parseInt(args[1]);
+                    final REPLMessage request = new REPLMessage();
+                    request.put(REPLMessage.OP, REPLMessage.CLEAR_BREAK);
+                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+                    return request;
+                } catch (IllegalArgumentException ex) {
+                    context.displayFailReply(ex.getMessage());
+                }
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
+                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " cleared");
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand CONDITION_BREAK_CMD = new REPLRemoteCommand("cond", null, "Set new condition on a breakpoint") {
+
+        private final String[] help = {"cond <n> [expr]: sets new condition on breakpoint number <n>; make unconditional if no [expr]"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length == 1) {
+                context.displayFailReply("breakpoint number not speciified:  \"cond <n>\"");
+            } else {
+                try {
+                    final int breakpointNumber = Integer.parseInt(args[1]);
+                    final REPLMessage request = new REPLMessage();
+                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+                    if (args.length == 2) {
+                        request.put(REPLMessage.OP, REPLMessage.UNSET_BREAK_CONDITION);
+                    } else {
+                        final StringBuilder exprBuilder = new StringBuilder();
+                        for (int i = 2; i < args.length; i++) {
+                            exprBuilder.append(args[i]).append(" ");
+                        }
+                        request.put(REPLMessage.BREAKPOINT_CONDITION, exprBuilder.toString().trim());
+                        request.put(REPLMessage.OP, REPLMessage.SET_BREAK_CONDITION);
+                    }
+                    return request;
+                } catch (IllegalArgumentException ex) {
+                    context.displayFailReply(ex.getMessage());
+                }
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
+                final String condition = firstReply.get(REPLMessage.BREAKPOINT_CONDITION);
+                if (condition == null) {
+                    firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition cleared");
+                } else {
+                    firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " condition=\"" + condition + "\"");
+                }
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand CONTINUE_CMD = new REPLRemoteCommand("continue", "c", "Continue execution") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.CONTINUE);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+
+            throw new REPLContinueException();
+
+        }
+    };
+
+    public static final REPLRemoteCommand DELETE_CMD = new REPLRemoteCommand("delete", "d", "Delete all breakpoints") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.DELETE_BREAK);
+            return request;
+        }
+    };
+
+    public static final REPLRemoteCommand DISABLE_CMD = new REPLRemoteCommand("disable", null, "Disable a breakpoint") {
+
+        private final String[] help = {"disable <n>: disable breakpoint number <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length == 1) {
+                context.displayFailReply("breakpoint number not speciified:  \"disable <n>\"");
+            } else if (args.length > 2) {
+                context.displayFailReply("breakpoint number not understood:  \"disable <n>\"");
+            } else {
+                try {
+                    final int breakpointNumber = Integer.parseInt(args[1]);
+                    final REPLMessage request = new REPLMessage();
+                    request.put(REPLMessage.OP, REPLMessage.DISABLE_BREAK);
+                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+                    return request;
+                } catch (IllegalArgumentException ex) {
+                    context.displayFailReply(ex.getMessage());
+                }
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
+                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " disabled");
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand DOWN_CMD = new REPLRemoteCommand("down", null, "Move down a stack frame") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final List<REPLFrame> frames = context.frames();
+            final int newFrameSelection = context.getSelectedFrameNumber() + 1;
+            if (newFrameSelection > frames.size() - 1) {
+                context.displayFailReply("at bottom of stack");
+                return null;
+            }
+            context.selectFrameNumber(newFrameSelection);
+            return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
+                context.displayFailReply(result != null ? result : firstReply.toString());
+            } else {
+                context.displayStack();
+            }
+        }
+    };
+
+    public static final REPLRemoteCommand ENABLE_CMD = new REPLRemoteCommand("enable", null, "Enable a breakpoint") {
+
+        private final String[] help = {"enable <n>: enable breakpoint number <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length == 1) {
+                context.displayFailReply("breakpoint number not speciified:  \"enable <n>\"");
+            } else if (args.length > 2) {
+                context.displayFailReply("breakpoint number not understood:  \"enable <n>\"");
+            } else {
+                try {
+                    final int breakpointNumber = Integer.parseInt(args[1]);
+                    final REPLMessage request = new REPLMessage();
+                    request.put(REPLMessage.OP, REPLMessage.ENABLE_BREAK);
+                    request.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+                    return request;
+                } catch (IllegalArgumentException ex) {
+                    context.displayFailReply(ex.getMessage());
+                }
+            }
+            return null;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                final int breakpointNumber = firstReply.getIntValue(REPLMessage.BREAKPOINT_ID);
+                firstReply.put(REPLMessage.DISPLAY_MSG, "breakpoint " + breakpointNumber + " enabled");
+            }
+            super.processReply(context, replies);
+        }
+    };
+
+    public static final REPLRemoteCommand FRAME_CMD = new REPLRemoteCommand("frame", null, "Display a stack frame") {
+
+        private final String[] help = {"frame : display currently selected frame", "frame <n> : display frame <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.FRAME);
+
+            int frameNumber = context.getSelectedFrameNumber();
+            if (args.length > 1) {
+                if (args.length == 2) {
+                    try {
+                        frameNumber = Integer.parseInt(args[1]);
+                    } catch (NumberFormatException e) {
+                        throw new IllegalArgumentException("Unrecognized argument \"" + args[1] + "\"");
+                    }
+                } else {
+                    throw new IllegalArgumentException("Unrecognized argument \"" + args[2] + "\"");
+                }
+            }
+            request.put(REPLMessage.FRAME_NUMBER, Integer.toString(frameNumber));
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                Integer frameNumber = replies[0].getIntValue(REPLMessage.FRAME_NUMBER);
+                context.selectFrameNumber(frameNumber);
+                context.displayReply("Frame " + frameNumber + ":");
+                for (REPLMessage message : replies) {
+                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
+                        context.displayInfo(line);
+                    }
+                }
+            }
+        }
+    };
+
+    public static final REPLRemoteCommand KILL_CMD = new REPLRemoteCommand("kill", null, "Stop program execution") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, "kill");
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.SUCCEEDED)) {
+                context.displayReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                context.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            }
+        }
+    };
+
+    public static final REPLRemoteCommand LOAD_RUN_CMD = new REPLRemoteCommand("load-run", "loadr", "Load and run a source") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            Source runSource = null;
+            if (args.length == 1) {
+                runSource = context.getSelectedSource();
+                if (runSource == null) {
+                    context.displayFailReply("No file selected");
+                    return null;
+                }
+            } else {
+                try {
+                    runSource = Source.fromFileName(args[1]);
+                } catch (IOException e) {
+                    context.displayFailReply("Can't find file: " + args[1]);
+                    return null;
+                }
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.LOAD_RUN);
+            request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
+            return request;
+        }
+    };
+
+    public static final REPLRemoteCommand LOAD_STEP_CMD = new REPLRemoteCommand("load-step", "loads", "Load and step into a source") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            Source runSource = null;
+            if (args.length == 1) {
+                runSource = context.getSelectedSource();
+                if (runSource == null) {
+                    context.displayFailReply("No file selected");
+                    return null;
+                }
+            } else {
+                try {
+                    runSource = Source.fromFileName(args[1]);
+                } catch (IOException e) {
+                    context.displayFailReply("Can't find file: " + args[1]);
+                    return null;
+                }
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.LOAD_STEP);
+            request.put(REPLMessage.SOURCE_NAME, runSource.getPath());
+            return request;
+        }
+    };
+
+    public static final REPLRemoteCommand STEP_INTO_CMD = new REPLRemoteCommand("step", "s", "(StepInto) next statement, going into functions.") {
+
+        @Override
+        public String[] getHelp() {
+            return new String[]{"step into:  step to next statement (into calls)", "step <n>: step to nth next statement (into calls)"};
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.STEP_INTO);
+
+            if (args.length >= 2) {
+                final String nText = args[1];
+                try {
+                    final int nSteps = Integer.parseInt(nText);
+                    if (nSteps > 0) {
+                        request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
+                    } else {
+                        return null;
+                    }
+                } catch (NumberFormatException e) {
+                    context.displayFailReply("Step into count \"" + nText + "\" not recognized");
+                    return null;
+                }
+            }
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+
+            throw new REPLContinueException();
+        }
+    };
+
+    public static final REPLRemoteCommand STEP_OUT_CMD = new REPLRemoteCommand("finish", null, "(StepOut) continue to end of function") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.STEP_OUT);
+
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+
+            throw new REPLContinueException();
+        }
+    };
+
+    public static final REPLRemoteCommand STEP_OVER_CMD = new REPLRemoteCommand("next", "n", "(StepOver) execute next line of code, not into functions.") {
+
+        @Override
+        public String[] getHelp() {
+            return new String[]{"next:  (StepOver) execute next line of code, not into functions.", "next <n>: (StepOver) execute to nth next statement (not counting into functions)"};
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.STEP_OVER);
+
+            if (args.length >= 2) {
+                final String nText = args[1];
+                try {
+                    final int nSteps = Integer.parseInt(nText);
+                    if (nSteps > 0) {
+                        request.put(REPLMessage.REPEAT, Integer.toString(nSteps));
+                    } else {
+                        return null;
+                    }
+                } catch (NumberFormatException e) {
+                    context.displayFailReply("Next count \"" + nText + "\" not recognized");
+                    return null;
+                }
+            }
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+
+            throw new REPLContinueException();
+        }
+    };
+
+    public static final REPLRemoteCommand UP_CMD = new REPLRemoteCommand("up", null, "Move up a stack frame") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (context.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final int newFrameSelection = context.getSelectedFrameNumber() - 1;
+            if (newFrameSelection < 0) {
+                context.displayFailReply("at top of stack");
+                return null;
+            }
+            context.selectFrameNumber(newFrameSelection);
+            return FRAME_CMD.createRequest(context, Arrays.copyOfRange(args, 0, 0));
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
+                context.displayFailReply(result != null ? result : firstReply.toString());
+            } else {
+                context.displayStack();
+            }
+        }
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/REPLineLocation.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+import java.io.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+final class REPLineLocation {
+
+    private final Source source;
+    private final int lineNumber;
+
+    /**
+     * Attempts to extract description of a source line from {@code arg[1]}, either
+     * "<source name>:<n>" or just "<n>".
+     */
+    static REPLineLocation parse(REPLClientContext context, String[] args) throws IllegalArgumentException {
+        if (args.length == 1) {
+            throw new IllegalArgumentException("no location specified");
+        }
+
+        Source source = null;
+        int lineNumber = -1;
+        String lineNumberText = null;
+
+        final String[] split = args[1].split(":");
+        if (split.length == 1) {
+            // Specification only has one part; it should be a line number
+            lineNumberText = split[0];
+            try {
+                lineNumber = Integer.parseInt(lineNumberText);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("no line number specified");
+            }
+            // If only line number specified, then there must be a selected file
+            final Source selectedSource = context.getSelectedSource();
+            if (selectedSource == null) {
+                throw new IllegalArgumentException("no selected file set");
+            }
+            source = selectedSource;
+
+        } else {
+            final String fileName = split[0];
+            lineNumberText = split[1];
+            try {
+                source = Source.fromFileName(fileName);
+            } catch (IOException e1) {
+                throw new IllegalArgumentException("Can't find file \"" + fileName + "\"");
+            }
+            try {
+                lineNumber = Integer.parseInt(lineNumberText);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Invalid line number \"" + lineNumberText + "\"");
+            }
+            if (lineNumber <= 0) {
+                throw new IllegalArgumentException("Invalid line number \"" + lineNumberText + "\"");
+            }
+        }
+
+        return new REPLineLocation(source, lineNumber);
+    }
+
+    REPLineLocation(Source source, int lineNumber) {
+        this.source = source;
+        this.lineNumber = lineNumber;
+    }
+
+    public Source getSource() {
+        return source;
+    }
+
+    public int getLineNumber() {
+        return lineNumber;
+    }
+
+    /**
+     * Creates a message containing an "op" and a line location.
+     *
+     * @param op the operation to be performed on this location
+     */
+    public REPLMessage createMessage(String op) {
+        final REPLMessage msg = new REPLMessage(REPLMessage.OP, op);
+        msg.put(REPLMessage.SOURCE_NAME, source.getShortName());
+        msg.put(REPLMessage.FILE_PATH, source.getPath());
+        msg.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
+        return msg;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/client/SimpleREPLClient.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,1397 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.client;
+
+import java.io.*;
+import java.util.*;
+
+import jline.console.*;
+
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+/**
+ * A very simple line-oriented, language-agnostic debugging client shell: the first step toward a
+ * general, extensible debugging framework designed to be adapted for remote debugging.
+ * <p>
+ * The architecture of this debugging framework is modeled loosely on <a
+ * href="https://github.com/clojure/tools.nrepl">nREPL</a>, a network REPL developed by the Clojure
+ * community with a focus on generality:
+ * <ul>
+ * <li>Client and (possibly remote) server communicate via <em>messages</em> carried over some
+ * <em>transport</em>;</li>
+ * <li>A message is a <em>map</em> of key/value pairs;</li>
+ * <li>Keys and values are <em>strings</em>;</li>
+ * <li>The client sends messages as <em>requests</em> to a server;</li>
+ * <li>A server dispatches each incoming request to an appropriate <em>handler</em> that takes
+ * appropriate action and responds to the client with one or more messages; and</li>
+ * <li>Many implementations of the <em>transport</em> are possible.</li>
+ * </ul>
+ * <p>
+ * <strong>Compromises:</strong>
+ * <p>
+ * In order to get
+ * <ol>
+ * <li>A debugging session should start from this shell, but there is no machinery in place for
+ * doing that; instead, an entry into the language implementation creates both the server and this
+ * shell;</li>
+ * <li>The current startup sequence is based on method calls, not messages;</li>
+ * <li>Only a very few request types and keys are implemented, omitting for example request and
+ * session ids;</li>
+ * <li>Message passing is synchronous and "transported" via method calls;</li>
+ * <li>Asynchrony is emulated by having each call to the server pass only a message, and by having
+ * the server return only a list of messages.</li>
+ * </ol>
+ *
+ * @see REPLServer
+ * @see REPLMessage
+ */
+public class SimpleREPLClient implements REPLClient {
+
+    private static final String REPLY_PREFIX = "==> ";
+    private static final String FAIL_PREFIX = "**> ";
+    private static final String WARNING_PREFIX = "!!> ";
+    private static final String TRACE_PREFIX = ">>> ";
+    private static final String[] NULL_ARGS = new String[0];
+
+    static final String INFO_LINE_FORMAT = "    %s\n";
+    static final String CODE_LINE_FORMAT = "    %3d  %s\n";
+    static final String CODE_LINE_BREAK_FORMAT = "--> %3d  %s\n";
+
+    private static final String STACK_FRAME_FORMAT = "    %3d: at %s in %s    line =\"%s\"\n";
+    private static final String STACK_FRAME_SELECTED_FORMAT = "==> %3d: at %s in %s    line =\"%s\"\n";
+
+    private final String languageName;
+
+    // Top level commands
+    private final Map<String, REPLCommand> commandMap = new HashMap<>();
+    private final Collection<String> commandNames = new TreeSet<>();
+
+    // Local options
+    private final Map<String, LocalOption> localOptions = new HashMap<>();
+    private final Collection<String> optionNames = new TreeSet<>();
+
+    // Current local context
+    ClientContextImpl clientContext;
+
+    // Cheating for the prototype; prototype startup now happens from the language server.
+    // So this isn't used.
+    public static void main(String[] args) {
+        final SimpleREPLClient repl = new SimpleREPLClient(null, null);
+        repl.start();
+    }
+
+    private final ConsoleReader reader;
+
+    private final PrintStream writer;
+
+    private final REPLServer replServer;
+
+    private final LocalOption astDepthOption = new IntegerOption(9, "astdepth", "default depth for AST display");
+
+    private final LocalOption autoWhereOption = new BooleanOption(true, "autowhere", "run the \"where\" command after each navigation");
+
+    private final LocalOption autoNodeOption = new BooleanOption(false, "autonode", "run the \"truffle node\" command after each navigation");
+
+    private final LocalOption autoSubtreeOption = new BooleanOption(false, "autosubtree", "run the \"truffle subtree\" command after each navigation");
+
+    private final LocalOption autoASTOption = new BooleanOption(false, "autoast", "run the \"truffle ast\" command after each navigation");
+
+    private final LocalOption listSizeOption = new IntegerOption(25, "listsize", "default number of lines to list");
+
+    private final LocalOption traceMessagesOption = new BooleanOption(false, "tracemessages", "trace REPL messages between client and server");
+
+    private final LocalOption verboseBreakpointInfoOption = new BooleanOption(true, "verbosebreakpointinfo", "\"info breakpoint\" displays more info");
+
+    private void addOption(LocalOption localOption) {
+        final String optionName = localOption.getName();
+        localOptions.put(optionName, localOption);
+        optionNames.add(optionName);
+    }
+
+    /**
+     * Non-null when the user has named a file other than where halted, providing context for
+     * commands such as "break"; if no explicit selection, then defaults to where halted. This is
+     * session state, so it persists across halting contexts.
+     */
+    private Source selectedSource = null;
+
+    public SimpleREPLClient(String languageName, REPLServer replServer) {
+        this.languageName = languageName;
+        this.replServer = replServer;
+        this.writer = System.out;
+        try {
+            this.reader = new ConsoleReader();
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to create console " + e);
+        }
+
+        addCommand(backtraceCommand);
+        addCommand(REPLRemoteCommand.BREAK_AT_LINE_CMD);
+        addCommand(REPLRemoteCommand.BREAK_AT_LINE_ONCE_CMD);
+        addCommand(REPLRemoteCommand.BREAK_AT_THROW_CMD);
+        addCommand(REPLRemoteCommand.BREAK_AT_THROW_ONCE_CMD);
+        addCommand(REPLRemoteCommand.CLEAR_BREAK_CMD);
+        addCommand(REPLRemoteCommand.CONDITION_BREAK_CMD);
+        addCommand(REPLRemoteCommand.CONTINUE_CMD);
+        addCommand(REPLRemoteCommand.DELETE_CMD);
+        addCommand(REPLRemoteCommand.DISABLE_CMD);
+        addCommand(REPLRemoteCommand.DOWN_CMD);
+        addCommand(REPLRemoteCommand.ENABLE_CMD);
+        addCommand(evalCommand);
+        addCommand(fileCommand);
+        addCommand(REPLRemoteCommand.FRAME_CMD);
+        addCommand(helpCommand);
+        addCommand(infoCommand);
+        addCommand(REPLRemoteCommand.KILL_CMD);
+        addCommand(listCommand);
+        addCommand(REPLRemoteCommand.LOAD_RUN_CMD);
+        addCommand(REPLRemoteCommand.LOAD_STEP_CMD);
+        addCommand(quitCommand);
+        addCommand(setCommand);
+        addCommand(REPLRemoteCommand.STEP_INTO_CMD);
+        addCommand(REPLRemoteCommand.STEP_OUT_CMD);
+        addCommand(REPLRemoteCommand.STEP_OVER_CMD);
+        addCommand(truffleCommand);
+        addCommand(REPLRemoteCommand.UP_CMD);
+        addCommand(whereCommand);
+
+        infoCommand.addCommand(infoBreakCommand);
+        infoCommand.addCommand(infoLanguageCommand);
+        infoCommand.addCommand(infoSetCommand);
+
+        truffleCommand.addCommand(truffleASTCommand);
+        truffleCommand.addCommand(truffleNodeCommand);
+        truffleCommand.addCommand(truffleSubtreeCommand);
+
+        addOption(astDepthOption);
+        addOption(autoASTOption);
+        addOption(autoNodeOption);
+        addOption(autoSubtreeOption);
+        addOption(autoWhereOption);
+        addOption(listSizeOption);
+        addOption(traceMessagesOption);
+        addOption(verboseBreakpointInfoOption);
+    }
+
+    public void start() {
+
+        REPLMessage startReply = replServer.start();
+
+        if (startReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+            clientContext.displayFailReply(startReply.get(REPLMessage.DISPLAY_MSG));
+            throw new RuntimeException("Can't start REPL server");
+        }
+
+        this.clientContext = new ClientContextImpl(null, null);
+
+        try {
+            clientContext.startSession();
+        } finally {
+            clientContext.displayReply("Goodbye from " + languageName + "/REPL");
+        }
+
+    }
+
+    public void addCommand(REPLCommand replCommand) {
+        final String commandName = replCommand.getCommand();
+        final String abbreviation = replCommand.getAbbreviation();
+
+        commandNames.add(commandName);
+        commandMap.put(commandName, replCommand);
+        if (abbreviation != null) {
+            commandMap.put(abbreviation, replCommand);
+        }
+    }
+
+    private class ClientContextImpl implements REPLClientContext {
+
+        private final ClientContextImpl predecessor;
+        private final int level;
+
+        // Information about where the execution is halted
+        /** The source where execution, if any, is halted; null if none. */
+        private Source haltedSource = null;
+        /** The line number where execution, if any, is halted; 0 if none. */
+        private int haltedLineNumber = 0;
+        /** The stack where execution, if any, is halted; null if none. Evaluated lazily. */
+        private List<REPLFrame> frames = null;
+
+        /** The frame number currently selected by user. */
+        private int selectedFrameNumber = 0;
+
+        private String currentPrompt;
+
+        /**
+         * Create a new context on the occasion of an execution halting.
+         */
+        public ClientContextImpl(ClientContextImpl predecessor, REPLMessage message) {
+            this.predecessor = predecessor;
+            this.level = predecessor == null ? 0 : predecessor.level + 1;
+
+            if (message != null) {
+                try {
+                    this.haltedSource = Source.fromFileName(message.get(REPLMessage.SOURCE_NAME));
+                    selectedSource = this.haltedSource;
+                    try {
+                        haltedLineNumber = Integer.parseInt(message.get(REPLMessage.LINE_NUMBER));
+                    } catch (NumberFormatException e) {
+                        haltedLineNumber = 0;
+                    }
+                } catch (IOException e1) {
+                    this.haltedSource = null;
+                    this.haltedLineNumber = 0;
+                }
+            }
+            updatePrompt();
+        }
+
+        private void selectSource(String fileName) {
+            try {
+                selectedSource = Source.fromFileName(fileName);
+            } catch (IOException e1) {
+                selectedSource = null;
+            }
+            updatePrompt();
+        }
+
+        private void updatePrompt() {
+            if (level == 0) {
+                // 0-level context; no executions halted.
+                if (selectedSource == null) {
+                    currentPrompt = languageName == null ? "() " : "( " + languageName + " ) ";
+                } else {
+                    currentPrompt = "(" + selectedSource.getShortName() + ") ";
+                }
+            } else if (selectedSource != null && selectedSource != haltedSource) {
+                // User is focusing somewhere else than the current locn; show no line number.
+                final StringBuilder sb = new StringBuilder();
+                sb.append("(<" + Integer.toString(level) + "> ");
+                sb.append(selectedSource.getShortName());
+                sb.append(") ");
+                currentPrompt = sb.toString();
+            } else {
+                // Prompt reveals where currently halted.
+                final StringBuilder sb = new StringBuilder();
+                sb.append("(<" + Integer.toString(level) + "> ");
+                sb.append(haltedSource == null ? "??" : haltedSource.getShortName());
+                if (haltedLineNumber > 0) {
+                    sb.append(":" + Integer.toString(haltedLineNumber));
+                }
+                sb.append(") ");
+                currentPrompt = sb.toString();
+            }
+
+        }
+
+        public Source source() {
+            return haltedSource;
+        }
+
+        public int lineNumber() {
+            return haltedLineNumber;
+        }
+
+        public List<REPLFrame> frames() {
+            if (frames == null) {
+                final REPLMessage request = new REPLMessage(REPLMessage.OP, REPLMessage.BACKTRACE);
+                final REPLMessage[] replies = sendToServer(request);
+                if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                    return null;
+                }
+                frames = new ArrayList<>();
+                for (REPLMessage reply : replies) {
+                    final int index = reply.getIntValue(REPLMessage.FRAME_NUMBER);
+                    final String locationFilePath = reply.get(REPLMessage.FILE_PATH);
+                    final Integer locationLineNumber = reply.getIntValue(REPLMessage.LINE_NUMBER);
+                    final String locationDescription = reply.get(REPLMessage.SOURCE_LOCATION);
+                    final String name = reply.get(REPLMessage.METHOD_NAME);
+                    final String sourceLineText = reply.get(REPLMessage.SOURCE_LINE_TEXT);
+                    frames.add(new REPLFrameImpl(index, locationFilePath, locationLineNumber, locationDescription, name, sourceLineText));
+                }
+                frames = Collections.unmodifiableList(frames);
+            }
+            return frames;
+        }
+
+        public int level() {
+            return this.level;
+        }
+
+        public Source getSelectedSource() {
+            return selectedSource == null ? haltedSource : selectedSource;
+        }
+
+        public int getSelectedFrameNumber() {
+            return selectedFrameNumber;
+        }
+
+        public String stringQuery(String op) {
+            assert op != null;
+            REPLMessage request = null;
+            switch (op) {
+                case REPLMessage.TRUFFLE_AST:
+                    request = truffleASTCommand.createRequest(clientContext, NULL_ARGS);
+                    break;
+                case REPLMessage.TRUFFLE_SUBTREE:
+                    request = truffleSubtreeCommand.createRequest(clientContext, NULL_ARGS);
+                    break;
+                default:
+                    request = new REPLMessage();
+                    request.put(REPLMessage.OP, op);
+            }
+            if (request == null) {
+                return null;
+            }
+            final REPLMessage[] replies = sendToServer(request);
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                return null;
+            }
+            return replies[0].get(REPLMessage.DISPLAY_MSG);
+        }
+
+        public void selectFrameNumber(int frameNumber) {
+            this.selectedFrameNumber = frameNumber;
+        }
+
+        void displayWhere() {
+            if (level == 0) {
+                displayFailReply("no active execution");
+                return;
+            }
+
+            Source whereSource = null;
+            int whereLineNumber = 0;
+
+            if (selectedFrameNumber == 0) {
+                whereSource = haltedSource;
+                whereLineNumber = haltedLineNumber;
+            } else {
+                final REPLFrame frame = frames().get(selectedFrameNumber);
+                final String locationFileName = frame.locationFilePath();
+                if (locationFileName != null) {
+                    try {
+                        whereSource = Source.fromFileName(locationFileName);
+                    } catch (IOException e) {
+                    }
+                }
+                whereLineNumber = frame.locationLineNumber();
+            }
+            if (whereSource == null) {
+                displayFailReply("Frame " + selectedFrameNumber + ": source unavailable");
+                return;
+            }
+            final int listSize = listSizeOption.getInt();
+
+            final int fileLineCount = whereSource.getLineCount();
+            final String code = whereSource.getCode();
+
+            writer.println("Frame " + selectedFrameNumber + ": " + whereSource.getShortName() + "\n");
+            final int halfListSize = listSize / 2;
+            final int startLineNumber = Math.max(1, whereLineNumber - halfListSize);
+            final int lastLineNumber = Math.min(startLineNumber + listSize - 1, fileLineCount);
+            for (int line = startLineNumber; line <= lastLineNumber; line++) {
+                final int offset = whereSource.getLineStartOffset(line);
+                final String lineText = code.substring(offset, offset + whereSource.getLineLength(line));
+                if (line == whereLineNumber) {
+                    writer.format(CODE_LINE_BREAK_FORMAT, line, lineText);
+                } else {
+                    writer.format(CODE_LINE_FORMAT, line, lineText);
+                }
+            }
+        }
+
+        public void displayStack() {
+            final List<REPLFrame> frameList = frames();
+            if (frameList == null) {
+                writer.println("<empty stack>");
+            } else {
+                for (REPLFrame frame : frameList) {
+                    String sourceLineText = frame.sourceLineText();
+                    if (sourceLineText == null) {
+                        sourceLineText = "<??>";
+                    }
+                    if (frame.index() == selectedFrameNumber) {
+                        writer.format(STACK_FRAME_SELECTED_FORMAT, frame.index(), frame.locationDescription(), frame.name(), sourceLineText);
+                    } else {
+                        writer.format(STACK_FRAME_FORMAT, frame.index(), frame.locationDescription(), frame.name(), sourceLineText);
+                    }
+                }
+            }
+        }
+
+        public void displayInfo(String message) {
+            writer.format(INFO_LINE_FORMAT, message);
+        }
+
+        public void displayReply(String message) {
+            writer.println(REPLY_PREFIX + message);
+        }
+
+        public void displayFailReply(String message) {
+            writer.println(FAIL_PREFIX + message);
+        }
+
+        public void displayWarnings(String warnings) {
+            for (String warning : warnings.split("\\n")) {
+                writer.println(WARNING_PREFIX + warning);
+            }
+        }
+
+        public void traceMessage(String message) {
+            writer.println(TRACE_PREFIX + message);
+        }
+
+        public void startSession() {
+
+            while (true) {
+                try {
+                    String[] args;
+                    String line = reader.readLine(currentPrompt).trim();
+                    if (line.startsWith("eval ")) {
+                        args = new String[]{"eval", line.substring(5)};
+                    } else {
+                        args = line.split("[ \t]+");
+                    }
+                    if (args.length == 0) {
+                        break;
+                    }
+                    final String cmd = args[0];
+
+                    if (cmd.isEmpty()) {
+                        continue;
+                    }
+
+                    REPLCommand command = commandMap.get(cmd);
+                    while (command instanceof REPLIndirectCommand) {
+                        if (traceMessagesOption.getBool()) {
+                            traceMessage("Executing indirect: " + command.getCommand());
+                        }
+                        command = ((REPLIndirectCommand) command).getCommand(args);
+                    }
+                    if (command == null) {
+                        clientContext.displayFailReply("Unrecognized command \"" + cmd + "\"");
+                        continue;
+                    }
+                    if (command instanceof REPLLocalCommand) {
+                        if (traceMessagesOption.getBool()) {
+                            traceMessage("Executing local: " + command.getCommand());
+                        }
+                        ((REPLLocalCommand) command).execute(args);
+
+                    } else if (command instanceof REPLRemoteCommand) {
+                        final REPLRemoteCommand remoteCommand = (REPLRemoteCommand) command;
+
+                        final REPLMessage request = remoteCommand.createRequest(clientContext, args);
+                        if (request == null) {
+                            continue;
+                        }
+
+                        REPLMessage[] replies = sendToServer(request);
+
+                        remoteCommand.processReply(clientContext, replies);
+                    } else {
+                        assert false; // Should not happen.
+                    }
+
+                } catch (REPLContinueException ex) {
+                    break;
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+
+        }
+
+        private REPLMessage[] sendToServer(REPLMessage request) {
+            if (traceMessagesOption.getBool()) {
+                clientContext.traceMessage("Sever request:");
+                request.print(writer, "  ");
+            }
+
+            REPLMessage[] replies = replServer.receive(request);
+
+            assert replies != null && replies.length > 0;
+            if (traceMessagesOption.getBool()) {
+                if (replies.length > 1) {
+                    clientContext.traceMessage("Received " + replies.length + " server replies");
+                    int replyCount = 0;
+                    for (REPLMessage reply : replies) {
+                        clientContext.traceMessage("Server Reply " + replyCount++ + ":");
+                        reply.print(writer, "  ");
+                    }
+                } else {
+                    clientContext.traceMessage("Received reply:");
+                    replies[0].print(writer, "  ");
+                }
+            }
+            return replies;
+        }
+
+        private final class REPLFrameImpl implements REPLFrame {
+
+            private final int index;
+            private final String locationFilePath;
+            private final Integer locationLineNumber;
+            private final String locationDescription;
+            private final String name;
+            private final String sourceLineText;
+
+            REPLFrameImpl(int index, String locationFilePath, Integer locationLineNumber, String locationDescription, String name, String sourceLineText) {
+                this.index = index;
+                this.locationFilePath = locationFilePath;
+                this.locationLineNumber = locationLineNumber;
+                this.locationDescription = locationDescription;
+                this.name = name;
+                this.sourceLineText = sourceLineText;
+            }
+
+            public int index() {
+                return index;
+            }
+
+            public String locationFilePath() {
+                return locationFilePath;
+            }
+
+            public Integer locationLineNumber() {
+                return locationLineNumber;
+            }
+
+            public String locationDescription() {
+                return locationDescription;
+            }
+
+            public String name() {
+                return name;
+            }
+
+            public String sourceLineText() {
+                return sourceLineText;
+            }
+
+        }
+
+    }
+
+    // Cheating with synchrony: asynchronous replies should arrive here, but don't.
+    @Override
+    public REPLMessage receive(REPLMessage request) {
+        final String result = request.get("result");
+        clientContext.displayReply(result != null ? result : request.toString());
+        return null;
+    }
+
+    /**
+     * Cheating with synchrony: take a direct call from the server that execution has halted and
+     * we've entered a nested debugging context.
+     */
+    public void halted(REPLMessage message) {
+
+        // Push a new context for where we've stopped.
+        clientContext = new ClientContextImpl(clientContext, message);
+        final String warnings = message.get(REPLMessage.WARNINGS);
+        if (warnings != null) {
+            clientContext.displayWarnings(warnings);
+        }
+        if (autoWhereOption.getBool()) {
+            clientContext.displayWhere();
+        }
+        if (autoNodeOption.getBool()) {
+            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_NODE);
+            if (result != null) {
+                displayTruffleNode(result);
+            }
+        }
+        if (autoASTOption.getBool()) {
+            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_AST);
+            if (result != null) {
+                displayTruffleAST(result);
+            }
+        }
+        if (autoSubtreeOption.getBool()) {
+            final String result = clientContext.stringQuery(REPLMessage.TRUFFLE_SUBTREE);
+            if (result != null) {
+                displayTruffleSubtree(result);
+            }
+        }
+
+        try {
+            clientContext.startSession();
+        } finally {
+
+            // To continue execution, pop the context and return
+            this.clientContext = clientContext.predecessor;
+        }
+    }
+
+    /**
+     * A command that can be executed without (direct) communication with the server; it may rely on
+     * some other method that goes to the server for information.
+     */
+    private abstract class REPLLocalCommand extends REPLCommand {
+
+        public REPLLocalCommand(String command, String abbreviation, String description) {
+            super(command, abbreviation, description);
+        }
+
+        abstract void execute(String[] args);
+    }
+
+    /**
+     * A command that redirects to other commands, based on arguments.
+     */
+    private abstract class REPLIndirectCommand extends REPLCommand {
+
+        public REPLIndirectCommand(String command, String abbreviation, String description) {
+            super(command, abbreviation, description);
+        }
+
+        abstract void addCommand(REPLCommand command);
+
+        abstract REPLCommand getCommand(String[] args);
+    }
+
+    private final REPLCommand backtraceCommand = new REPLLocalCommand("backtrace", "bt", "Display current stack") {
+
+        @Override
+        void execute(String[] args) {
+            if (clientContext.level == 0) {
+                clientContext.displayFailReply("no active execution");
+            } else {
+                clientContext.displayStack();
+            }
+        }
+    };
+
+    private final REPLCommand evalCommand = new REPLRemoteCommand("eval", null, "Evaluate a string, in context of the current frame if any") {
+
+        private int evalCounter = 0;
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length > 1) {
+                final String code = args[1];
+                if (!code.isEmpty()) {
+                    // Create a fake entry in the file maps and cache, based on this unique name
+                    final String fakeFileName = "<eval" + ++evalCounter + ">";
+                    Source.fromNamedText(fakeFileName, code);
+                    final REPLMessage request = new REPLMessage();
+                    request.put(REPLMessage.OP, REPLMessage.EVAL);
+                    request.put(REPLMessage.CODE, code);
+                    request.put(REPLMessage.SOURCE_NAME, fakeFileName);
+                    if (clientContext.level > 0) {
+                        // Specify a requested execution context, if one exists; otherwise top level
+                        request.put(REPLMessage.FRAME_NUMBER, Integer.toString(context.getSelectedFrameNumber()));
+                    }
+                    return request;
+                }
+            }
+            return null;
+        }
+    };
+
+    private final REPLCommand fileCommand = new REPLRemoteCommand("file", null, "Set/display current file for viewing") {
+
+        final String[] help = {"file:  display current file path", "file <filename>: Set file to be current file for viewing"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (args.length == 1) {
+                final Source source = clientContext.getSelectedSource();
+                if (source == null) {
+                    clientContext.displayFailReply("no file currently selected");
+                } else {
+                    clientContext.displayReply(source.getPath());
+                }
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.FILE);
+            request.put(REPLMessage.SOURCE_NAME, args[1]);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            REPLMessage firstReply = replies[0];
+
+            if (firstReply.get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                final String result = firstReply.get(REPLMessage.DISPLAY_MSG);
+                clientContext.displayFailReply(result != null ? result : firstReply.toString());
+                return;
+            }
+            final String fileName = firstReply.get(REPLMessage.SOURCE_NAME);
+            final String path = firstReply.get(REPLMessage.FILE_PATH);
+            clientContext.selectSource(path == null ? fileName : path);
+            clientContext.displayReply(clientContext.getSelectedSource().getPath());
+
+            for (int i = 1; i < replies.length; i++) {
+                REPLMessage reply = replies[i];
+                final String result = reply.get(REPLMessage.DISPLAY_MSG);
+                clientContext.displayInfo(result != null ? result : reply.toString());
+            }
+        }
+
+    };
+
+    private final REPLCommand helpCommand = new REPLLocalCommand("help", null, "Describe commands") {
+
+        final String[] help = {"help:  list available commands", "help <command>: additional information about <command>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public void execute(String[] args) {
+
+            if (args.length == 1) {
+                clientContext.displayReply("Available commands:");
+                for (String commandName : commandNames) {
+                    final REPLCommand command = commandMap.get(commandName);
+                    if (command == null) {
+                        clientContext.displayInfo(commandName + ": Error, no implementation for command");
+                    } else {
+                        final String abbrev = command.getAbbreviation();
+                        if (abbrev == null) {
+                            clientContext.displayInfo(commandName + ": " + command.getDescription());
+                        } else {
+                            clientContext.displayInfo(commandName + "(" + abbrev + "): " + command.getDescription());
+                        }
+                    }
+                }
+            } else {
+                final String cmdName = args[1];
+                final REPLCommand cmd = commandMap.get(cmdName);
+                if (cmd == null) {
+                    clientContext.displayReply("command \"" + cmdName + "\" not recognized");
+                } else {
+                    final String[] helpLines = cmd.getHelp();
+                    if (helpLines == null) {
+                        clientContext.displayReply("\"" + cmdName + "\":");
+                    } else if (helpLines.length == 1) {
+                        clientContext.displayInfo(helpLines[0]);
+                    } else {
+                        clientContext.displayReply("\"" + cmdName + "\":");
+                        for (String line : helpLines) {
+                            clientContext.displayInfo(line);
+                        }
+                    }
+                }
+            }
+        }
+    };
+
+    private final REPLIndirectCommand infoCommand = new REPLIndirectCommand(REPLMessage.INFO, null, "Additional information on topics") {
+
+        // "Info" commands
+        private final Map<String, REPLCommand> infoCommandMap = new HashMap<>();
+        private final Collection<String> infoCommandNames = new TreeSet<>();
+
+        @Override
+        public String[] getHelp() {
+            final ArrayList<String> lines = new ArrayList<>();
+            for (String infoCommandName : infoCommandNames) {
+                final REPLCommand cmd = infoCommandMap.get(infoCommandName);
+                if (cmd == null) {
+                    lines.add("\"" + REPLMessage.INFO + " " + infoCommandName + "\" not implemented");
+                } else {
+                    lines.add("\"" + REPLMessage.INFO + " " + infoCommandName + "\": " + cmd.getDescription());
+                }
+            }
+            return lines.toArray(new String[0]);
+        }
+
+        @Override
+        void addCommand(REPLCommand replCommand) {
+            final String commandName = replCommand.getCommand();
+            final String abbreviation = replCommand.getAbbreviation();
+
+            infoCommandNames.add(commandName);
+            infoCommandMap.put(commandName, replCommand);
+            if (abbreviation != null) {
+                infoCommandMap.put(abbreviation, replCommand);
+            }
+        }
+
+        @Override
+        REPLCommand getCommand(String[] args) {
+            if (args.length == 1) {
+                clientContext.displayFailReply("info topic not specified; try \"help info\"");
+                return null;
+            }
+            final String topic = args[1];
+            REPLCommand command = infoCommandMap.get(topic);
+            if (command == null) {
+                clientContext.displayFailReply("topic \"" + topic + "\" not recognized");
+                return null;
+            }
+
+            return command;
+        }
+
+    };
+
+    private final REPLCommand infoBreakCommand = new REPLRemoteCommand("breakpoint", "break", "info about breakpoints") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.BREAKPOINT_INFO);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                Arrays.sort(replies, new Comparator<REPLMessage>() {
+
+                    public int compare(REPLMessage o1, REPLMessage o2) {
+                        try {
+                            final int n1 = Integer.parseInt(o1.get(REPLMessage.BREAKPOINT_ID));
+                            final int n2 = Integer.parseInt(o2.get(REPLMessage.BREAKPOINT_ID));
+                            return Integer.compare(n1, n2);
+                        } catch (Exception ex) {
+                        }
+                        return 0;
+                    }
+
+                });
+                clientContext.displayReply("Breakpoints set:");
+                for (REPLMessage message : replies) {
+                    final StringBuilder sb = new StringBuilder();
+
+                    sb.append(Integer.parseInt(message.get(REPLMessage.BREAKPOINT_ID)) + ": ");
+                    sb.append("@" + message.get(REPLMessage.INFO_VALUE));
+                    sb.append(" (state=" + message.get(REPLMessage.BREAKPOINT_STATE));
+                    if (verboseBreakpointInfoOption.getBool()) {
+                        sb.append(", group=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_GROUP_ID)));
+                        sb.append(", hits=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_HIT_COUNT)));
+                        sb.append(", ignore=" + Integer.parseInt(message.get(REPLMessage.BREAKPOINT_IGNORE_COUNT)));
+                    }
+                    final String condition = message.get(REPLMessage.BREAKPOINT_CONDITION);
+                    if (condition != null) {
+                        sb.append(", condition=\"" + condition + "\"");
+                    }
+                    sb.append(")");
+                    clientContext.displayInfo(sb.toString());
+                }
+            }
+        }
+    };
+
+    private final REPLCommand infoLanguageCommand = new REPLRemoteCommand("language", "lang", "language and implementation details") {
+
+        final String[] help = {"info language:  list details about the language implementation"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.INFO);
+            request.put(REPLMessage.TOPIC, REPLMessage.LANGUAGE);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                clientContext.displayReply("Language info:");
+                for (REPLMessage message : replies) {
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append(message.get(REPLMessage.INFO_KEY));
+                    sb.append(": ");
+                    sb.append(message.get(REPLMessage.INFO_VALUE));
+                    clientContext.displayInfo(sb.toString());
+                }
+            }
+        }
+    };
+
+    private final REPLCommand infoSetCommand = new REPLLocalCommand("set", null, "info about settings") {
+
+        final String[] help = {"info sets:  list local options that can be set"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public void execute(String[] args) {
+
+            clientContext.displayReply("Settable options:");
+
+            for (String optionName : optionNames) {
+                final LocalOption localOption = localOptions.get(optionName);
+                if (localOption == null) {
+                    clientContext.displayInfo(localOption + ": Error, no implementation for option");
+                } else {
+                    clientContext.displayInfo(optionName + "=" + localOption.getValue() + ": " + localOption.getDescription());
+                }
+            }
+        }
+    };
+
+    private final REPLCommand listCommand = new REPLLocalCommand("list", null, "Display selected source file") {
+
+        final String[] help = {"list:  list <listsize> lines of selected file (see option \"listsize\")", "list all: list all lines", "list <n>: list <listsize> lines centered around line <n>"};
+
+        private Source lastListedSource = null;
+
+        private int nextLineToList = 1;
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public void execute(String[] args) {
+            final Source source = clientContext.getSelectedSource();
+            if (source == null) {
+                clientContext.displayFailReply("No selected file");
+                reset();
+                return;
+            }
+            final int listSize = listSizeOption.getInt();
+
+            if (args.length == 1) {
+                if (!source.equals(lastListedSource)) {
+                    reset();
+                } else if (nextLineToList > source.getLineCount()) {
+                    reset();
+                }
+                final int lastListedLine = printLines(source, nextLineToList, listSize);
+                lastListedSource = source;
+                nextLineToList = lastListedLine > source.getLineCount() ? 1 : lastListedLine + 1;
+            } else if (args.length == 2) {
+                reset();
+                if (args[1].equals("all")) {
+                    printLines(source, 1, source.getLineCount());
+                } else {
+                    try {
+                        final int line = Integer.parseInt(args[1]);
+                        final int halfListSize = listSize / 2;
+                        final int start = Math.max(1, line - halfListSize);
+                        final int count = Math.min(source.getLineCount() + 1 - start, listSize);
+                        printLines(source, start, count);
+                    } catch (NumberFormatException e) {
+                        clientContext.displayFailReply("\"" + args[1] + "\" not recognized");
+                    }
+
+                }
+            }
+        }
+
+        private int printLines(Source printSource, int start, int listSize) {
+
+            clientContext.displayReply(printSource.getShortName() + ":");
+            final int lastLineNumber = Math.min(start + listSize - 1, printSource.getLineCount());
+            for (int line = start; line <= lastLineNumber; line++) {
+                writer.format(CODE_LINE_FORMAT, line, printSource.getCode(line));
+            }
+            return lastLineNumber;
+        }
+
+        /**
+         * Forget where we were in a sequence of list commands with no arguments
+         */
+        private void reset() {
+            lastListedSource = clientContext.getSelectedSource();
+            nextLineToList = 1;
+        }
+    };
+
+    private final REPLCommand quitCommand = new REPLRemoteCommand("quit", "q", "Quit execution and REPL") {
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.QUIT);
+            return request;
+        }
+
+    };
+
+    private final REPLCommand setCommand = new REPLLocalCommand("set", null, "set <option>=<value>") {
+
+        @Override
+        public String[] getHelp() {
+            return new String[]{"Sets an option \"set <option-name>=<value>\";  see also \"info set\""};
+        }
+
+        @Override
+        public void execute(String[] args) {
+            REPLMessage request = null;
+            if (args.length == 1) {
+                clientContext.displayFailReply("No option specified, try \"help set\"");
+            } else if (args.length == 2) {
+                String[] split = new String[0];
+                try {
+                    split = args[1].split("=");
+                } catch (Exception ex) {
+                }
+                if (split.length == 0) {
+                    clientContext.displayFailReply("Arguments not understood, try \"help set\"");
+                } else if (split.length == 1) {
+                    clientContext.displayFailReply("No option value specified, try \"help set\"");
+                } else if (split.length > 2) {
+                    clientContext.displayFailReply("Arguments not understood, try \"help set\"");
+                } else {
+                    final String optionName = split[0];
+                    final String newValue = split[1];
+                    final LocalOption localOption = localOptions.get(optionName);
+                    if (localOption != null) {
+                        if (!localOption.setValue(newValue)) {
+                            clientContext.displayFailReply("Invalid option value \"" + newValue + "\"");
+                        }
+                        clientContext.displayInfo(localOption.name + " = " + localOption.getValue());
+                    } else {
+                        request = new REPLMessage();
+                        request.put(REPLMessage.OP, REPLMessage.SET);
+                        request.put(REPLMessage.OPTION, optionName);
+                        request.put(REPLMessage.VALUE, newValue);
+                    }
+                }
+            } else {
+                clientContext.displayFailReply("Arguments not understood, try \"help set\"");
+            }
+        }
+    };
+
+    private final REPLIndirectCommand truffleCommand = new REPLIndirectCommand(REPLMessage.TRUFFLE, "t", "Access to Truffle internals") {
+
+        // "Truffle" commands
+        private final Map<String, REPLCommand> truffleCommandMap = new HashMap<>();
+        private final Collection<String> truffleCommandNames = new TreeSet<>();
+
+        @Override
+        public String[] getHelp() {
+            final ArrayList<String> lines = new ArrayList<>();
+            for (String truffleCommandName : truffleCommandNames) {
+                final REPLCommand cmd = truffleCommandMap.get(truffleCommandName);
+                if (cmd == null) {
+                    lines.add("\"" + REPLMessage.TRUFFLE + " " + truffleCommandName + "\" not implemented");
+                } else {
+                    for (String line : cmd.getHelp()) {
+                        lines.add(line);
+                    }
+                }
+            }
+            return lines.toArray(new String[0]);
+        }
+
+        @Override
+        void addCommand(REPLCommand replCommand) {
+            final String commandName = replCommand.getCommand();
+            final String abbreviation = replCommand.getAbbreviation();
+
+            truffleCommandNames.add(commandName);
+            truffleCommandMap.put(commandName, replCommand);
+            if (abbreviation != null) {
+                truffleCommandMap.put(abbreviation, replCommand);
+            }
+        }
+
+        @Override
+        REPLCommand getCommand(String[] args) {
+            if (args.length == 1) {
+                clientContext.displayFailReply("truffle request not specified; try \"help truffle\"");
+                return null;
+            }
+            final String topic = args[1];
+            REPLCommand command = truffleCommandMap.get(topic);
+            if (command == null) {
+                clientContext.displayFailReply("truffle request \"" + topic + "\" not recognized");
+                return null;
+            }
+            return command;
+        }
+    };
+
+    private final REPLRemoteCommand truffleASTCommand = new REPLRemoteCommand("ast", null, "print the AST that contains the current node") {
+
+        final String[] help = {"truffle ast:  print the AST subtree that contains current node (see \"set treedepth\")",
+                        "truffle ast <n>:  print the AST subtree that contains current node to a maximum depth of <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (clientContext.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.TRUFFLE);
+            request.put(REPLMessage.TOPIC, REPLMessage.AST);
+
+            int astDepth = astDepthOption.getInt();
+            if (args.length > 2) {
+                final String depthText = args[2];
+                try {
+                    astDepth = Integer.parseInt(depthText);
+                } catch (NumberFormatException e) {
+                }
+            }
+            request.put(REPLMessage.AST_DEPTH, Integer.toString(astDepth));
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                clientContext.displayReply("AST containing the Current Node:");
+                for (REPLMessage message : replies) {
+                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
+                        clientContext.displayInfo(line);
+                    }
+                }
+            }
+        }
+    };
+
+    private void displayTruffleAST(String text) {
+        clientContext.displayReply("AST containing Current Node:");
+        for (String line : text.split("\n")) {
+            clientContext.displayInfo(line);
+        }
+    }
+
+    private final REPLRemoteCommand truffleNodeCommand = new REPLRemoteCommand("node", null, "describe current AST node") {
+
+        final String[] help = {"truffle node:  describe the AST node at the current execution context"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (clientContext.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.TRUFFLE_NODE);
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                displayTruffleNode(replies[0].get(REPLMessage.DISPLAY_MSG));
+            }
+        }
+    };
+
+    private void displayTruffleNode(String nodeString) {
+        clientContext.displayReply("Current Node: " + nodeString);
+    }
+
+    private final REPLRemoteCommand truffleSubtreeCommand = new REPLRemoteCommand("subtree", "sub", "print the AST subtree rooted at the current node") {
+
+        final String[] help = {"truffle sub:  print the AST subtree at the current node (see \"set treedepth\")", "truffle sub <n>:  print the AST subtree at the current node to maximum depth <n>",
+                        "truffle subtree:   print the AST subtree at the current node (see \"set treedepth\")", "truffle sub <n>:  print the AST subtree at the current node to maximum depth <n>"};
+
+        @Override
+        public String[] getHelp() {
+            return help;
+        }
+
+        @Override
+        public REPLMessage createRequest(REPLClientContext context, String[] args) {
+            if (clientContext.level() == 0) {
+                context.displayFailReply("no active execution");
+                return null;
+            }
+
+            final REPLMessage request = new REPLMessage();
+            request.put(REPLMessage.OP, REPLMessage.TRUFFLE);
+            request.put(REPLMessage.TOPIC, REPLMessage.SUBTREE);
+
+            int astDepth = astDepthOption.getInt();
+            if (args.length > 2) {
+                final String depthText = args[2];
+                try {
+                    astDepth = Integer.parseInt(depthText);
+                } catch (NumberFormatException e) {
+                }
+            }
+            request.put(REPLMessage.AST_DEPTH, Integer.toString(astDepth));
+            return request;
+        }
+
+        @Override
+        void processReply(REPLClientContext context, REPLMessage[] replies) {
+            if (replies[0].get(REPLMessage.STATUS).equals(REPLMessage.FAILED)) {
+                clientContext.displayFailReply(replies[0].get(REPLMessage.DISPLAY_MSG));
+            } else {
+                clientContext.displayReply("AST subtree at Current Node:");
+                for (REPLMessage message : replies) {
+                    for (String line : message.get(REPLMessage.DISPLAY_MSG).split("\n")) {
+                        clientContext.displayInfo(line);
+                    }
+                }
+            }
+        }
+    };
+
+    private void displayTruffleSubtree(String text) {
+        clientContext.displayReply("AST subtree at Current Node:");
+        for (String line : text.split("\n")) {
+            clientContext.displayInfo(line);
+        }
+    }
+
+    private final REPLCommand whereCommand = new REPLLocalCommand("where", null, "Show code around current break location") {
+
+        @Override
+        public void execute(String[] args) {
+            clientContext.displayWhere();
+        }
+    };
+
+    private abstract static class LocalOption {
+        private final String name;
+        private final String description;
+
+        protected LocalOption(String name, String description) {
+            this.name = name;
+            this.description = description;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public abstract boolean setValue(String newValue);
+
+        public boolean getBool() {
+            assert false;
+            return false;
+        }
+
+        public int getInt() {
+            assert false;
+            return 0;
+        }
+
+        public abstract String getValue();
+    }
+
+    private static final class BooleanOption extends LocalOption {
+
+        private Boolean value;
+
+        public BooleanOption(boolean value, String name, String description) {
+            super(name, description);
+            this.value = value;
+        }
+
+        @Override
+        public boolean setValue(String newValue) {
+            final Boolean valueOf = Boolean.valueOf(newValue);
+            if (valueOf == null) {
+                return false;
+            }
+            value = valueOf;
+            return true;
+        }
+
+        @Override
+        public boolean getBool() {
+            return value;
+        }
+
+        @Override
+        public String getValue() {
+            return value.toString();
+        }
+    }
+
+    private static final class IntegerOption extends LocalOption {
+
+        private Integer value;
+
+        public IntegerOption(int value, String name, String description) {
+            super(name, description);
+            this.value = value;
+        }
+
+        @Override
+        public boolean setValue(String newValue) {
+            Integer valueOf;
+            try {
+                valueOf = Integer.valueOf(newValue);
+            } catch (NumberFormatException e) {
+                return false;
+            }
+            value = valueOf;
+            return true;
+        }
+
+        @Override
+        public int getInt() {
+            return value;
+        }
+
+        @Override
+        public String getValue() {
+            return value.toString();
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/package-info.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This package contains an experimental framework for building simple command-line oriented debuggers
+ * that work with Truffle-implemented languages; it is used mainly for testing Truffle's built-in
+ * {@link com.oracle.truffle.tools.debug.engine.DebugEngine}, which actually provides the debugging services.
+ * <p>
+ * Truffle debugging is made possible by the general purpose Instrumentation Framework built
+ * into the Truffle platform.  Some online documentation for the Instrumentation Framework is available
+ * online:
+ * <quote>
+ * <a href="https://wiki.openjdk.java.net/display/Graal/Instrumentation+API">https://wiki.openjdk.java.net/display/Graal/Instrumentation+API</a>
+ * </quote>
+ * <p>
+ * Building one of these command line debuggers requires creating language-specific instances of:
+ * <ol>
+ * <li>{@link com.oracle.truffle.tools.debug.engine.DebugEngine},
+ * noting that this instance also depends on related services provided by the language implementation,</li>
+ * <li>{@link com.oracle.truffle.tools.debug.shell.REPLServer}, best accomplished by copying the implementation for
+ * Truffle's demonstration language "Simple" (a.k.a. "SL").</li>
+ * </ol>
+ *
+ * <strong>Disclaimer: </strong> although these command line debuggers are useful, they are
+ * not intended, and will not be maintained as, fully functioning debuggers.  They should be
+ * considered valuable tools for the maintainers of the {@link com.oracle.truffle.tools.debug.engine.DebugEngine},
+ * as well as for Truffle language implementors for whom concurrent access to any kind debugging services can
+ * be quite helpful.
+ * <p>
+ * <strong>Note:</strong> Both the functionality and API for this package are under active development.
+ * <p>
+ * @see com.oracle.truffle.api.instrument
+ * @see com.oracle.truffle.tools.debug.engine
+ */
+package com.oracle.truffle.tools.debug.shell;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLHandler.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.server;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+import com.oracle.truffle.tools.debug.engine.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+/**
+ * Server-side REPL implementation of an {@linkplain REPLMessage "op"}.
+ * <p>
+ * The language-agnostic handlers are implemented here.
+ */
+public abstract class REPLHandler {
+
+    // TODO (mlvdv) add support for setting/using ignore count
+    private static final int DEFAULT_IGNORE_COUNT = 0;
+
+    // TODO (mlvdv) add support for setting/using groupId
+    private static final int DEFAULT_GROUP_ID = 0;
+
+    private final String op;
+
+    protected REPLHandler(String op) {
+        this.op = op;
+    }
+
+    /**
+     * Gets the "op" implemented by this handler.
+     */
+    public final String getOp() {
+        return op;
+    }
+
+    /**
+     * Passes a request to this handler.
+     */
+    public abstract REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext);
+
+    /**
+     * Creates skeleton for a reply message that identifies the operation currently being handled.
+     */
+    protected final REPLMessage createReply() {
+        return new REPLMessage(REPLMessage.OP, op);
+    }
+
+    /**
+     * Creates skeleton for a reply message that identifies a specified operation.
+     */
+    protected static final REPLMessage createReply(String opString) {
+        return new REPLMessage(REPLMessage.OP, opString);
+    }
+
+    /**
+     * Completes a reply, reporting and explaining successful handling.
+     */
+    protected static final REPLMessage[] finishReplySucceeded(REPLMessage reply, String explanation) {
+        reply.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+        reply.put(REPLMessage.DISPLAY_MSG, explanation);
+        final REPLMessage[] replies = new REPLMessage[]{reply};
+        return replies;
+    }
+
+    /**
+     * Completes a reply, reporting and explaining failed handling.
+     */
+    protected static final REPLMessage[] finishReplyFailed(REPLMessage reply, String explanation) {
+        reply.put(REPLMessage.STATUS, REPLMessage.FAILED);
+        reply.put(REPLMessage.DISPLAY_MSG, explanation);
+        final REPLMessage[] replies = new REPLMessage[]{reply};
+        return replies;
+    }
+
+    protected static REPLMessage createBreakpointInfoMessage(Breakpoint breakpoint) {
+        final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.BREAKPOINT_INFO);
+        infoMessage.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpoint.getId()));
+        infoMessage.put(REPLMessage.BREAKPOINT_GROUP_ID, Integer.toString(breakpoint.getGroupId()));
+        infoMessage.put(REPLMessage.BREAKPOINT_STATE, breakpoint.getState().toString());
+        infoMessage.put(REPLMessage.BREAKPOINT_HIT_COUNT, Integer.toString(breakpoint.getHitCount()));
+        infoMessage.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, Integer.toString(breakpoint.getIgnoreCount()));
+        infoMessage.put(REPLMessage.INFO_VALUE, breakpoint.getLocationDescription().toString());
+        if (breakpoint.getCondition() != null) {
+            infoMessage.put(REPLMessage.BREAKPOINT_CONDITION, breakpoint.getCondition());
+        }
+        infoMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+        return infoMessage;
+    }
+
+    protected static REPLMessage createFrameInfoMessage(final REPLServerContext serverContext, FrameDebugDescription frame) {
+        final Visualizer visualizer = serverContext.getLanguage().getDebugSupport().getVisualizer();
+        final REPLMessage infoMessage = new REPLMessage(REPLMessage.OP, REPLMessage.FRAME_INFO);
+        infoMessage.put(REPLMessage.FRAME_NUMBER, Integer.toString(frame.index()));
+        final Node node = frame.node();
+
+        infoMessage.put(REPLMessage.SOURCE_LOCATION, visualizer.displaySourceLocation(node));
+        infoMessage.put(REPLMessage.METHOD_NAME, visualizer.displayMethodName(node));
+
+        if (node != null) {
+            SourceSection section = node.getSourceSection();
+            if (section == null) {
+                section = node.getEncapsulatingSourceSection();
+                if (section != null) {
+                    infoMessage.put(REPLMessage.FILE_PATH, section.getSource().getPath());
+                    infoMessage.put(REPLMessage.LINE_NUMBER, Integer.toString(section.getStartLine()));
+                    infoMessage.put(REPLMessage.SOURCE_LINE_TEXT, section.getSource().getCode(section.getStartLine()));
+                }
+            }
+        }
+        infoMessage.put(REPLMessage.STATUS, REPLMessage.SUCCEEDED);
+        return infoMessage;
+    }
+
+    public static final REPLHandler BACKTRACE_HANDLER = new REPLHandler(REPLMessage.BACKTRACE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final ArrayList<REPLMessage> frameMessages = new ArrayList<>();
+            for (FrameDebugDescription frame : serverContext.getDebugEngine().getStack()) {
+                frameMessages.add(createFrameInfoMessage(serverContext, frame));
+            }
+            if (frameMessages.size() > 0) {
+                return frameMessages.toArray(new REPLMessage[0]);
+            }
+            return finishReplyFailed(reply, "No stack");
+        }
+    };
+
+    public static final REPLHandler BREAK_AT_LINE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_LINE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final String path = request.get(REPLMessage.FILE_PATH);
+            final String fileName = request.get(REPLMessage.SOURCE_NAME);
+            final String lookupFile = (path == null || path.isEmpty()) ? fileName : path;
+            Source source = null;
+            try {
+                source = Source.fromFileName(lookupFile, true);
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+            if (source == null) {
+                return finishReplyFailed(reply, fileName + " not found");
+            }
+            Integer lineNumber = request.getIntValue(REPLMessage.LINE_NUMBER);
+            if (lineNumber == null) {
+                return finishReplyFailed(reply, "missing line number");
+            }
+            Integer ignoreCount = request.getIntValue(REPLMessage.BREAKPOINT_IGNORE_COUNT);
+            if (ignoreCount == null) {
+                ignoreCount = 0;
+            }
+            LineBreakpoint breakpoint;
+            try {
+                breakpoint = serverContext.getDebugEngine().setLineBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, source.createLineLocation(lineNumber), false);
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+            reply.put(REPLMessage.SOURCE_NAME, fileName);
+            reply.put(REPLMessage.FILE_PATH, source.getPath());
+            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpoint.getId()));
+            reply.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
+            reply.put(REPLMessage.BREAKPOINT_IGNORE_COUNT, ignoreCount.toString());
+            return finishReplySucceeded(reply, "Breakpoint set");
+        }
+    };
+
+    public static final REPLHandler BREAK_AT_LINE_ONCE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_LINE_ONCE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final String path = request.get(REPLMessage.FILE_PATH);
+            final String fileName = request.get(REPLMessage.SOURCE_NAME);
+            final String lookupFile = (path == null || path.isEmpty()) ? fileName : path;
+            Source source = null;
+            try {
+                source = Source.fromFileName(lookupFile, true);
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+            if (source == null) {
+                return finishReplyFailed(reply, fileName + " not found");
+            }
+            Integer lineNumber = request.getIntValue(REPLMessage.LINE_NUMBER);
+            if (lineNumber == null) {
+                return finishReplyFailed(reply, "missing line number");
+            }
+            try {
+                serverContext.getDebugEngine().setLineBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, source.createLineLocation(lineNumber), true);
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+            reply.put(REPLMessage.SOURCE_NAME, fileName);
+            reply.put(REPLMessage.FILE_PATH, source.getPath());
+            reply.put(REPLMessage.LINE_NUMBER, Integer.toString(lineNumber));
+            return finishReplySucceeded(reply, "One-shot line breakpoint set");
+        }
+    };
+
+    public static final REPLHandler BREAK_AT_THROW_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_THROW) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            try {
+                serverContext.getDebugEngine().setTagBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, StandardSyntaxTag.THROW, false);
+                return finishReplySucceeded(reply, "Breakpoint at any throw set");
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+        }
+    };
+
+    public static final REPLHandler BREAK_AT_THROW_ONCE_HANDLER = new REPLHandler(REPLMessage.BREAK_AT_THROW_ONCE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            try {
+                serverContext.getDebugEngine().setTagBreakpoint(DEFAULT_GROUP_ID, DEFAULT_IGNORE_COUNT, StandardSyntaxTag.THROW, true);
+                return finishReplySucceeded(reply, "One-shot breakpoint at any throw set");
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.getMessage());
+            }
+        }
+    };
+
+    public static final REPLHandler BREAKPOINT_INFO_HANDLER = new REPLHandler(REPLMessage.BREAKPOINT_INFO) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final ArrayList<REPLMessage> infoMessages = new ArrayList<>();
+            for (Breakpoint breakpoint : serverContext.getDebugEngine().getBreakpoints()) {
+                infoMessages.add(createBreakpointInfoMessage(breakpoint));
+            }
+            if (infoMessages.size() > 0) {
+                return infoMessages.toArray(new REPLMessage[0]);
+            }
+            return finishReplyFailed(reply, "No breakpoints");
+        }
+    };
+
+    public static final REPLHandler CLEAR_BREAK_HANDLER = new REPLHandler(REPLMessage.CLEAR_BREAK) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
+            if (breakpointNumber == null) {
+                return finishReplyFailed(reply, "missing breakpoint number");
+            }
+            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
+            if (breakpoint == null) {
+                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
+            }
+            breakpoint.dispose();
+            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " cleared");
+        }
+    };
+
+    public static final REPLHandler CONTINUE_HANDLER = new REPLHandler(REPLMessage.CONTINUE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            serverContext.getDebugEngine().prepareContinue();
+            return finishReplySucceeded(reply, "Continue mode entered");
+        }
+    };
+
+    public static final REPLHandler DELETE_HANDLER = new REPLHandler(REPLMessage.DELETE_BREAK) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            int deleteCount = 0;
+            for (Breakpoint breakpoint : serverContext.getDebugEngine().getBreakpoints()) {
+                breakpoint.dispose();
+                deleteCount++;
+            }
+            if (deleteCount == 0) {
+                return finishReplyFailed(reply, "no breakpoints to delete");
+            }
+            return finishReplySucceeded(reply, Integer.toString(deleteCount) + " breakpoints deleted");
+        }
+    };
+
+    public static final REPLHandler DISABLE_BREAK_HANDLER = new REPLHandler(REPLMessage.DISABLE_BREAK) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
+            if (breakpointNumber == null) {
+                return finishReplyFailed(reply, "missing breakpoint number");
+            }
+            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
+            if (breakpoint == null) {
+                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
+            }
+            breakpoint.setEnabled(false);
+            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " disabled");
+        }
+    };
+
+    public static final REPLHandler ENABLE_BREAK_HANDLER = new REPLHandler(REPLMessage.ENABLE_BREAK) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
+            if (breakpointNumber == null) {
+                return finishReplyFailed(reply, "missing breakpoint number");
+            }
+            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
+            if (breakpoint == null) {
+                return finishReplyFailed(reply, "no breakpoint number " + breakpointNumber);
+            }
+            breakpoint.setEnabled(true);
+            reply.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+            return finishReplySucceeded(reply, "Breakpoint " + breakpointNumber + " enabled");
+        }
+    };
+
+    public static final REPLHandler FILE_HANDLER = new REPLHandler(REPLMessage.FILE) {
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final String fileName = request.get(REPLMessage.SOURCE_NAME);
+            if (fileName == null) {
+                return finishReplyFailed(reply, "no file specified");
+            }
+            try {
+                Source source = Source.fromFileName(fileName);
+                if (source == null) {
+                    reply.put(REPLMessage.SOURCE_NAME, fileName);
+                    return finishReplyFailed(reply, " not found");
+                } else {
+                    reply.put(REPLMessage.SOURCE_NAME, fileName);
+                    reply.put(REPLMessage.FILE_PATH, source.getPath());
+                    reply.put(REPLMessage.CODE, source.getCode());
+                    return finishReplySucceeded(reply, "file found");
+                }
+            } catch (Exception ex) {
+                reply.put(REPLMessage.SOURCE_NAME, fileName);
+                return finishReplyFailed(reply, "file \"" + fileName + "\" not found");
+            }
+        }
+    };
+
+    // TODO (mlvdv) deal with slot locals explicitly
+    /**
+     * Returns a general description of the frame, plus a textual summary of the slot values: one
+     * per line.
+     */
+    public static final REPLHandler FRAME_HANDLER = new REPLHandler(REPLMessage.FRAME) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final Integer frameNumber = request.getIntValue(REPLMessage.FRAME_NUMBER);
+            if (frameNumber == null) {
+                return finishReplyFailed(reply, "no frame number specified");
+            }
+            final List<FrameDebugDescription> stack = serverContext.getDebugEngine().getStack();
+            if (frameNumber < 0 || frameNumber >= stack.size()) {
+                return finishReplyFailed(reply, "frame number " + frameNumber + " out of range");
+            }
+            final FrameDebugDescription frameDescription = stack.get(frameNumber);
+            final REPLMessage frameMessage = createFrameInfoMessage(serverContext, frameDescription);
+            final Frame frame = frameDescription.frameInstance().getFrame(FrameInstance.FrameAccess.READ_ONLY, true);
+            final Language language = serverContext.getLanguage();
+            final Visualizer visualizer = language.getDebugSupport().getVisualizer();
+            final FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
+            try {
+                final StringBuilder sb = new StringBuilder();
+                for (FrameSlot slot : frameDescriptor.getSlots()) {
+                    sb.append(Integer.toString(slot.getIndex()) + ": " + visualizer.displayIdentifier(slot) + " = ");
+                    try {
+                        final Object value = frame.getValue(slot);
+                        sb.append(visualizer.displayValue(value, 0));
+                    } catch (Exception ex) {
+                        sb.append("???");
+                    }
+                    sb.append("\n");
+                }
+                return finishReplySucceeded(frameMessage, sb.toString());
+            } catch (Exception ex) {
+                return finishReplyFailed(frameMessage, ex.toString());
+            }
+        }
+    };
+
+    public static final REPLHandler KILL_HANDLER = new REPLHandler(REPLMessage.KILL) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            if (serverContext.getLevel() == 0) {
+                return finishReplyFailed(createReply(), "nothing to kill");
+            }
+            throw new KillException();
+        }
+    };
+
+    public static final REPLHandler QUIT_HANDLER = new REPLHandler(REPLMessage.QUIT) {
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            throw new QuitException();
+        }
+    };
+
+    public static final REPLHandler SET_BREAK_CONDITION_HANDLER = new REPLHandler(REPLMessage.SET_BREAK_CONDITION) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.SET_BREAK_CONDITION);
+            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
+            if (breakpointNumber == null) {
+                return finishReplyFailed(message, "missing breakpoint number");
+            }
+            message.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
+            if (breakpoint == null) {
+                return finishReplyFailed(message, "no breakpoint number " + breakpointNumber);
+            }
+            final String expr = request.get(REPLMessage.BREAKPOINT_CONDITION);
+            if (expr == null || expr.isEmpty()) {
+                return finishReplyFailed(message, "missing condition for " + breakpointNumber);
+            }
+            try {
+                breakpoint.setCondition(expr);
+            } catch (DebugException ex) {
+                return finishReplyFailed(message, "invalid condition for " + breakpointNumber);
+            } catch (UnsupportedOperationException ex) {
+                return finishReplyFailed(message, "conditions not unsupported by breakpoint " + breakpointNumber);
+            }
+            message.put(REPLMessage.BREAKPOINT_CONDITION, expr);
+            return finishReplySucceeded(message, "Breakpoint " + breakpointNumber + " condition=\"" + expr + "\"");
+        }
+    };
+
+    public static final REPLHandler STEP_INTO_HANDLER = new REPLHandler(REPLMessage.STEP_INTO) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            Integer repeat = request.getIntValue(REPLMessage.REPEAT);
+            if (repeat == null) {
+                repeat = 1;
+            }
+            serverContext.getDebugEngine().prepareStepInto(repeat);
+            return finishReplySucceeded(reply, "StepInto <" + repeat + "> enabled");
+        }
+    };
+
+    public static final REPLHandler STEP_OUT_HANDLER = new REPLHandler(REPLMessage.STEP_OUT) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            serverContext.getDebugEngine().prepareStepOut();
+            return finishReplySucceeded(createReply(), "StepOut enabled");
+        }
+    };
+
+    public static final REPLHandler STEP_OVER_HANDLER = new REPLHandler(REPLMessage.STEP_OVER) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext debugServerContextFrame) {
+            final REPLMessage reply = createReply();
+            Integer repeat = request.getIntValue(REPLMessage.REPEAT);
+            if (repeat == null) {
+                repeat = 1;
+            }
+            debugServerContextFrame.getDebugEngine().prepareStepOver(repeat);
+            return finishReplySucceeded(reply, "StepOver <" + repeat + "> enabled");
+        }
+    };
+
+    public static final REPLHandler TRUFFLE_HANDLER = new REPLHandler(REPLMessage.TRUFFLE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter();
+            final String topic = request.get(REPLMessage.TOPIC);
+            reply.put(REPLMessage.TOPIC, topic);
+            Node node = serverContext.getNode();
+            if (node == null) {
+                return finishReplyFailed(reply, "no current AST node");
+            }
+            final Integer depth = request.getIntValue(REPLMessage.AST_DEPTH);
+            if (depth == null) {
+                return finishReplyFailed(reply, "missing AST depth");
+            }
+            try {
+                switch (topic) {
+                    case REPLMessage.AST:
+                        while (node.getParent() != null) {
+                            node = node.getParent();
+                        }
+                        final String astText = astPrinter.printTreeToString(node, depth, serverContext.getNode());
+                        return finishReplySucceeded(reply, astText);
+                    case REPLMessage.SUBTREE:
+                    case REPLMessage.SUB:
+                        final String subTreeText = astPrinter.printTreeToString(node, depth);
+                        return finishReplySucceeded(reply, subTreeText);
+                    default:
+                        return finishReplyFailed(reply, "Unknown \"" + REPLMessage.TRUFFLE.toString() + "\" topic");
+                }
+
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.toString());
+            }
+        }
+    };
+
+    public static final REPLHandler UNSET_BREAK_CONDITION_HANDLER = new REPLHandler(REPLMessage.UNSET_BREAK_CONDITION) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage message = new REPLMessage(REPLMessage.OP, REPLMessage.UNSET_BREAK_CONDITION);
+            Integer breakpointNumber = request.getIntValue(REPLMessage.BREAKPOINT_ID);
+            if (breakpointNumber == null) {
+                return finishReplyFailed(message, "missing breakpoint number");
+            }
+            message.put(REPLMessage.BREAKPOINT_ID, Integer.toString(breakpointNumber));
+            final Breakpoint breakpoint = serverContext.getDebugEngine().findBreakpoint(breakpointNumber);
+            if (breakpoint == null) {
+                return finishReplyFailed(message, "no breakpoint number " + breakpointNumber);
+            }
+            try {
+                breakpoint.setCondition(null);
+            } catch (DebugException e) {
+                return finishReplyFailed(message, e.getMessage());
+            }
+            return finishReplyFailed(message, "Breakpoint " + breakpointNumber + " condition cleared");
+        }
+    };
+
+    public static final REPLHandler TRUFFLE_NODE_HANDLER = new REPLHandler(REPLMessage.TRUFFLE_NODE) {
+
+        @Override
+        public REPLMessage[] receive(REPLMessage request, REPLServerContext serverContext) {
+            final REPLMessage reply = createReply();
+            final ASTPrinter astPrinter = serverContext.getLanguage().getDebugSupport().getVisualizer().getASTPrinter();
+            final Node node = serverContext.getNode();
+            if (node == null) {
+                return finishReplyFailed(reply, "no current AST node");
+            }
+
+            try {
+                final StringBuilder sb = new StringBuilder();
+                sb.append(astPrinter.printNodeWithInstrumentation(node));
+
+                final SourceSection sourceSection = node.getSourceSection();
+                if (sourceSection != null) {
+                    final String code = sourceSection.getCode();
+                    sb.append(" \"");
+                    sb.append(code.substring(0, Math.min(code.length(), 15)));
+                    sb.append("...\"");
+                }
+                return finishReplySucceeded(reply, sb.toString());
+            } catch (Exception ex) {
+                return finishReplyFailed(reply, ex.toString());
+            }
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.debug.shell/src/com/oracle/truffle/tools/debug/shell/server/REPLServerContext.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.debug.shell.server;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.vm.TruffleVM.Language;
+import com.oracle.truffle.tools.debug.engine.*;
+import com.oracle.truffle.tools.debug.shell.*;
+
+public abstract class REPLServerContext {
+
+    private final int level;
+    private final Node astNode;
+    private final MaterializedFrame mFrame;
+
+    protected REPLServerContext(int level, Node astNode, MaterializedFrame mFrame) {
+        this.level = level;
+        this.astNode = astNode;
+        this.mFrame = mFrame;
+    }
+
+    /**
+     * The nesting depth of this context in the current session.
+     */
+    public int getLevel() {
+        return level;
+    }
+
+    /**
+     * The AST node where execution is halted in this context.
+     */
+    public Node getNode() {
+        return astNode;
+    }
+
+    /**
+     * The frame where execution is halted in this context.
+     */
+    public MaterializedFrame getFrame() {
+        return mFrame;
+    }
+
+    public abstract Language getLanguage();
+
+    public abstract DebugEngine getDebugEngine();
+
+    /**
+     * Dispatches a REPL request to the appropriate handler.
+     */
+    public abstract REPLMessage[] receive(REPLMessage request);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/CoverageTrackerTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.test;
+
+import static com.oracle.truffle.tools.test.TestNodes.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.tools.*;
+
+public class CoverageTrackerTest {
+
+    @Test
+    public void testNoExecution() {
+        final CoverageTracker tool = new CoverageTracker();
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+        tool.install();
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+        tool.setEnabled(false);
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+        tool.setEnabled(true);
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+        tool.reset();
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+        tool.dispose();
+        assertEquals(tool.getCounts().entrySet().size(), 0);
+    }
+
+    @Test
+    public void testToolCreatedTooLate() {
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+        final CoverageTracker tool = new CoverageTracker();
+        tool.install();
+        assertEquals(13, expr13rootNode.execute(null));
+        assertTrue(tool.getCounts().isEmpty());
+        tool.dispose();
+    }
+
+    @Test
+    public void testToolInstalledcTooLate() {
+        final CoverageTracker tool = new CoverageTracker();
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+        tool.install();
+        assertEquals(13, expr13rootNode.execute(null));
+        assertTrue(tool.getCounts().isEmpty());
+        tool.dispose();
+    }
+
+    @Test
+    public void testCountingCoverage() {
+        final CoverageTracker tool = new CoverageTracker();
+        tool.install();
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+
+        // Not probed yet.
+        assertEquals(13, expr13rootNode.execute(null));
+        assertTrue(tool.getCounts().isEmpty());
+
+        final Node addNode = expr13rootNode.getChildren().iterator().next();
+        final Probe probe = addNode.probe();
+
+        // Probed but not tagged yet.
+        assertEquals(13, expr13rootNode.execute(null));
+        assertTrue(tool.getCounts().isEmpty());
+
+        probe.tagAs(StandardSyntaxTag.STATEMENT, "fake statement for testing");
+
+        // Counting now; execute once
+        assertEquals(13, expr13rootNode.execute(null));
+
+        final Long[] longs1 = tool.getCounts().get(addNode.getSourceSection().getSource());
+        assertNotNull(longs1);
+        assertEquals(longs1.length, 2);
+        assertNull(longs1[0]);  // Line 1 is empty (text lines are 1-based)
+        assertEquals(1L, longs1[1].longValue());  // Expression is on line 2
+
+        // Execute 99 more times
+        for (int i = 0; i < 99; i++) {
+            assertEquals(13, expr13rootNode.execute(null));
+        }
+
+        final Long[] longs100 = tool.getCounts().get(addNode.getSourceSection().getSource());
+        assertNotNull(longs100);
+        assertEquals(longs100.length, 2);
+        assertNull(longs100[0]);
+        assertEquals(100L, longs100[1].longValue());
+
+        tool.dispose();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/LineToProbesMapTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.test;
+
+import static com.oracle.truffle.tools.test.TestNodes.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.tools.*;
+
+public class LineToProbesMapTest {
+
+    @Test
+    public void testToolCreatedTooLate() {
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+        final Node addNode = expr13rootNode.getChildren().iterator().next();
+        final Probe probe = addNode.probe();
+        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
+        assertEquals(lineLocation, expr13Line2);
+
+        final LineToProbesMap tool = new LineToProbesMap();
+        tool.install();
+
+        assertNull(tool.findFirstProbe(expr13Line1));
+        assertNull(tool.findFirstProbe(expr13Line2));
+        tool.dispose();
+    }
+
+    @Test
+    public void testToolInstalledTooLate() {
+        final LineToProbesMap tool = new LineToProbesMap();
+
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+        final Node addNode = expr13rootNode.getChildren().iterator().next();
+        final Probe probe = addNode.probe();
+        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
+        assertEquals(lineLocation, expr13Line2);
+
+        tool.install();
+
+        assertNull(tool.findFirstProbe(expr13Line1));
+        assertNull(tool.findFirstProbe(expr13Line2));
+        tool.dispose();
+    }
+
+    @Test
+    public void testMapping() {
+        final LineToProbesMap tool = new LineToProbesMap();
+        tool.install();
+
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+        final Node addNode = expr13rootNode.getChildren().iterator().next();
+        final Probe probe = addNode.probe();
+        final LineLocation lineLocation = probe.getProbedSourceSection().getLineLocation();
+        assertEquals(lineLocation, expr13Line2);
+
+        assertNull(tool.findFirstProbe(expr13Line1));
+        assertEquals(tool.findFirstProbe(expr13Line2), probe);
+        tool.dispose();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/NodeExecCounterTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.test;
+
+import static com.oracle.truffle.tools.test.TestNodes.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.tools.*;
+import com.oracle.truffle.tools.NodeExecCounter.NodeExecutionCount;
+import com.oracle.truffle.tools.test.TestNodes.TestAddNode;
+import com.oracle.truffle.tools.test.TestNodes.TestValueNode;
+
+public class NodeExecCounterTest {
+
+    @Test
+    public void testNoExecution() {
+        final NodeExecCounter tool = new NodeExecCounter();
+        assertEquals(tool.getCounts().length, 0);
+        tool.install();
+        assertEquals(tool.getCounts().length, 0);
+        tool.setEnabled(false);
+        assertEquals(tool.getCounts().length, 0);
+        tool.setEnabled(true);
+        assertEquals(tool.getCounts().length, 0);
+        tool.reset();
+        assertEquals(tool.getCounts().length, 0);
+        tool.dispose();
+        assertEquals(tool.getCounts().length, 0);
+    }
+
+    @Test
+    public void testToolCreatedTooLate() {
+        final CallTarget expr13callTarget = createExpr13TestCallTarget();
+        final NodeExecCounter tool = new NodeExecCounter();
+        tool.install();
+        assertEquals(13, expr13callTarget.call());
+        assertEquals(tool.getCounts().length, 0);
+        tool.dispose();
+    }
+
+    @Test
+    public void testToolInstalledcTooLate() {
+        final NodeExecCounter tool = new NodeExecCounter();
+        final CallTarget expr13callTarget = createExpr13TestCallTarget();
+        tool.install();
+        assertEquals(13, expr13callTarget.call());
+        assertEquals(tool.getCounts().length, 0);
+        tool.dispose();
+    }
+
+    @Test
+    public void testCountingAll() {
+        final NodeExecCounter tool = new NodeExecCounter();
+        tool.install();
+        final CallTarget expr13callTarget = createExpr13TestCallTarget();
+
+        // execute once
+        assertEquals(13, expr13callTarget.call());
+        final NodeExecutionCount[] count1 = tool.getCounts();
+        assertNotNull(count1);
+        assertEquals(count1.length, 2);
+        for (NodeExecutionCount count : count1) {
+            final Class<?> class1 = count.nodeClass();
+            final long executionCount = count.executionCount();
+            if (class1 == TestAddNode.class) {
+                assertEquals(executionCount, 1);
+            } else if (class1 == TestValueNode.class) {
+                assertEquals(executionCount, 2);
+            } else {
+                fail();
+            }
+        }
+
+        // Execute 99 more times
+        for (int i = 0; i < 99; i++) {
+            assertEquals(13, expr13callTarget.call());
+        }
+        final NodeExecutionCount[] counts100 = tool.getCounts();
+        assertNotNull(counts100);
+        assertEquals(counts100.length, 2);
+        for (NodeExecutionCount count : counts100) {
+            final Class<?> class1 = count.nodeClass();
+            final long executionCount = count.executionCount();
+            if (class1 == TestAddNode.class) {
+                assertEquals(executionCount, 100);
+            } else if (class1 == TestValueNode.class) {
+                assertEquals(executionCount, 200);
+            } else {
+                fail();
+            }
+        }
+
+        tool.dispose();
+    }
+
+    @Test
+    public void testCountingTagged() {
+        final NodeExecCounter tool = new NodeExecCounter(StandardSyntaxTag.STATEMENT);
+        tool.install();
+        final RootNode expr13rootNode = createExpr13TestRootNode();
+
+        // Not probed yet.
+        assertEquals(13, expr13rootNode.execute(null));
+        assertEquals(tool.getCounts().length, 0);
+
+        final Node addNode = expr13rootNode.getChildren().iterator().next();
+        final Probe probe = addNode.probe();
+
+        // Probed but not tagged yet.
+        assertEquals(13, expr13rootNode.execute(null));
+        assertEquals(tool.getCounts().length, 0);
+
+        probe.tagAs(StandardSyntaxTag.STATEMENT, "fake statement for testing");
+
+        // Counting now; execute once
+        assertEquals(13, expr13rootNode.execute(null));
+        final NodeExecutionCount[] counts1 = tool.getCounts();
+        assertNotNull(counts1);
+        assertEquals(counts1.length, 1);
+        final NodeExecutionCount count1 = counts1[0];
+        assertNotNull(count1);
+        assertEquals(count1.nodeClass(), addNode.getClass());
+        assertEquals(count1.executionCount(), 1);
+
+        // Execute 99 more times
+        for (int i = 0; i < 99; i++) {
+            assertEquals(13, expr13rootNode.execute(null));
+        }
+
+        final NodeExecutionCount[] counts100 = tool.getCounts();
+        assertNotNull(counts100);
+        assertEquals(counts100.length, 1);
+        final NodeExecutionCount count100 = counts100[0];
+        assertNotNull(count100);
+        assertEquals(count100.nodeClass(), addNode.getClass());
+        assertEquals(count100.executionCount(), 100);
+
+        tool.dispose();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TestNodes.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.test;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * Nodes and an {@linkplain CallTarget executable ASTs} for testing.
+ */
+class TestNodes {
+
+    /**
+     * A fake source used for testing: empty line 1, expression on line 2.
+     */
+    public static final Source expr13Source = Source.fromText("\n6+7\n", "Test Source: expression on line 2 that evaluates to 13");
+    public static final LineLocation expr13Line1 = expr13Source.createLineLocation(1);
+    public static final LineLocation expr13Line2 = expr13Source.createLineLocation(2);
+
+    /**
+     * An executable addition expression that evaluates to 13.
+     */
+    static CallTarget createExpr13TestCallTarget() {
+        final RootNode rootNode = createExpr13TestRootNode();
+        return Truffle.getRuntime().createCallTarget(rootNode);
+    }
+
+    /**
+     * Root holding an addition expression that evaluates to 13.
+     */
+    static RootNode createExpr13TestRootNode() {
+        final TestLanguageNode ast = createExpr13AST();
+        final TestRootNode rootNode = new TestRootNode(ast);
+        rootNode.adoptChildren();
+        return rootNode;
+    }
+
+    /**
+     * Addition expression that evaluates to 13, with faked source attribution.
+     */
+    static TestLanguageNode createExpr13AST() {
+        final SourceSection leftSourceSection = expr13Source.createSection("left", 1, 1);
+        final TestValueNode leftValueNode = new TestValueNode(6, leftSourceSection);
+        final SourceSection rightSourceSection = expr13Source.createSection("right", 3, 1);
+        final TestValueNode rightValueNode = new TestValueNode(7, rightSourceSection);
+        final SourceSection exprSourceSection = expr13Source.createSection("expr", 1, 3);
+        return new TestAddNode(leftValueNode, rightValueNode, exprSourceSection);
+    }
+
+    abstract static class TestLanguageNode extends Node {
+        public abstract Object execute(VirtualFrame frame);
+
+        public TestLanguageNode() {
+        }
+
+        public TestLanguageNode(SourceSection srcSection) {
+            super(srcSection);
+        }
+
+        @Override
+        public boolean isInstrumentable() {
+            return true;
+        }
+
+        @Override
+        public WrapperNode createWrapperNode() {
+            return new TestWrapperNode(this);
+        }
+    }
+
+    @NodeInfo(cost = NodeCost.NONE)
+    static class TestWrapperNode extends TestLanguageNode implements WrapperNode {
+        @Child private TestLanguageNode child;
+        @Child private ProbeNode probeNode;
+
+        public TestWrapperNode(TestLanguageNode child) {
+            assert !(child instanceof TestWrapperNode);
+            this.child = child;
+        }
+
+        @Override
+        public String instrumentationInfo() {
+            return "Wrapper node for testing";
+        }
+
+        @Override
+        public boolean isInstrumentable() {
+            return false;
+        }
+
+        @Override
+        public void insertProbe(ProbeNode newProbeNode) {
+            this.probeNode = newProbeNode;
+        }
+
+        @Override
+        public Probe getProbe() {
+            return probeNode.getProbe();
+        }
+
+        @Override
+        public Node getChild() {
+            return child;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            probeNode.enter(child, frame);
+            Object result;
+
+            try {
+                result = child.execute(frame);
+                probeNode.returnValue(child, frame, result);
+            } catch (KillException e) {
+                throw (e);
+            } catch (Exception e) {
+                probeNode.returnExceptional(child, frame, e);
+                throw (e);
+            }
+
+            return result;
+        }
+    }
+
+    /**
+     * Truffle requires that all guest languages to have a {@link RootNode} which sits atop any AST
+     * of the guest language. This is necessary since creating a {@link CallTarget} is how Truffle
+     * completes an AST. The root nodes serves as our entry point into a program.
+     */
+    static class TestRootNode extends RootNode {
+        @Child private TestLanguageNode body;
+
+        /**
+         * This constructor emulates the global machinery that applies registered probers to every
+         * newly created AST. Global registry is not used, since that would interfere with other
+         * tests run in the same environment.
+         */
+        public TestRootNode(TestLanguageNode body) {
+            super(null);
+            this.body = body;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return body.execute(frame);
+        }
+
+        @Override
+        public boolean isCloningAllowed() {
+            return true;
+        }
+
+        @Override
+        public void applyInstrumentation() {
+            Probe.applyASTProbers(body);
+        }
+    }
+
+    static class TestValueNode extends TestLanguageNode {
+        private final int value;
+
+        public TestValueNode(int value) {
+            this.value = value;
+        }
+
+        public TestValueNode(int value, SourceSection srcSection) {
+            super(srcSection);
+            this.value = value;
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return new Integer(this.value);
+        }
+    }
+
+    static class TestAddNode extends TestLanguageNode {
+        @Child private TestLanguageNode leftChild;
+        @Child private TestLanguageNode rightChild;
+
+        public TestAddNode(TestValueNode leftChild, TestValueNode rightChild, SourceSection sourceSection) {
+            super(sourceSection);
+            this.leftChild = insert(leftChild);
+            this.rightChild = insert(rightChild);
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return new Integer(((Integer) leftChild.execute(frame)).intValue() + ((Integer) rightChild.execute(frame)).intValue());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools.test/src/com/oracle/truffle/tools/test/TruffleToolTest.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.instrument.*;
+
+/**
+ * Test the basic life cycle properties shared by all instances of {@link InstrumentationTool}.
+ */
+public class TruffleToolTest {
+
+    @Test
+    public void testEmptyLifeCycle() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        assertFalse(tool.isEnabled());
+        tool.install();
+        assertTrue(tool.isEnabled());
+        tool.reset();
+        assertTrue(tool.isEnabled());
+        tool.setEnabled(false);
+        assertFalse(tool.isEnabled());
+        tool.reset();
+        assertFalse(tool.isEnabled());
+        tool.setEnabled(true);
+        assertTrue(tool.isEnabled());
+        tool.reset();
+        assertTrue(tool.isEnabled());
+        tool.dispose();
+        assertFalse(tool.isEnabled());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNotYetInstalled1() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.reset();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNotYetInstalled2() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.setEnabled(true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNotYetInstalled3() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.dispose();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAlreadyInstalled() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.install();
+        tool.install();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAlreadyDisposed1() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.install();
+        tool.dispose();
+        tool.install();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAlreadyDisposed2() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.install();
+        tool.dispose();
+        tool.reset();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAlreadyDisposed3() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.install();
+        tool.dispose();
+        tool.setEnabled(true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAlreadyDisposed4() {
+        final DummyTruffleTool tool = new DummyTruffleTool();
+        tool.install();
+        tool.dispose();
+        tool.dispose();
+    }
+
+    private static final class DummyTruffleTool extends InstrumentationTool {
+
+        @Override
+        protected boolean internalInstall() {
+            return true;
+        }
+
+        @Override
+        protected void internalReset() {
+        }
+
+        @Override
+        protected void internalDispose() {
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/CoverageTracker.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools;
+
+import java.io.*;
+import java.util.*;
+import java.util.Map.Entry;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * An {@link InstrumentationTool} that counts interpreter <em>execution calls</em> to AST nodes that
+ * hold a specified {@linkplain SyntaxTag syntax tag}, tabulated by source and line number
+ * associated with each node. Syntax tags are presumed to be applied external to the tool. If no tag
+ * is specified, {@linkplain StandardSyntaxTag#STATEMENT STATEMENT} is used, corresponding to
+ * conventional behavior for code coverage tools.
+ * <p>
+ * No counts will be kept for execution in sources that hold the {@link SourceTag}
+ * {@link Tags#NO_COVERAGE}.
+ * <p>
+ * <b>Tool Life Cycle</b>
+ * <p>
+ * See {@link InstrumentationTool} for the life cycle common to all such tools.
+ * <p>
+ * <b>Execution Counts</b>
+ * <p>
+ * <ul>
+ * <li>"Execution call" on a node is is defined as invocation of a node method that is instrumented
+ * to produce the event {@link SimpleInstrumentListener#enter(Probe)};</li>
+ * <li>Execution calls are tabulated only at <em>instrumented</em> nodes, i.e. those for which
+ * {@linkplain Node#isInstrumentable() isInstrumentable() == true};</li>
+ * <li>Execution calls are tabulated only at nodes present in the AST when originally created;
+ * dynamically added nodes will not be instrumented.</li>
+ * </ul>
+ * </p>
+ * <b>Results</b>
+ * <p>
+ * A modification-safe copy of the {@linkplain #getCounts() counts} can be retrieved at any time,
+ * without effect on the state of the tool.
+ * </p>
+ * <p>
+ * A "default" {@linkplain #print(PrintStream) print()} method can summarizes the current counts at
+ * any time in a simple textual format, with no other effect on the state of the tool.
+ * </p>
+ *
+ * @see Instrument
+ * @see SyntaxTag
+ */
+public final class CoverageTracker extends InstrumentationTool {
+
+    public enum Tags implements SourceTag {
+
+        /**
+         * Report no counts for sources holding this tag.
+         */
+        NO_COVERAGE("No Coverage", "Coverage Tracker will igore");
+
+        private final String name;
+        private final String description;
+
+        private Tags(String name, String description) {
+            this.name = name;
+            this.description = description;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+    }
+
+    /** Counting data. */
+    private final Map<LineLocation, CoverageRecord> coverageMap = new HashMap<>();
+
+    /** Needed for disposal. */
+    private final List<Instrument> instruments = new ArrayList<>();
+
+    /**
+     * Coverage counting is restricted to nodes holding this tag.
+     */
+    private final SyntaxTag countingTag;
+
+    private final ProbeListener probeListener;
+
+    /**
+     * Create a per-line coverage tool for nodes tagged as {@linkplain StandardSyntaxTag#STATEMENT
+     * statements} in subsequently created ASTs.
+     */
+    public CoverageTracker() {
+        this(StandardSyntaxTag.STATEMENT);
+    }
+
+    /**
+     * Create a per-line coverage tool for nodes tagged as specified, presuming that tags applied
+     * outside this tool.
+     */
+    public CoverageTracker(SyntaxTag tag) {
+        this.probeListener = new CoverageProbeListener();
+        this.countingTag = tag;
+    }
+
+    @Override
+    protected boolean internalInstall() {
+        Probe.addProbeListener(probeListener);
+        return true;
+    }
+
+    @Override
+    protected void internalReset() {
+        coverageMap.clear();
+    }
+
+    @Override
+    protected void internalDispose() {
+        Probe.removeProbeListener(probeListener);
+        for (Instrument instrument : instruments) {
+            instrument.dispose();
+        }
+    }
+
+    /**
+     * Gets a modification-safe summary of the current per-type node execution counts; does not
+     * affect the counts.
+     * <p>
+     * The map holds an array for each source, and elements of the a array corresponding to the
+     * textual lines of that source. An array entry contains null if the corresponding line of
+     * source is associated with no nodes of the relevant type, i.e. where no count was made. A
+     * numeric entry represents the execution count at the corresponding line of source.
+     * <p>
+     * <b>Note:</b> source line numbers are 1-based, so array index {@code i} corresponds to source
+     * line number {@code i + 1}
+     */
+    public Map<Source, Long[]> getCounts() {
+
+        /**
+         * Counters for every {Source, line number} for which a counter was installed, i.e. for
+         * every line associated with an appropriately tagged AST node; iterable in order of source
+         * name, then line number.
+         */
+        final TreeSet<Entry<LineLocation, CoverageRecord>> entries = new TreeSet<>(new LineLocationEntryComparator());
+
+        for (Entry<LineLocation, CoverageRecord> entry : coverageMap.entrySet()) {
+            entries.add(entry);
+        }
+        final Map<Source, Long[]> result = new HashMap<>();
+        Source curSource = null;
+        Long[] curLineTable = null;
+        for (Entry<LineLocation, CoverageRecord> entry : entries) {
+            final LineLocation key = entry.getKey();
+            final Source source = key.getSource();
+            final int lineNo = key.getLineNumber();
+            if (source != curSource) {
+                if (curSource != null) {
+                    result.put(curSource, curLineTable);
+                }
+                curSource = source;
+                curLineTable = new Long[source.getLineCount()];
+            }
+            curLineTable[lineNo - 1] = entry.getValue().count;
+        }
+        if (curSource != null) {
+            result.put(curSource, curLineTable);
+        }
+        return result;
+    }
+
+    /**
+     * A default printer for the current line counts, producing lines of the form " (<count>) <line
+     * number> : <text of line>", grouped by source.
+     */
+    public void print(PrintStream out) {
+        out.println();
+        out.println(countingTag.name() + " coverage:");
+
+        /**
+         * Counters for every {Source, line number} for which a counter was installed, i.e. for
+         * every line associated with an appropriately tagged AST node; iterable in order of source
+         * name, then line number.
+         */
+        final TreeSet<Entry<LineLocation, CoverageRecord>> entries = new TreeSet<>(new LineLocationEntryComparator());
+
+        for (Entry<LineLocation, CoverageRecord> entry : coverageMap.entrySet()) {
+            entries.add(entry);
+        }
+        Source curSource = null;
+        int curLineNo = 1;
+        for (Entry<LineLocation, CoverageRecord> entry : entries) {
+            final LineLocation key = entry.getKey();
+            final Source source = key.getSource();
+            final int lineNo = key.getLineNumber();
+            if (source != curSource) {
+                if (curSource != null) {
+                    while (curLineNo <= curSource.getLineCount()) {
+                        displayLine(out, null, curSource, curLineNo++);
+                    }
+                }
+                curSource = source;
+                curLineNo = 1;
+                out.println();
+                out.println(source.getPath());
+            }
+            while (curLineNo < lineNo) {
+                displayLine(out, null, curSource, curLineNo++);
+            }
+            displayLine(out, entry.getValue(), curSource, curLineNo++);
+        }
+        if (curSource != null) {
+            while (curLineNo <= curSource.getLineCount()) {
+                displayLine(out, null, curSource, curLineNo++);
+            }
+        }
+    }
+
+    private static void displayLine(PrintStream out, CoverageRecord record, Source source, int lineNo) {
+        if (record == null) {
+            out.format("%14s", " ");
+        } else {
+            out.format("(%12d)", record.count);
+        }
+        out.format(" %3d: ", lineNo);
+        out.println(source.getCode(lineNo));
+    }
+
+    /**
+     * A listener for events at each instrumented AST location. This listener counts
+     * "execution calls" to the instrumented node.
+     */
+    private final class CoverageRecord extends DefaultSimpleInstrumentListener {
+
+        private final SourceSection srcSection; // The text of the code being counted
+        private Instrument instrument;  // The attached Instrument, in case need to remove.
+        private long count = 0;
+
+        CoverageRecord(SourceSection srcSection) {
+            this.srcSection = srcSection;
+        }
+
+        @Override
+        public void enter(Probe probe) {
+            if (isEnabled()) {
+                count++;
+            }
+        }
+
+    }
+
+    private static final class LineLocationEntryComparator implements Comparator<Entry<LineLocation, CoverageRecord>> {
+
+        public int compare(Entry<LineLocation, CoverageRecord> e1, Entry<LineLocation, CoverageRecord> e2) {
+            return LineLocation.COMPARATOR.compare(e1.getKey(), e2.getKey());
+        }
+    }
+
+    /**
+     * Attach a counting instrument to each node that is assigned a specified tag.
+     */
+    private class CoverageProbeListener extends DefaultProbeListener {
+
+        @Override
+        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+            if (countingTag == tag) {
+
+                final SourceSection srcSection = probe.getProbedSourceSection();
+                if (srcSection == null) {
+                    // TODO (mlvdv) report this?
+                } else if (!srcSection.getSource().isTaggedAs(Tags.NO_COVERAGE)) {
+                    // Get the source line where the
+                    final LineLocation lineLocation = srcSection.getLineLocation();
+                    CoverageRecord record = coverageMap.get(lineLocation);
+                    if (record != null) {
+                        // Another node starts on same line; count only the first (textually)
+                        if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) {
+                            // Existing record, corresponds to code earlier on line
+                            return;
+                        } else {
+                            // Existing record, corresponds to code at a later position; replace it
+                            record.instrument.dispose();
+                        }
+                    }
+
+                    final CoverageRecord coverage = new CoverageRecord(srcSection);
+                    final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName());
+                    coverage.instrument = instrument;
+                    instruments.add(instrument);
+                    probe.attach(instrument);
+                    coverageMap.put(lineLocation, coverage);
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/LineToProbesMap.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * An {@link InstrumentationTool} that builds a map of every {@link Probe} attached to some AST,
+ * indexed by {@link Source} and line number.
+ */
+public final class LineToProbesMap extends InstrumentationTool {
+
+    private static final boolean TRACE = false;
+    private static final PrintStream OUT = System.out;
+
+    private static void trace(String msg) {
+        OUT.println("LineToProbesMap: " + msg);
+    }
+
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<LineLocation, Collection<Probe>> lineToProbesMap = new HashMap<>();
+
+    private final ProbeListener probeListener;
+
+    /**
+     * Create a map of {@link Probe}s that collects information on all probes added to subsequently
+     * created ASTs (once installed).
+     */
+    public LineToProbesMap() {
+        this.probeListener = new LineToProbesListener();
+    }
+
+    @Override
+    protected boolean internalInstall() {
+        Probe.addProbeListener(probeListener);
+        return true;
+    }
+
+    @Override
+    protected void internalReset() {
+        lineToProbesMap.clear();
+    }
+
+    @Override
+    protected void internalDispose() {
+        Probe.removeProbeListener(probeListener);
+    }
+
+    /**
+     * Returns the {@link Probe}, if any, associated with a specific line of guest language code; if
+     * more than one, return the one with the first starting character location.
+     */
+    public Probe findFirstProbe(LineLocation lineLocation) {
+        Probe probe = null;
+        final Collection<Probe> probes = findProbes(lineLocation);
+        for (Probe probesOnLine : probes) {
+            if (probe == null) {
+                probe = probesOnLine;
+            } else if (probesOnLine.getProbedSourceSection().getCharIndex() < probe.getProbedSourceSection().getCharIndex()) {
+                probe = probesOnLine;
+            }
+        }
+        return probe;
+    }
+
+    /**
+     * Returns all {@link Probe}s whose associated source begins at the given {@link LineLocation},
+     * an empty list if none.
+     */
+    public Collection<Probe> findProbes(LineLocation line) {
+        final Collection<Probe> probes = lineToProbesMap.get(line);
+        if (probes == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableCollection(probes);
+    }
+
+    private class LineToProbesListener extends DefaultProbeListener {
+
+        @Override
+        public void newProbeInserted(Probe probe) {
+            final SourceSection sourceSection = probe.getProbedSourceSection();
+            if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) {
+                final LineLocation lineLocation = sourceSection.getLineLocation();
+                if (TRACE) {
+                    trace("ADD " + lineLocation.getShortDescription() + " ==> " + probe.getShortDescription());
+                }
+                Collection<Probe> probes = lineToProbesMap.get(lineLocation);
+                if (probes == null) {
+                    probes = new ArrayList<>(2);
+                    lineToProbesMap.put(lineLocation, probes);
+                } else {
+                    assert !probes.contains(probe);
+                }
+                probes.add(probe);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/com.oracle.truffle.tools/src/com/oracle/truffle/tools/NodeExecCounter.java	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.tools;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.instrument.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.nodes.Node.Child;
+
+/**
+ * An {@link InstrumentationTool} that counts interpreter <em>execution calls</em> to AST nodes,
+ * tabulated by the type of called nodes; counting can be enabled <em>all</em> nodes or restricted
+ * to nodes with a specified {@linkplain SyntaxTag tag} that is presumed to be applied external to
+ * the tool.
+ * <p>
+ * <b>Tool Life Cycle</b>
+ * <p>
+ * See {@link InstrumentationTool} for the life cycle common to all such tools.
+ * </p>
+ * <b>Execution Counts</b>
+ * <p>
+ * <ul>
+ * <li>"Execution call" on a node is is defined as invocation of a node method that is instrumented
+ * to produce the event {@link StandardInstrumentListener#enter(Probe, Node, VirtualFrame)};</li>
+ * <li>Execution calls are tabulated only at <em>instrumented</em> nodes, i.e. those for which
+ * {@linkplain Node#isInstrumentable() isInstrumentable() == true};</li>
+ * <li>Execution calls are tabulated only at nodes present in the AST when originally created;
+ * dynamically added nodes will not be instrumented.</li>
+ * </ul>
+ * </p>
+ * <b>Failure Log</b>
+ * <p>
+ * For the benefit of language implementors, the tool maintains a log describing failed attempts to
+ * probe AST nodes. Most failures occur when the type of the wrapper created by
+ * {@link Node#createWrapperNode()} is not assignable to the relevant {@link Child} field in the
+ * node's parent.
+ * </p>
+ * <p>
+ * {@linkplain #reset() Resetting} the counts has no effect on the failure log.
+ * </p>
+ * <b>Results</b>
+ * <p>
+ * A modification-safe copy of the {@linkplain #getCounts() counts} can be retrieved at any time,
+ * without effect on the state of the tool.
+ * </p>
+ * <p>
+ * A "default" {@linkplain #print(PrintStream) print()} method can summarizes the current counts at
+ * any time in a simple textual format, without effect on the state of the tool.
+ * </p>
+ *
+ * @see Instrument
+ * @see SyntaxTag
+ * @see ProbeFailure
+ */
+public final class NodeExecCounter extends InstrumentationTool {
+
+    /**
+     * Execution count for AST nodes of a particular type.
+     */
+    public interface NodeExecutionCount {
+        Class<?> nodeClass();
+
+        long executionCount();
+    }
+
+    /**
+     * Listener for events at instrumented nodes. Counts are maintained in a shared table, so the
+     * listener is stateless and can be shared by every {@link Instrument}.
+     */
+    private final StandardInstrumentListener instrumentListener = new DefaultStandardInstrumentListener() {
+        @Override
+        public void enter(Probe probe, Node node, VirtualFrame vFrame) {
+            if (isEnabled()) {
+                final Class<?> nodeClass = node.getClass();
+                /*
+                 * Everything up to here is inlined by Truffle compilation. Delegate the next part
+                 * to a method behind an inlining boundary.
+                 * 
+                 * Note that it is not permitted to pass a {@link VirtualFrame} across an inlining
+                 * boundary; they are truly virtual in inlined code.
+                 */
+                AtomicLong nodeCounter = getCounter(nodeClass);
+                nodeCounter.getAndIncrement();
+            }
+        }
+
+        /**
+         * Mark this method as a boundary that will stop Truffle inlining, which should not be
+         * allowed to inline the hash table method or any other complex library code.
+         */
+        @TruffleBoundary
+        private AtomicLong getCounter(Class<?> nodeClass) {
+            AtomicLong nodeCounter = counters.get(nodeClass);
+            if (nodeCounter == null) {
+                nodeCounter = new AtomicLong();
+                counters.put(nodeClass, nodeCounter);
+            }
+            return nodeCounter;
+        }
+    };
+
+    /** Counting data. */
+    private final Map<Class<?>, AtomicLong> counters = new HashMap<>();
+
+    /** Failure log. */
+    private final List<ProbeFailure> failures = new ArrayList<>();
+
+    /** For disposal. */
+    private final List<Instrument> instruments = new ArrayList<>();
+
+    /**
+     * If non-null, counting is restricted to nodes holding this tag.
+     */
+    private final SyntaxTag countingTag;
+
+    /**
+     * Prober used only when instrumenting every node.
+     */
+    private ASTProber astProber;
+
+    /**
+     * Listener used only when restricting counting to a specific tag.
+     */
+    private ProbeListener probeListener;
+
+    /**
+     * Create a per node-type execution counting tool for all nodes in subsequently created ASTs.
+     */
+    public NodeExecCounter() {
+        this.countingTag = null;
+    }
+
+    /**
+     * Creates a per-type execution counting for nodes tagged as specified in subsequently created
+     * ASTs.
+     */
+    public NodeExecCounter(SyntaxTag tag) {
+        this.countingTag = tag;
+    }
+
+    @Override
+    protected boolean internalInstall() {
+        if (countingTag == null) {
+            astProber = new ExecCounterASTProber();
+            Probe.registerASTProber(astProber);
+        } else {
+            probeListener = new NodeExecCounterProbeListener();
+            Probe.addProbeListener(probeListener);
+        }
+        return true;
+    }
+
+    @Override
+    protected void internalReset() {
+        counters.clear();
+        failures.clear();
+    }
+
+    @Override
+    protected void internalDispose() {
+        if (astProber != null) {
+            Probe.unregisterASTProber(astProber);
+        }
+        if (probeListener != null) {
+            Probe.removeProbeListener(probeListener);
+        }
+        for (Instrument instrument : instruments) {
+            instrument.dispose();
+        }
+    }
+
+    /**
+     * Gets a modification-safe summary of the current per-type node execution counts; does not
+     * affect the counts.
+     */
+    public NodeExecutionCount[] getCounts() {
+        final Collection<Map.Entry<Class<?>, AtomicLong>> entrySet = counters.entrySet();
+        final NodeExecutionCount[] result = new NodeExecCountImpl[entrySet.size()];
+        int i = 0;
+        for (Map.Entry<Class<?>, AtomicLong> entry : entrySet) {
+            result[i++] = new NodeExecCountImpl(entry.getKey(), entry.getValue().longValue());
+        }
+        return result;
+    }
+
+    /**
+     * Gets a log containing a report of every failed attempt to instrument a node.
+     */
+    public ProbeFailure[] getFailures() {
+        return failures.toArray(new ProbeFailure[failures.size()]);
+    }
+
+    /**
+     * A default printer for the current counts, producing lines of the form
+     * " <count> : <node type>" in descending order of count.
+     */
+    public void print(PrintStream out) {
+        print(out, false);
+    }
+
+    /**
+     * A default printer for the current counts, producing lines of the form
+     * " <count> : <node type>" in descending order of count.
+     *
+     * @param out
+     * @param verbose whether to describe nodes on which instrumentation failed
+     */
+    public void print(PrintStream out, boolean verbose) {
+
+        final long missedNodes = failures.size();
+        out.println();
+        if (countingTag == null) {
+            out.println("Execution counts by node type:");
+        } else {
+            out.println("\"" + countingTag.name() + "\"-tagged execution counts by node type:");
+        }
+        final StringBuilder disclaim = new StringBuilder("(");
+        if (missedNodes > 0) {
+            disclaim.append(Long.toString(missedNodes) + " original AST nodes not instrumented, ");
+        }
+        disclaim.append("dynamically added nodes not instrumented)");
+        out.println(disclaim.toString());
+        NodeExecutionCount[] execCounts = getCounts();
+        // Sort in descending order
+        Arrays.sort(execCounts, new Comparator<NodeExecutionCount>() {
+
+            public int compare(NodeExecutionCount o1, NodeExecutionCount o2) {
+                return Long.compare(o2.executionCount(), o1.executionCount());
+            }
+
+        });
+        for (NodeExecutionCount nodeCount : execCounts) {
+            out.format("%12d", nodeCount.executionCount());
+            out.println(" : " + nodeCount.nodeClass().getName());
+        }
+
+        if (verbose && missedNodes > 0) {
+            out.println("Instrumentation failures for execution counts:");
+
+            for (ProbeFailure failure : failures) {
+                out.println("\t" + failure.getMessage());
+            }
+        }
+    }
+
+    /**
+     * A prober that attempts to probe and instrument every node.
+     */
+    private class ExecCounterASTProber implements ASTProber, NodeVisitor {
+
+        public boolean visit(Node node) {
+
+            if (node.isInstrumentable()) {
+                try {
+                    final Instrument instrument = Instrument.create(instrumentListener, "NodeExecCounter");
+                    instruments.add(instrument);
+                    node.probe().attach(instrument);
+                } catch (ProbeException ex) {
+                    failures.add(ex.getFailure());
+                }
+            }
+            return true;
+        }
+
+        public void probeAST(Node node) {
+            node.accept(this);
+        }
+    }
+
+    /**
+     * A listener that assumes ASTs have been tagged external to this tool, and which instruments
+     * nodes holding a specified tag.
+     */
+    private class NodeExecCounterProbeListener extends DefaultProbeListener {
+
+        @Override
+        public void probeTaggedAs(Probe probe, SyntaxTag tag, Object tagValue) {
+            if (countingTag == tag) {
+                final Instrument instrument = Instrument.create(instrumentListener, NodeExecCounter.class.getSimpleName());
+                instruments.add(instrument);
+                probe.attach(instrument);
+            }
+        }
+    }
+
+    private static class NodeExecCountImpl implements NodeExecutionCount {
+
+        private final Class<?> nodeClass;
+        private final long count;
+
+        public NodeExecCountImpl(Class<?> nodeClass, long count) {
+            this.nodeClass = nodeClass;
+            this.count = count;
+        }
+
+        public Class<?> nodeClass() {
+            return nodeClass;
+        }
+
+        public long executionCount() {
+            return count;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/truffle/overview.html	Wed Jun 17 10:58:08 2015 +0200
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.  Oracle designates this
+particular file as subject to the "Classpath" exception as provided
+by Oracle in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+-->
+
+</head>
+<body>
+
+<a href="projects.html" title="Click to enlarge"><img src="projects.jpg" width="400"/></a>
+<p>
+This document is the unified Javadoc for the Graal code base.
+The project dependency graph is shown above.
+Each node in the diagram is a link to the standalone Javadoc for the denoted project.
+<p>
+<a target="_top" href="http://openjdk.java.net/projects/graal/"><b>[go to the OpenJDK Graal project site]</b></a>
+
+</body>
+</html>