changeset 16898:433ece7d941d

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 22 Aug 2014 16:03:49 +0200
parents f90dcdbbb75e (current diff) f3bc50fe5157 (diff)
children 6f245b6d2936
files graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BooleanConditionProfileTest.java graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/IntegerConditionProfileTest.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BooleanConditionProfile.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/IntegerConditionProfile.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/model/TemplateMethodParser.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeExecutionData.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java
diffstat 101 files changed, 2752 insertions(+), 1791 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Aug 22 15:56:51 2014 +0200
+++ b/.hgtags	Fri Aug 22 16:03:49 2014 +0200
@@ -406,3 +406,4 @@
 b124e22eb772806c13d942cc110de38da0108147 graal-0.1
 483d05bf77a7c2a762aca1e06c4191bc06647176 graal-0.2
 9535eccd2a115f6c6f0b15efb508b11ff74cc0d3 graal-0.3
+7d4f630172a16e983212d46c0f1ad6cdb826dfce graal-0.4
--- a/CHANGELOG.md	Fri Aug 22 15:56:51 2014 +0200
+++ b/CHANGELOG.md	Fri Aug 22 16:03:49 2014 +0200
@@ -2,28 +2,35 @@
 
 ## `tip`
 ### Graal
+* ...
+
+### Truffle
+* ...
+
+## Version 0.4
+19-Aug-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.4)
+### Graal
 * Made initialization of Graal runtime lazy in hosted mode.
-* Added supported for new 'jrelibrary' dependency type in mx/projects.
-* Java projects with compliance level higher than the JDKs specified by JAVA_HOME and EXTRA_JAVA_HOMES are ignored once mx/projects has been processed.
-* ResolvedJavaType.resolveMethod now takes a context type used to perform access checks. It now works correctly regarding default methods.
-* Removed Java based compilation queue (CompilationQueue.java).
-* Enabled use of separate class loader (via -XX:+UseGraalClassLoader) for classes loaded from graal.jar to hide them from application classes.
+* Added supported for new `jrelibrary` dependency type in `mx/projects`.
+* Java projects with compliance level higher than the JDKs specified by `JAVA_HOME` and `EXTRA_JAVA_HOMES` are ignored once `mx/projects` has been processed.
+* `ResolvedJavaType.resolveMethod` now takes a context type used to perform access checks. It now works correctly regarding default methods.
+* Removed Java based compilation queue (`CompilationQueue.java`).
+* Enabled use of separate class loader (via `-XX:+UseGraalClassLoader`) for classes loaded from `graal.jar` to hide them from application classes.
 
 ### Truffle
 * Change API for stack walking to a visitor: `TruffleRuntime#iterateFrames` replaces `TruffleRuntime#getStackTrace`
-* New flag -G:+TraceTruffleCompilationCallTree to print the tree of inlined calls before compilation.
+* New flag `-G:+TraceTruffleCompilationCallTree` to print the tree of inlined calls before compilation.
 * `truffle.jar`: strip out build-time only dependency into a seperated JAR file (`truffle-dsl-processor.jar`)
-* New flag -G:+TraceTruffleCompilationAST to print the AST before compilation.
-* New experimental TypedObject interface added.
-* Renamed flag -G:+TruffleSplittingEnabled to -G:+TruffleSplitting
-* New flag -G:+TruffleSplittingNew to enable the experimental splitting mode based on function arguments.
-* New flag -G:+TruffleSplittingTypedInstanceStamps to enable splitting for TypedObject instances.
-* New flag -G:+TruffleSplittingClassInstanceStamps to enable splitting for Java object instances except TypedObject.
-* New flag -G:TruffleSplittingStartCallCount=3 which sets the number of minimal calls until splitting is performed.
-* New flag -G:-TruffleSplittingAggressive if enabled splits every function call.
-* Added isVisited method for BranchProfile.
-* Added new ConditionProfile, BooleanConditionProfile and IntegerConditionProfile utility classes to profile if conditions.
-* ...
+* New flag `-G:+TraceTruffleCompilationAST` to print the AST before compilation.
+* New experimental `TypedObject` interface added.
+* Renamed flag `-G:+TruffleSplittingEnabled` to `-G:+TruffleSplitting`
+* New flag `-G:+TruffleSplittingNew` to enable the experimental splitting mode based on function arguments.
+* New flag `-G:+TruffleSplittingTypedInstanceStamps` to enable splitting for `TypedObject` instances.
+* New flag `-G:+TruffleSplittingClassInstanceStamps` to enable splitting for Java object instances except `TypedObject`.
+* New flag `-G:TruffleSplittingStartCallCount=3` which sets the number of minimal calls until splitting is performed.
+* New flag `-G:-TruffleSplittingAggressive` if enabled splits every function call.
+* Added `isVisited` method for `BranchProfile`.
+* Added new `ConditionProfile`, `BinaryConditionProfile` and `CountingConditionProfile` utility classes to profile if conditions.
 
 ## Version 0.3
 9-May-2014, [Repository Revision](http://hg.openjdk.java.net/graal/graal/rev/graal-0.3)
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java	Fri Aug 22 16:03:49 2014 +0200
@@ -161,6 +161,9 @@
      * because of Word type rewriting and alternative backends that can't be done.
      */
     public boolean validateFormat() {
+        if (caller() != null) {
+            caller().validateFormat();
+        }
         for (int i = 0; i < numLocals + numStack; i++) {
             if (values[i] != null) {
                 Kind kind = values[i].getKind();
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Fri Aug 22 16:03:49 2014 +0200
@@ -88,12 +88,30 @@
      */
     public abstract void mov(Register a, Constant src);
 
+    private static String getBitTypeFromKind(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Float:
+                return "b32";
+            case Long:
+            case Double:
+            case Object:
+                return "b64";
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
     public final void emitMov(Kind kind, Value dst, Value src) {
         if (isRegister(dst) && isConstant(src) && kind.getStackKind() == Kind.Object) {
             mov(asRegister(dst), asConstant(src));
         } else {
-            String argtype = getArgTypeFromKind(kind).substring(1);
-            emitString("mov_b" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
+            String argtype = getBitTypeFromKind(kind);
+            emitString("mov_" + argtype + " " + mapRegOrConstToString(dst) + ", " + mapRegOrConstToString(src) + ";");
         }
     }
 
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -400,20 +400,7 @@
             return;
         }
 
-        double probability = profilingInfo.getBranchTakenProbability(bci());
-        if (probability < 0) {
-            assert probability == -1 : "invalid probability";
-            Debug.log("missing probability in %s at bci %d", method, bci());
-            probability = 0.5;
-        }
-
-        if (!optimisticOpts.removeNeverExecutedCode()) {
-            if (probability == 0) {
-                probability = 0.0000001;
-            } else if (probability == 1) {
-                probability = 0.999999;
-            }
-        }
+        double probability = branchProbability();
 
         LabelRef trueDestination = getSuccessor(0);
         LabelRef falseDestination = getSuccessor(1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/lambda/MoreThanEightArgsTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.hsail.test.lambda;
+
+import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
+
+import org.junit.*;
+
+public class MoreThanEightArgsTest extends GraalKernelTester {
+
+    int[] makeIntArray(int size) {
+        int[] out = new int[size];
+
+        for (int i = 0; i < size; i++) {
+            out[i] = 1;
+        }
+        return out;
+    }
+
+    final int rows = 4096;
+    final int cols = 4096;
+    final int loops = 2;
+
+    @Result int[] result;
+
+    void innerTest(int[] res, int[] a, int[] b, int[] c, int[] d, int base, int stride) {
+        final int resCols = a.length;
+        final int resRows = res.length;
+        final int limit = resCols - stride;
+
+        dispatchLambdaKernel(resRows, (row) -> {
+            res[row] = 0;
+            if (a != null) {
+                for (int col = base; col < limit; col += 4) {
+                    int p0 = 0;
+                    int p1 = 0;
+                    int p2 = 0;
+                    int p3 = 0;
+                    p0 = a[col] + b[col] + c[col] + d[col] + stride;
+                    p1 = a[col + 1] + b[col + 1] + c[col + 1] + d[col + 1];
+                    p2 = a[col + 2] + b[col + 2] + c[col + 2] + d[col + 2];
+                    p3 = a[col + 3] + b[col + 3] + c[col + 3] + d[col + 3];
+                    res[row] += p0 + p1 + p2 + p3;
+                }
+            }
+        });
+    }
+
+    @Override
+    public void runTest() {
+        int[] a;
+        int[] b;
+        int[] c;
+        int[] d;
+
+        result = makeIntArray(rows);
+        a = makeIntArray(cols);
+        b = makeIntArray(cols);
+        c = makeIntArray(cols);
+        d = makeIntArray(cols);
+        for (int i = 0; i < loops; i++) {
+            innerTest(result, a, b, c, d, 0, 4);
+        }
+    }
+
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+
+    @Test
+    public void testUsingLambdaMethod() {
+        testGeneratedHsailUsingLambdaMethod();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java	Fri Aug 22 16:03:49 2014 +0200
@@ -146,7 +146,8 @@
     }
 
     /**
-     * Generates code for {@code GraalRuntime::set_option()}.
+     * Generates code for {@code GraalRuntime::set_option()} and
+     * {@code GraalRuntime::set_option_bool()}.
      */
     private static void genSetOption(PrintStream out) throws Exception {
         SortedMap<String, OptionDescriptor> options = getOptions();
@@ -157,21 +158,20 @@
         }
         lengths.add("PrintFlags".length());
 
-        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS) {");
+        out.println("bool GraalRuntime::set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS) {");
         out.println("  bool check_only = hotSpotOptionsClass.is_null();");
-        out.println("  if (value != NULL && (value[0] == '+' || value[0] == '-')) {");
-        out.println("    // boolean options");
         genMatchers(out, lengths, options, true);
-        out.println("  } else {");
-        out.println("    // non-boolean options");
+        out.println("  return false;");
+        out.println("}");
+        out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS) {");
+        out.println("  bool check_only = hotSpotOptionsClass.is_null();");
         genMatchers(out, lengths, options, false);
-        out.println("  }");
         out.println("  return false;");
         out.println("}");
     }
 
     protected static void genMatchers(PrintStream out, Set<Integer> lengths, SortedMap<String, OptionDescriptor> options, boolean isBoolean) throws Exception {
-        out.println("    switch (name_len) {");
+        out.println("  switch (name_len) {");
         for (int len : lengths) {
             boolean printedCase = false;
 
@@ -179,56 +179,56 @@
             // null terminated for <name>=<value> style options.
             if (len == "PrintFlags".length() && isBoolean) {
                 printedCase = true;
-                out.println("    case " + len + ":");
-                out.printf("      if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
-                out.println("        if (value[0] == '+') {");
-                out.println("          if (check_only) {");
-                out.println("            TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
-                out.println("            hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
-                out.println("          }");
-                out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
+                out.println("  case " + len + ":");
+                out.printf("    if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len);
+                out.println("      if (value == '+') {");
+                out.println("        if (check_only) {");
+                out.println("          TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));");
+                out.println("          hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));");
                 out.println("        }");
-                out.println("        return true;");
+                out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);");
                 out.println("      }");
+                out.println("      return true;");
+                out.println("    }");
             }
             for (Map.Entry<String, OptionDescriptor> e : options.entrySet()) {
                 OptionDescriptor desc = e.getValue();
                 if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) {
                     if (!printedCase) {
                         printedCase = true;
-                        out.println("    case " + len + ":");
+                        out.println("  case " + len + ":");
                     }
-                    out.printf("      if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
+                    out.printf("    if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len);
                     Class<?> declaringClass = desc.getDeclaringClass();
                     if (isBoolean) {
-                        out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
+                                        toInternalName(getFieldType(desc)));
+                        out.println("      if (!check_only) {");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, value, Handle(), 0L);");
+                        out.println("      }");
+                    } else if (desc.getType() == String.class) {
+                        out.println("      check_required_value(name, name_len, value, CHECK_(true));");
+                        out.printf("      Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
                                         toInternalName(getFieldType(desc)));
-                        out.println("        if (!check_only) {");
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, value[0], Handle(), 0L);");
-                        out.println("        }");
-                    } else if (desc.getType() == String.class) {
-                        out.println("        check_required_value(name, name_len, value, CHECK_(true));");
+                        out.println("      if (!check_only) {");
+                        out.println("        Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
+                        out.println("      }");
+                    } else {
+                        char spec = getPrimitiveSpecChar(desc);
+                        out.println("      jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
+                        out.println("      if (!check_only) {");
                         out.printf("        Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
                                         toInternalName(getFieldType(desc)));
-                        out.println("        if (!check_only) {");
-                        out.println("          Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));");
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);");
-                        out.println("        }");
-                    } else {
-                        char spec = getPrimitiveSpecChar(desc);
-                        out.println("        jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));");
-                        out.println("        if (!check_only) {");
-                        out.printf("          Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(),
-                                        toInternalName(getFieldType(desc)));
-                        out.println("          set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
-                        out.println("        }");
+                        out.println("        set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);");
+                        out.println("      }");
                     }
-                    out.println("        return true;");
-                    out.println("      }");
+                    out.println("      return true;");
+                    out.println("    }");
                 }
             }
         }
-        out.println("    }");
+        out.println("  }");
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Fri Aug 22 16:03:49 2014 +0200
@@ -42,7 +42,6 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.options.*;
 import com.oracle.graal.options.OptionValue.OverrideScope;
-import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
 
 /**
@@ -237,79 +236,81 @@
     private void compile(String fileList) throws Throwable {
         final String[] entries = fileList.split(File.pathSeparator);
 
-        for (int i = 0; i < entries.length; i++) {
-            final String entry = entries[i];
-
-            // For now we only compile all methods in all classes in zip/jar files.
-            if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
-                println("CompileTheWorld : Skipped classes in " + entry);
-                println();
-                continue;
-            }
+        try (AutoCloseable s = config.apply()) {
+            for (int i = 0; i < entries.length; i++) {
+                final String entry = entries[i];
 
-            println("CompileTheWorld : Compiling all classes in " + entry);
-            println();
-
-            URL url = new URL("jar", "", "file:" + entry + "!/");
-            ClassLoader loader = new URLClassLoader(new URL[]{url});
-
-            JarFile jarFile = new JarFile(entry);
-            Enumeration<JarEntry> e = jarFile.entries();
-
-            while (e.hasMoreElements()) {
-                JarEntry je = e.nextElement();
-                if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                // For now we only compile all methods in all classes in zip/jar files.
+                if (!entry.endsWith(".zip") && !entry.endsWith(".jar")) {
+                    println("CompileTheWorld : Skipped classes in " + entry);
+                    println();
                     continue;
                 }
 
-                // Are we done?
-                if (classFileCounter >= stopAt) {
-                    break;
-                }
+                println("CompileTheWorld : Compiling all classes in " + entry);
+                println();
 
-                String className = je.getName().substring(0, je.getName().length() - ".class".length());
-                classFileCounter++;
+                URL url = new URL("jar", "", "file:" + entry + "!/");
+                ClassLoader loader = new URLClassLoader(new URL[]{url});
+
+                JarFile jarFile = new JarFile(entry);
+                Enumeration<JarEntry> e = jarFile.entries();
 
-                try (AutoCloseable s = config.apply()) {
-                    // Load and initialize class
-                    Class<?> javaClass = Class.forName(className.replace('/', '.'), true, loader);
+                while (e.hasMoreElements()) {
+                    JarEntry je = e.nextElement();
+                    if (je.isDirectory() || !je.getName().endsWith(".class")) {
+                        continue;
+                    }
 
-                    // Pre-load all classes in the constant pool.
-                    try {
-                        HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
-                        ConstantPool constantPool = objectType.constantPool();
-                        for (int cpi = 1; cpi < constantPool.length(); cpi++) {
-                            constantPool.loadReferencedType(cpi, Bytecodes.LDC);
-                        }
-                    } catch (Throwable t) {
-                        // If something went wrong during pre-loading we just ignore it.
-                        println("Preloading failed for (%d) %s", classFileCounter, className);
+                    // Are we done?
+                    if (classFileCounter >= stopAt) {
+                        break;
                     }
 
-                    // Are we compiling this class?
-                    HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess();
-                    if (classFileCounter >= startAt) {
-                        println("CompileTheWorld (%d) : %s", classFileCounter, className);
+                    String className = je.getName().substring(0, je.getName().length() - ".class".length());
+                    classFileCounter++;
+
+                    try {
+                        // Load and initialize class
+                        Class<?> javaClass = Class.forName(className.replace('/', '.'), true, loader);
 
-                        // Compile each constructor/method in the class.
-                        for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
-                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor);
-                            if (canBeCompiled(javaMethod, constructor.getModifiers())) {
-                                compileMethod(javaMethod);
+                        // Pre-load all classes in the constant pool.
+                        try {
+                            HotSpotResolvedObjectType objectType = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(javaClass);
+                            ConstantPool constantPool = objectType.constantPool();
+                            for (int cpi = 1; cpi < constantPool.length(); cpi++) {
+                                constantPool.loadReferencedType(cpi, Bytecodes.LDC);
+                            }
+                        } catch (Throwable t) {
+                            // If something went wrong during pre-loading we just ignore it.
+                            println("Preloading failed for (%d) %s", classFileCounter, className);
+                        }
+
+                        // Are we compiling this class?
+                        HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess();
+                        if (classFileCounter >= startAt) {
+                            println("CompileTheWorld (%d) : %s", classFileCounter, className);
+
+                            // Compile each constructor/method in the class.
+                            for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
+                                HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaConstructor(constructor);
+                                if (canBeCompiled(javaMethod, constructor.getModifiers())) {
+                                    compileMethod(javaMethod);
+                                }
+                            }
+                            for (Method method : javaClass.getDeclaredMethods()) {
+                                HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
+                                if (canBeCompiled(javaMethod, method.getModifiers())) {
+                                    compileMethod(javaMethod);
+                                }
                             }
                         }
-                        for (Method method : javaClass.getDeclaredMethods()) {
-                            HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
-                            if (canBeCompiled(javaMethod, method.getModifiers())) {
-                                compileMethod(javaMethod);
-                            }
-                        }
+                    } catch (Throwable t) {
+                        println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
                     }
-                } catch (Throwable t) {
-                    println("CompileTheWorld (%d) : Skipping %s", classFileCounter, className);
                 }
+                jarFile.close();
             }
-            jarFile.close();
         }
 
         println();
@@ -323,16 +324,6 @@
         }
 
         /**
-         * Returns a fresh compilation suite for its compilation so that the CTW option value
-         * overriding configuration has effect.
-         */
-        @Override
-        protected Suites getSuites(HotSpotProviders providers) {
-            assert config.scope != null : "not inside a CTW option value overriding scope";
-            return providers.getSuites().createSuites();
-        }
-
-        /**
          * Returns empty profiling info to be as close to the CTW behavior of C1 and C2 as possible.
          */
         @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Fri Aug 22 16:03:49 2014 +0200
@@ -159,8 +159,8 @@
         linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
         linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION);
         linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
-        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java	Fri Aug 22 16:03:49 2014 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.phases.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -35,18 +36,18 @@
  */
 public class HotSpotSuitesProvider implements SuitesProvider {
 
-    protected final Suites defaultSuites;
+    protected final DerivedOptionValue<Suites> defaultSuites;
     protected final PhaseSuite<HighTierContext> defaultGraphBuilderSuite;
     protected final HotSpotGraalRuntime runtime;
 
     public HotSpotSuitesProvider(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
         this.defaultGraphBuilderSuite = createGraphBuilderSuite();
-        defaultSuites = createSuites();
+        this.defaultSuites = new DerivedOptionValue<>(this::createSuites);
     }
 
     public Suites getDefaultSuites() {
-        return defaultSuites;
+        return defaultSuites.getValue();
     }
 
     public PhaseSuite<HighTierContext> getDefaultGraphBuilderSuite() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Fri Aug 22 16:03:49 2014 +0200
@@ -88,7 +88,7 @@
 
     @Override
     public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes) {
-        HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true);
+        HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false);
         return createHandle(functionPointer, returnType, argumentTypes);
     }
 
@@ -179,7 +179,7 @@
         if (rtldDefault == null) {
             throw new UnsatisfiedLinkError(name);
         }
-        return lookupFunctionPointer(name, rtldDefault, true);
+        return lookupFunctionPointer(name, rtldDefault, false);
     }
 
     public boolean isDefaultLibrarySearchSupported() {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -896,6 +896,28 @@
         return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
     }
 
+    protected double branchProbability() {
+        double probability = profilingInfo.getBranchTakenProbability(bci());
+        if (probability < 0) {
+            assert probability == -1 : "invalid probability";
+            Debug.log("missing probability in %s at bci %d", method, bci());
+            probability = 0.5;
+        }
+
+        if (!removeNeverExecutedCode()) {
+            if (probability == 0) {
+                probability = 0.0000001;
+            } else if (probability == 1) {
+                probability = 0.999999;
+            }
+        }
+        return probability;
+    }
+
+    protected boolean removeNeverExecutedCode() {
+        return optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI;
+    }
+
     protected abstract void processBlock(BciBlock block);
 
     protected abstract void iterateBytecodesForBlock(BciBlock block);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java	Fri Aug 22 16:03:49 2014 +0200
@@ -22,21 +22,22 @@
  */
 package com.oracle.graal.java;
 
+import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
 
 public class DefaultSuitesProvider implements SuitesProvider {
 
-    private final Suites defaultSuites;
+    private final DerivedOptionValue<Suites> defaultSuites;
     private final PhaseSuite<HighTierContext> defaultGraphBuilderSuite;
 
     public DefaultSuitesProvider() {
         this.defaultGraphBuilderSuite = createGraphBuilderSuite();
-        this.defaultSuites = createSuites();
+        this.defaultSuites = new DerivedOptionValue<>(this::createSuites);
     }
 
     public Suites getDefaultSuites() {
-        return defaultSuites;
+        return defaultSuites.getValue();
     }
 
     public Suites createSuites() {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Aug 22 16:03:49 2014 +0200
@@ -1401,20 +1401,7 @@
                     return;
                 }
 
-                double probability = profilingInfo.getBranchTakenProbability(bci());
-                if (probability < 0) {
-                    assert probability == -1 : "invalid probability";
-                    Debug.log("missing probability in %s at bci %d", method, bci());
-                    probability = 0.5;
-                }
-
-                if (!optimisticOpts.removeNeverExecutedCode()) {
-                    if (probability == 0) {
-                        probability = 0.0000001;
-                    } else if (probability == 1) {
-                        probability = 0.999999;
-                    }
-                }
+                double probability = branchProbability();
 
                 // the mirroring and negation operations get the condition into canonical form
                 boolean mirror = cond.canonicalMirror();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Aug 22 16:03:49 2014 +0200
@@ -926,16 +926,16 @@
                     break;
 
                 case B2I:
-                    masm.movsbl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movsbl(asIntReg(dst), (AMD64Address) crb.asByteAddr(src));
                     break;
                 case S2I:
-                    masm.movswl(asIntReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movswl(asIntReg(dst), (AMD64Address) crb.asShortAddr(src));
                     break;
                 case B2L:
-                    masm.movsbq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movsbq(asLongReg(dst), (AMD64Address) crb.asByteAddr(src));
                     break;
                 case S2L:
-                    masm.movswq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
+                    masm.movswq(asLongReg(dst), (AMD64Address) crb.asShortAddr(src));
                     break;
                 case I2L:
                     masm.movslq(asLongReg(dst), (AMD64Address) crb.asIntAddr(src));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.options;
+
+import java.util.function.*;
+
+import com.oracle.graal.options.OptionValue.OverrideScope;
+
+/**
+ * A cached value that needs to be recomputed when an option changes.
+ */
+public class DerivedOptionValue<T> {
+
+    private final T initialValue;
+    private final Supplier<T> supplier;
+
+    public DerivedOptionValue(Supplier<T> supplier) {
+        this.supplier = supplier;
+        assert OptionValue.overrideScopes.get() == null : "derived option value should be initialized outside any override scope";
+        this.initialValue = createValue();
+    }
+
+    public T getValue() {
+        OverrideScope overrideScope = OptionValue.overrideScopes.get();
+        if (overrideScope != null) {
+            return overrideScope.getDerived(this);
+        } else {
+            return initialValue;
+        }
+    }
+
+    T createValue() {
+        return supplier.get();
+    }
+}
--- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java	Fri Aug 22 16:03:49 2014 +0200
@@ -128,7 +128,7 @@
         return new MultipleOverridesScope(current, map);
     }
 
-    private static final ThreadLocal<OverrideScope> overrideScopes = new ThreadLocal<>();
+    static final ThreadLocal<OverrideScope> overrideScopes = new ThreadLocal<>();
 
     /**
      * The raw option value.
@@ -252,6 +252,22 @@
      * {@link OptionValue#override(OptionValue, Object)} or {@link OptionValue#override(Map)}.
      */
     public abstract static class OverrideScope implements AutoCloseable {
+
+        private Map<DerivedOptionValue<?>, Object> derivedCache = null;
+
+        public <T> T getDerived(DerivedOptionValue<T> key) {
+            if (derivedCache == null) {
+                derivedCache = new HashMap<>();
+            }
+            @SuppressWarnings("unchecked")
+            T ret = (T) derivedCache.get(key);
+            if (ret == null) {
+                ret = key.createValue();
+                derivedCache.put(key, ret);
+            }
+            return ret;
+        }
+
         abstract void addToInherited(Map<OptionValue<?>, Object> inherited);
 
         abstract <T> T getOverride(OptionValue<T> option);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/Suites.java	Fri Aug 22 16:03:49 2014 +0200
@@ -83,26 +83,19 @@
             }
         }
 
-        if (CompilerConfiguration.getValue().equals("")) {
-            if (nonBasicCount == 1) {
-                /*
-                 * There is exactly one non-basic configuration. We use this one as default.
-                 */
-                defaultConfiguration = nonBasic;
-            } else {
-                /*
-                 * There is either no extended configuration available, or more than one. In that
-                 * case, default to "basic".
-                 */
-                defaultConfiguration = basic;
-                if (defaultConfiguration == null) {
-                    throw new GraalInternalError("unable to find basic compiler configuration");
-                }
-            }
+        if (nonBasicCount == 1) {
+            /*
+             * There is exactly one non-basic configuration. We use this one as default.
+             */
+            defaultConfiguration = nonBasic;
         } else {
-            defaultConfiguration = configurations.get(CompilerConfiguration.getValue());
+            /*
+             * There is either no extended configuration available, or more than one. In that case,
+             * default to "basic".
+             */
+            defaultConfiguration = basic;
             if (defaultConfiguration == null) {
-                throw new GraalInternalError("unknown compiler configuration: " + CompilerConfiguration.getValue());
+                throw new GraalInternalError("unable to find basic compiler configuration");
             }
         }
     }
@@ -120,7 +113,12 @@
     }
 
     public static Suites createDefaultSuites() {
-        return new Suites(defaultConfiguration);
+        String selected = CompilerConfiguration.getValue();
+        if (selected.equals("")) {
+            return new Suites(defaultConfiguration);
+        } else {
+            return createSuites(selected);
+        }
     }
 
     public static Suites createSuites(String name) {
--- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/AbstractVerifier.java	Fri Aug 22 16:03:49 2014 +0200
@@ -44,7 +44,7 @@
     @SuppressWarnings("unchecked")
     protected static <T> T resolveAnnotationValue(Class<T> expectedType, AnnotationValue value) {
         if (value == null) {
-            throw new NullPointerException("Value must not be null.");
+            return null;
         }
         Object unboxedValue = value.getValue();
         if (unboxedValue != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Fri Aug 22 16:03:49 2014 +0200
@@ -275,9 +275,17 @@
     protected ReadNode createUnsafeRead(StructuredGraph graph, UnsafeLoadNode load, GuardingNode guard) {
         boolean compressible = load.accessKind() == Kind.Object;
         Kind readKind = load.accessKind();
-        LocationNode location = createLocation(load);
+        ValueNode[] base = null;
+        ValueNode object = load.object();
+        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
+            base = new ValueNode[1];
+        }
+        LocationNode location = createLocation(load, base);
+        if (base != null && base[0] != null) {
+            object = base[0];
+        }
         Stamp loadStamp = loadStamp(load.stamp(), readKind, compressible);
-        ReadNode memoryRead = graph.add(ReadNode.create(load.object(), location, loadStamp, guard, BarrierType.NONE));
+        ReadNode memoryRead = graph.add(ReadNode.create(object, location, loadStamp, guard, BarrierType.NONE));
         ValueNode readValue = implicitLoadConvert(graph, readKind, memoryRead, compressible);
         load.replaceAtUsages(readValue);
         return memoryRead;
@@ -285,8 +293,15 @@
 
     protected void lowerUnsafeStoreNode(UnsafeStoreNode store) {
         StructuredGraph graph = store.graph();
-        LocationNode location = createLocation(store);
         ValueNode object = store.object();
+        ValueNode[] base = null;
+        if (object.isConstant() && object.asConstant().isDefaultForKind()) {
+            base = new ValueNode[1];
+        }
+        LocationNode location = createLocation(store, base);
+        if (base != null && base[0] != null) {
+            object = base[0];
+        }
         boolean compressible = store.value().getKind() == Kind.Object;
         Kind valueKind = store.accessKind();
         ValueNode value = implicitStoreConvert(graph, valueKind, store.value(), compressible);
@@ -566,11 +581,26 @@
         }
     }
 
-    protected LocationNode createLocation(UnsafeAccessNode access) {
-        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind());
+    protected LocationNode createLocation(UnsafeAccessNode access, ValueNode[] base) {
+        return createLocation(access.offset(), access.getLocationIdentity(), access.accessKind(), base);
     }
 
     protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind) {
+        return createLocation(offsetNode, locationIdentity, accessKind, null);
+    }
+
+    /**
+     * Try to unpack the operations in offsetNode into a LocationNode, taking advantage of
+     * addressing modes if possible.
+     *
+     * @param offsetNode the computed offset into the base of the memory operation
+     * @param locationIdentity
+     * @param accessKind
+     * @param base if non-null try to find a value that can be used as the base of the memory
+     *            operation and return it as base[0]
+     * @return the newly created LocationNode
+     */
+    protected LocationNode createLocation(ValueNode offsetNode, LocationIdentity locationIdentity, Kind accessKind, ValueNode[] base) {
         ValueNode offset = offsetNode;
         if (offset.isConstant()) {
             long offsetValue = offset.asConstant().asLong();
@@ -594,7 +624,27 @@
                 offset = integerAddNode.getX();
             }
         }
-
+        if (base != null && signExtend == false && offset instanceof IntegerAddNode) {
+            /*
+             * Try to decompose the operation into base plus offset so the base can go into a new
+             * node. Prefer the unshifted side of an add as the base.
+             */
+            IntegerAddNode integerAddNode = (IntegerAddNode) offset;
+            if (integerAddNode.getY() instanceof LeftShiftNode) {
+                base[0] = integerAddNode.getX();
+                offset = integerAddNode.getY();
+            } else {
+                base[0] = integerAddNode.getY();
+                offset = integerAddNode.getX();
+            }
+            if (offset instanceof IntegerAddNode) {
+                integerAddNode = (IntegerAddNode) offset;
+                if (integerAddNode.getY() instanceof ConstantNode) {
+                    displacement = integerAddNode.getY().asConstant().asLong();
+                    offset = integerAddNode.getX();
+                }
+            }
+        }
         if (offset instanceof LeftShiftNode) {
             LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
             if (leftShiftNode.getY() instanceof ConstantNode) {
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java	Fri Aug 22 16:03:49 2014 +0200
@@ -231,7 +231,7 @@
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites();
         Suites suites = suitesProvider.createSuites();
-        suites.getHighTier().findPhase(InliningPhase.class).remove();
+        removeInliningPhase(suites);
         StructuredGraph graph = new StructuredGraph(javaMethod);
         new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph);
         PhaseSuite<HighTierContext> graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite();
@@ -247,6 +247,13 @@
         return runtimeProvider.getHostBackend().getProviders();
     }
 
+    private static void removeInliningPhase(Suites suites) {
+        ListIterator<BasePhase<? super HighTierContext>> inliningPhase = suites.getHighTier().findPhase(InliningPhase.class);
+        if (inliningPhase != null) {
+            inliningPhase.remove();
+        }
+    }
+
     @SlowPath
     @Override
     public <T> T iterateFrames(FrameInstanceVisitor<T> visitor) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java	Fri Aug 22 16:03:49 2014 +0200
@@ -54,6 +54,7 @@
         registerSubstitutions(ExactMath.class, ExactMathSubstitutions.class);
         registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class);
         registerSubstitutions(OptimizedCallTarget.class, OptimizedCallTargetSubstitutions.class);
+        registerSubstitutions(FrameWithoutBoxing.class, FrameWithoutBoxingSubstitutions.class);
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Fri Aug 22 16:03:49 2014 +0200
@@ -103,11 +103,16 @@
         throw new RuntimeException("Frame field not found: " + fieldName);
     }
 
+    @NodeInfo
     public static class VirtualOnlyInstanceNode extends VirtualInstanceNode {
 
         private boolean allowMaterialization;
 
-        public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
+        public static VirtualOnlyInstanceNode create(ResolvedJavaType type, ResolvedJavaField[] fields) {
+            return new NewFrameNode_VirtualOnlyInstanceNodeGen(type, fields);
+        }
+
+        VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) {
             super(type, fields, false);
         }
 
@@ -125,7 +130,7 @@
     }
 
     public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) {
-        if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) {
+        if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode || fixed instanceof ForceMaterializeNode) {
             // We need to conservatively assume that a materialization of a virtual frame can also
             // happen at a merge point.
             return AllocatedObjectNode.create(virtualNode);
@@ -161,7 +166,7 @@
         ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals");
         ResolvedJavaField tagsField = findField(frameFields, "tags");
 
-        VirtualObjectNode virtualFrame = VirtualInstanceNode.create(frameType, frameFields, false);
+        VirtualObjectNode virtualFrame = VirtualOnlyInstanceNode.create(frameType, frameFields);
         VirtualObjectNode virtualFrameObjectArray = VirtualArrayNode.create((ResolvedJavaType) localsField.getType().getComponentType(), frameSize);
         VirtualObjectNode virtualFramePrimitiveArray = VirtualArrayNode.create((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize);
         VirtualObjectNode virtualFrameTagArray = VirtualArrayNode.create((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.frame.*;
+import com.oracle.truffle.api.frame.*;
+
+@ClassSubstitution(FrameWithoutBoxing.class)
+public class FrameWithoutBoxingSubstitutions {
+
+    @MethodSubstitution(isStatic = false)
+    public static MaterializedFrame materialize(FrameWithoutBoxing frame) {
+        return MaterializeFrameNode.materialize(frame);
+    }
+}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Fri Aug 22 16:03:49 2014 +0200
@@ -84,6 +84,32 @@
         }
     }
 
+    /**
+     * CacheEntry describing an Unsafe memory reference. The memory location and the location
+     * identity are separate so both must be considered when looking for optimizable memory
+     * accesses.
+     *
+     */
+    static class UnsafeLoadCacheEntry extends CacheEntry<ValueNode> {
+
+        private LocationIdentity locationIdentity;
+
+        public UnsafeLoadCacheEntry(ValueNode object, ValueNode location, LocationIdentity locationIdentity) {
+            super(object, location);
+            this.locationIdentity = locationIdentity;
+        }
+
+        @Override
+        public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) {
+            return new UnsafeLoadCacheEntry(newObject, identity, locationIdentity);
+        }
+
+        @Override
+        public boolean conflicts(LocationIdentity other) {
+            return locationIdentity == other;
+        }
+    }
+
     static class ReadCacheEntry extends CacheEntry<LocationNode> {
 
         public ReadCacheEntry(ValueNode object, LocationNode identity) {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Fri Aug 22 16:03:49 2014 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
 
@@ -121,7 +122,7 @@
                 UnsafeLoadNode load = (UnsafeLoadNode) node;
                 if (load.offset().isConstant() && load.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
                     ValueNode object = GraphUtil.unproxify(load.object());
-                    LoadCacheEntry identifier = new LoadCacheEntry(object, load.getLocationIdentity());
+                    UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
                     if (cachedValue != null) {
                         effects.replaceAtUsages(load, cachedValue);
@@ -136,7 +137,7 @@
                 UnsafeStoreNode write = (UnsafeStoreNode) node;
                 if (write.offset().isConstant() && write.getLocationIdentity() != LocationIdentity.ANY_LOCATION) {
                     ValueNode object = GraphUtil.unproxify(write.object());
-                    LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
+                    UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
 
                     ValueNode value = getScalarAlias(write.value());
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ContainsTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -380,7 +380,7 @@
             return true;
         }
 
-        @Specialization()
+        @Specialization
         Object f0() {
             return null;
         }
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ImportGuardsTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -46,25 +46,25 @@
     @ImportGuards(Imports0.class)
     static class ImportGuards1 extends ValueNode {
 
-        @ExpectError("No compatible guard with method name 'nonStaticGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'nonStaticGuard' found.")
         @Specialization(guards = "nonStaticGuard")
         int f1(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'protectedGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'protectedGuard' found.")
         @Specialization(guards = "protectedGuard")
         int f2(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'packageGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'packageGuard' found.")
         @Specialization(guards = "packageGuard")
         int f3(int a) {
             return a;
         }
 
-        @ExpectError("No compatible guard with method name 'privateGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No compatible guard with method name 'privateGuard' found.")
         @Specialization(guards = "privateGuard")
         int f4(int a) {
             return a;
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -142,7 +142,7 @@
         }
 
         @Specialization(guards = "baseGuard")
-        @ExpectError("No compatible guard with method name 'baseGuard' found. Please note that all signature types of the method guard must be declared in the type system.")
+        @ExpectError("No guard with name 'baseGuard' matched the required signature.%")
         int doSpecialized(String value0) {
             return 42;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/MethodGuardsWithArgumentsTest.java	Fri Aug 22 16:03:49 2014 +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("No compatible guard with method name 'guard(' found.%")
+        @Specialization(guards = "guard(")
+        int do1() {
+            return 42;
+        }
+    }
+
+    abstract static class MArgumentsError1 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("No compatible guard with method name 'guard)' found.%")
+        @Specialization(guards = "guard)")
+        int do1() {
+            return 42;
+        }
+
+    }
+
+    abstract static class MArgumentsError2 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @Specialization(guards = "guard(a)")
+        int do1() {
+            return 42;
+        }
+    }
+
+    @NodeChild("b")
+    abstract static class MArgumentsError3 extends ValueNode {
+
+        static boolean guard() {
+            return true;
+        }
+
+        @ExpectError("Guard parameter 'a' for guard 'guard' could not be mapped to a declared child node.")
+        @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/NegatedGuardsTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NegatedGuardsTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -50,7 +50,7 @@
             throw new AssertionError();
         }
 
-        @Specialization()
+        @Specialization
         int do2() {
             return 42; // the generic answer to all questions
         }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InstrumentationTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/InstrumentationTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -188,7 +188,7 @@
 
         public TestWrapper(RootNode child, ExecutionContext context) {
             this.child = insert(child);
-            this.probe = context.getProbe(child.getSourceSection());
+            this.probe = context.createProbe(child.getSourceSection());
         }
 
         public boolean isTaggedAs(SyntaxTag tag) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/BinaryConditionProfileTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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};
+
+    @Test
+    public void testInitial() {
+        BinaryConditionProfile profile = ConditionProfile.createBinaryProfile();
+        assertThat(profile.wasTrue(), is(false));
+        assertThat(profile.wasFalse(), is(false));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        BinaryConditionProfile profile = ConditionProfile.createBinaryProfile();
+        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) {
+        BinaryConditionProfile profile = ConditionProfile.createBinaryProfile();
+        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) {
+        BinaryConditionProfile profile = ConditionProfile.createBinaryProfile();
+        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/BooleanConditionProfileTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +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.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 BooleanConditionProfileTest {
-
-    @DataPoints public static boolean[] data = new boolean[]{true, false};
-
-    @Test
-    public void testInitial() {
-        BooleanConditionProfile profile = new BooleanConditionProfile();
-        assertThat(profile.wasTrue(), is(false));
-        assertThat(profile.wasFalse(), is(false));
-    }
-
-    @Theory
-    public void testProfileOne(boolean value) {
-        BooleanConditionProfile profile = new BooleanConditionProfile();
-        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) {
-        BooleanConditionProfile profile = new BooleanConditionProfile();
-        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) {
-        BooleanConditionProfile profile = new BooleanConditionProfile();
-        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/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/utilities/CountingConditionProfileTest.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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};
+
+    @Test
+    public void testInitial() {
+        CountingConditionProfile profile = ConditionProfile.createCountingProfile();
+        assertThat(profile.getTrueCount(), is(0));
+        assertThat(profile.getFalseCount(), is(0));
+    }
+
+    @Theory
+    public void testProfileOne(boolean value) {
+        CountingConditionProfile profile = ConditionProfile.createCountingProfile();
+        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) {
+        CountingConditionProfile profile = ConditionProfile.createCountingProfile();
+        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) {
+        CountingConditionProfile profile = ConditionProfile.createCountingProfile();
+        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/IntegerConditionProfileTest.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +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.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 IntegerConditionProfileTest {
-
-    @DataPoints public static boolean[] data = new boolean[]{true, false};
-
-    @Test
-    public void testInitial() {
-        IntegerConditionProfile profile = new IntegerConditionProfile();
-        assertThat(profile.getTrueCount(), is(0));
-        assertThat(profile.getFalseCount(), is(0));
-    }
-
-    @Theory
-    public void testProfileOne(boolean value) {
-        IntegerConditionProfile profile = new IntegerConditionProfile();
-        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) {
-        IntegerConditionProfile profile = new IntegerConditionProfile();
-        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) {
-        IntegerConditionProfile profile = new IntegerConditionProfile();
-        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/src/com/oracle/truffle/api/Assumption.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/Assumption.java	Fri Aug 22 16:03:49 2014 +0200
@@ -34,6 +34,9 @@
  * 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 {
 
@@ -42,14 +45,14 @@
      * 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();
@@ -61,7 +64,7 @@
 
     /**
      * 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	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CallTarget.java	Fri Aug 22 16:03:49 2014 +0200
@@ -30,7 +30,7 @@
 public interface CallTarget {
 
     /**
-     * Calls this target as a root method..
+     * Calls this target as a root method.
      *
      * @param arguments passed arguments as an object array
      * @return the return result of the call
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/ExecutionContext.java	Fri Aug 22 16:03:49 2014 +0200
@@ -45,6 +45,9 @@
     protected ExecutionContext() {
     }
 
+    /**
+     * Sets up the {@link SourceCallback} for this execution context.
+     */
     public void initialize() {
         setSourceCallback(new SourceCallback() {
 
@@ -99,23 +102,13 @@
     }
 
     /**
-     * Return the (possibly newly created) {@link Probe} uniquely associated with a particular
-     * source code location. A newly created probe carries no tags.
+     * Return a newly created, untagged, {@link Probe} associated with a particular source section,
+     * with no requirement that the association be unique.
      *
-     * @return a probe uniquely associated with an extent of guest language source code.
+     * @return a probe associated with an extent of guest language source code.
      */
-    public final Probe getProbe(SourceSection sourceSection) {
-        return probeManager.getProbe(sourceSection);
-    }
-
-    /**
-     * Has a {@link Probe} been created that is uniquely associated with a particular source code
-     * location.
-     *
-     * @return a probe uniquely associated with an extent of guest language source code.
-     */
-    public final boolean hasProbe(SourceSection sourceSection) {
-        return probeManager.hasProbe(sourceSection);
+    public final Probe createProbe(SourceSection source) {
+        return probeManager.createProbe(source);
     }
 
     /**
@@ -127,14 +120,6 @@
     }
 
     /**
-     * Returns all existing probes with first character on a specified line; empty collection if no
-     * probes found.
-     */
-    public final Collection<Probe> findProbesByLine(LineLocation lineLocation) {
-        return probeManager.findProbesByLine(lineLocation);
-    }
-
-    /**
      * Sets a trap that will make a callback at any AST location where a existing probe holds a
      * specified tag; only one trap may be set at a time.
      *
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTNodeProber.java	Fri Aug 22 16:03:49 2014 +0200
@@ -27,11 +27,10 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Implementation of a policy for <em>instrumenting</em> inserting a {@link Probe} at a Truffle AST
- * node.
+ * Methods for inserting a {@link Probe} at a Truffle AST node.
  * <p>
- * Note that this interface is guest language agnostic, but current extensions are
- * language-specific. This will be revisited.
+ * This interface is guest language agnostic, but current extensions are language-specific. This
+ * will be revisited.
  * <p>
  * <strong>Disclaimer:</strong> experimental interface under development. Really!
  */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ASTPrinter.java	Fri Aug 22 16:03:49 2014 +0200
@@ -29,7 +29,8 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Language-agnostic access to AST-based debugging support.
+ * 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.
  */
@@ -37,7 +38,7 @@
 
     /**
      * 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
@@ -47,7 +48,7 @@
 
     /**
      * 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.
@@ -56,7 +57,7 @@
 
     /**
      * 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
      */
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ExecutionEvents.java	Fri Aug 22 16:03:49 2014 +0200
@@ -28,8 +28,9 @@
 import com.oracle.truffle.api.nodes.*;
 
 /**
- * Normal events during program execution at Truffle AST nodes that are reported via a {@link Probe}
- * associated with the node, and made available to the probe's attached {@link Instrument}s.
+ * Normal events at each Truffle AST {@link Node} that occur during guest language execution, and
+ * which the {@link Probe} associated with that node, if any, reports to every {@link Instrument}
+ * attached to the {@link Probe}.
  * <p>
  * <strong>Disclaimer:</strong> experimental interface under development.
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Instrumentable.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, 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.*;
+
+public interface Instrumentable {
+
+    /**
+     * Optionally applies <em>instrumentation</em> at a Truffle AST node, depending on guest
+     * language characteristics and use-case policy. Ideally, the parent node of the guest language
+     * implements this interface.
+     * <ul>
+     * <li>if no instrumentation is to be applied, returns the AST node unmodified;</li>
+     * <li>if an AST node is to be instrumented, then creates a new Wrapper that <em>decorates</em>
+     * the AST node. Additionally, this creates a probe on the wrapper that is to be used for
+     * attaching instruments. This {@link Probe} is notified of all {@link ExecutionEvents} at the
+     * wrapped AST node.</li>
+     * </ul>
+     *
+     * @param context The {@link ExecutionContext} of the guest language used to create probes on
+     *            the wrapper.
+     * @return The probe that was created.
+     */
+    public Probe probe(ExecutionContext context);
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/Probe.java	Fri Aug 22 16:03:49 2014 +0200
@@ -45,9 +45,6 @@
  * attached instruments seldom changes. The assumption is invalidated when instruments are added or
  * removed, but some instruments may change their internal state in such a way that the assumption
  * should also be invalidated.
- * <p>
- * <strong>Disclaimer:</strong> experimental interface under development. In particular, the
- * <em>notify</em> methods must be migrated to another interface.
  *
  * @see Instrument
  * @see Wrapper
@@ -55,24 +52,34 @@
 public interface Probe extends ExecutionEvents, SyntaxTagged {
 
     /**
-     * The source location with which this probe is (presumably uniquely) associated.
+     * Get the {@link SourceSection} in some Truffle AST associated with this probe.
+     *
+     * @return The source associated with this probe.
      */
     SourceSection getSourceLocation();
 
     /**
-     * Mark this probe as being associated with an AST node in some category useful for debugging
-     * and other tools.
+     * Mark this probe as belonging to some tool-related category that can be used to guide tool
+     * behavior at an associated AST node. For example, a debugger might add the tag
+     * {@link StandardSyntaxTag#STATEMENT} as a way of configuring where execution should stop when
+     * stepping.
      */
     void tagAs(SyntaxTag tag);
 
     /**
-     * Adds an instrument to this probe.
+     * Adds an {@link Instrument} to this probe's collection. No check is made to see if the same
+     * instrument has already been added.
+     *
+     * @param newInstrument The instrument to add to this probe.
      */
     void addInstrument(Instrument newInstrument);
 
     /**
-     * Removes an instrument from this probe.
+     * Removes the given instrument from the probe's collection.
+     *
+     * @param oldInstrument The instrument to remove from this probe.
+     * @throws RuntimeException if no matching instrument has been attached.
      */
-    void removeInstrument(Instrument oldInstrument);
+    void removeInstrument(Instrument oldInstrument) throws RuntimeException;
 
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeListener.java	Fri Aug 22 16:03:49 2014 +0200
@@ -39,7 +39,7 @@
      * Notifies that a newly created (untagged) {@link Probe} has been inserted into a Truffle AST.
      * There will be no notification when an existing {@link Probe} is shared by an AST copy.
      */
-    void newProbeInserted(SourceSection location, Probe probe);
+    void newProbeInserted(SourceSection source, Probe probe);
 
     /**
      * Notifies that a (fully constructed) {@link Probe} has been tagged. A subsequent marking with
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/SyntaxTagged.java	Fri Aug 22 16:03:49 2014 +0200
@@ -36,12 +36,13 @@
 public interface SyntaxTagged {
 
     /**
-     * Is this node tagged as belonging to a particular category of language constructs?
+     * Is this node tagged as belonging to a particular human-sensible category of language
+     * constructs?
      */
     boolean isTaggedAs(SyntaxTag tag);
 
     /**
-     * In which categories has this node been tagged (<em>empty set</em> if none).
+     * In which user-sensible categories has this node been tagged (<em>empty set</em> if none).
      */
     Iterable<SyntaxTag> getSyntaxTags();
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/InstrumentationNode.java	Fri Aug 22 16:03:49 2014 +0200
@@ -34,9 +34,9 @@
 import com.oracle.truffle.api.source.*;
 
 /**
- * Abstract implementation of Truffle {@link Node} to be used for AST probes and instruments.
- * <p>
- * Coordinates propagation of Truffle AST {@link ExecutionEvents}.
+ * Abstract implementation of Truffle {@link Node}s used as AST {@link Probe}s and
+ * {@link Instrument}s. A {@link Probe} manages its attached {@link Instrument}s by appending them
+ * to a chain through which {@link ExecutionEvents} are propagated.
  */
 public abstract class InstrumentationNode extends Node implements ExecutionEvents {
 
@@ -44,18 +44,12 @@
         void newTagAdded(ProbeImpl probe, SyntaxTag tag);
     }
 
-    /**
-     * Creates a new {@link Probe}, presumed to be unique to a particular {@linkplain SourceSection}
-     * extent of guest language source code.
-     *
-     * @return a new probe
-     */
-    static ProbeImpl createProbe(SourceSection sourceSection, ProbeCallback probeCallback) {
-        return new ProbeImpl(sourceSection, probeCallback);
+    static ProbeImpl createProbe(SourceSection source, ProbeCallback probeCallback) {
+        return new ProbeImpl(source, probeCallback);
     }
 
     /**
-     * Next in chain.
+     * Next instrumentation node in chain.
      */
     @Child protected InstrumentationNode next;
 
@@ -71,7 +65,7 @@
     }
 
     /**
-     * Add a probe to the end of this probe chain.
+     * Add an instrument to the end of this instrument chain.
      */
     private void internalAddInstrument(Instrument newInstrument) {
         if (next == null) {
@@ -81,6 +75,12 @@
         }
     }
 
+    /**
+     * Remove an instrument from this instrument chain. If no matching instrument is found, a
+     * {@link RuntimeException} is thrown.
+     *
+     * @param oldInstrument The {@link Instrument} to remove.
+     */
     private void internalRemoveInstrument(Instrument oldInstrument) {
         if (next == null) {
             throw new RuntimeException("Couldn't find probe to remove: " + oldInstrument);
@@ -109,6 +109,14 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution is just about to enter an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of entry
+     */
     protected void internalEnter(Node astNode, VirtualFrame frame) {
         enter(astNode, frame);
         if (next != null) {
@@ -116,6 +124,15 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalEnter(Node, VirtualFrame)} to inform all instruments in the chain. In this
+     * case, there is no return value.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame) {
         leave(astNode, frame);
         if (next != null) {
@@ -123,6 +140,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, boolean)} to inform all instruments in the chain.
+     * In this case, a boolean value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The boolean result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, boolean result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -130,6 +157,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, byte)} to inform all instruments in the chain. In
+     * this case, a byte value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The byte result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, byte result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -137,6 +174,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, short)} to inform all instruments in the chain. In
+     * this case, a short value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The short result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, short result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -144,6 +191,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, int)} to inform all instruments in the chain. In
+     * this case, a int value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The int result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, int result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -151,6 +208,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, long)} to inform all instruments in the chain. In
+     * this case, a long value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The long result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, long result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -158,6 +225,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, char)} to inform all instruments in the chain. In
+     * this case, a char value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The char result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, char result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -165,6 +242,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, float)} to inform all instruments in the chain. In
+     * this case, a float value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The float result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, float result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -172,6 +259,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, double)} to inform all instruments in the chain. In
+     * this case, a double value was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The double result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, double result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -179,6 +276,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeave(Node, VirtualFrame, Object)} to inform all instruments in the chain. In
+     * this case, an Object was returned.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param result The Object result
+     */
     protected void internalLeave(Node astNode, VirtualFrame frame, Object result) {
         leave(astNode, frame, result);
         if (next != null) {
@@ -186,6 +293,16 @@
         }
     }
 
+    /**
+     * Informs the instrument that execution has just returned from an AST node with which this
+     * instrumentation node is associated. This will continue to call
+     * {@link #internalLeaveExceptional(Node, VirtualFrame, Exception)} to inform all instruments in
+     * the chain. In this case, a exception (sometimes containing a value) was thrown.
+     *
+     * @param astNode The {@link Node} that was entered
+     * @param frame The {@link VirtualFrame} at the time of exit
+     * @param e The exception
+     */
     protected void internalLeaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
         leaveExceptional(astNode, frame, null);
         if (next != null) {
@@ -195,41 +312,66 @@
 
     /**
      * Holder of a chain of {@linkplain InstrumentationNode instruments}: manages the
-     * {@link Assumption} that none of the instruments have changed since last checked.
+     * {@link Assumption} that no {@link Instrument}s have been added or removed and that none of
+     * the attached instruments have changed state in a way that would require deopt.
      * <p>
      * An instance is intended to be shared by every clone of the AST node with which it is
      * originally attached, so it holds no parent pointer.
      * <p>
-     * May be categorized by one or more {@linkplain SyntaxTag tags}, signifying information useful
-     * for instrumentation about its AST location(s).
+     * Each probe is associated with a {@link SourceSection}, not necessarily uniquely, although
+     * such a policy could be enforced for some uses.
+     * <p>
+     * Each {@link Probe} be categorized by one or more {@linkplain SyntaxTag tags}, signifying
+     * information useful for instrumentation about its AST location(s).
      */
     static final class ProbeImpl extends InstrumentationNode implements Probe {
 
         private final ProbeCallback probeCallback;
 
-        /**
-         * Source information about the AST node (and its clones) to which this probe is attached.
-         */
-        private final SourceSection probedSourceSection;
-
         // TODO (mlvdv) assumption model broken
         @CompilerDirectives.CompilationFinal private Assumption probeUnchanged;
 
         @CompilerDirectives.CompilationFinal private SyntaxTagTrap trap = null;
 
+        /**
+         * The collection of tags for this instrumentation node
+         */
         private final ArrayList<SyntaxTag> tags = new ArrayList<>();
 
-        private ProbeImpl(SourceSection sourceSection, ProbeCallback probeCallback) {
+        /**
+         * The region of source code associated with this probe. Note that this is distinct from
+         * {@link Node#getSourceSection()}, which is {@code null} for all instances of
+         * {@link InstrumentationNode} since they have no corresponding source of their own.
+         */
+        private final SourceSection source;
+
+        /**
+         * Constructor.
+         *
+         * @param source The {@link SourceSection} associated with this probe.
+         * @param probeCallback The {@link ProbeCallback} to inform when tags have been added to
+         *            this probe.
+         */
+        private ProbeImpl(SourceSection source, ProbeCallback probeCallback) {
             this.probeCallback = probeCallback;
-            this.probedSourceSection = sourceSection;
+            this.source = source;
             this.probeUnchanged = Truffle.getRuntime().createAssumption();
             this.next = null;
         }
 
+        /**
+         * Returns the {@link SourceSection} associated with this probe.
+         */
         public SourceSection getSourceLocation() {
-            return probedSourceSection;
+            return source;
         }
 
+        /**
+         * Tags this probe with the given {@link SyntaxTag}. If the tag already exists, the tag is
+         * not added.
+         *
+         * @param tag The tag to add to this probe.
+         */
         @SlowPath
         public void tagAs(SyntaxTag tag) {
             assert tag != null;
@@ -239,15 +381,32 @@
             }
         }
 
+        /**
+         * Checks if this probe has been tagged with the given tag.
+         *
+         * @param tag The {@link SyntaxTag} to check for.
+         * @return True if this probe has the given tag, false otherwise.
+         */
         public boolean isTaggedAs(SyntaxTag tag) {
             assert tag != null;
             return tags.contains(tag);
         }
 
+        /**
+         * Returns an iterable collection of all syntax tags on this probe.
+         *
+         * @return A collection of {@link SyntaxTag}s.
+         */
         public Iterable<SyntaxTag> getSyntaxTags() {
             return tags;
         }
 
+        /**
+         * Adds the given {@link Instrument} to this probe's chain of instruments. This method does
+         * not check to see if the same instrument has already been added.
+         *
+         * @param instrument The instrument to add to this probe.
+         */
         @SlowPath
         public void addInstrument(Instrument instrument) {
             probeUnchanged.invalidate();
@@ -255,6 +414,12 @@
             probeUnchanged = Truffle.getRuntime().createAssumption();
         }
 
+        /**
+         * Removes the given instrument from the chain of instruments. If no matching instrument is
+         * found, a {@link RuntimeException} is thrown.
+         *
+         * @param instrument The instrument to remove from this probe.
+         */
         @SlowPath
         public void removeInstrument(Instrument instrument) {
             probeUnchanged.invalidate();
@@ -262,6 +427,9 @@
             probeUnchanged = Truffle.getRuntime().createAssumption();
         }
 
+        /**
+         * Returns this probe.
+         */
         @Override
         protected Probe getProbe() {
             return this;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToProbeCollectionMap.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to
+ * a collection of {@link Probe}s whose associated {@link SourceSection} starts on that line.
+ */
+public class LineLocationToProbeCollectionMap implements ProbeListener {
+
+    /**
+     * Map: Source line ==> probes associated with source sections starting on the line.
+     */
+    private final Map<LineLocation, Collection<Probe>> lineToProbesMap = new HashMap<>();
+
+    public LineLocationToProbeCollectionMap() {
+    }
+
+    public void newProbeInserted(SourceSection source, Probe probe) {
+        if (source != null && !(source instanceof NullSourceSection))
+            this.addProbeToLine(source.getLineLocation(), probe);
+    }
+
+    public void probeTaggedAs(Probe probe, SyntaxTag tag) {
+        // This map ignores tags
+    }
+
+    /**
+     * Returns the {@link Probe}, if any, associated with source that starts on a specified line; if
+     * there are more than one, return the one with the first starting character location.
+     */
+    public Probe findLineProbe(LineLocation lineLocation) {
+        Probe probe = null;
+        final Collection<Probe> probes = getProbesAtLine(lineLocation);
+        for (Probe probeOnLine : probes) {
+            if (probe == null) {
+                probe = probeOnLine;
+            } else if (probeOnLine.getSourceLocation().getCharIndex() < probe.getSourceLocation().getCharIndex()) {
+                probe = probeOnLine;
+            }
+        }
+        return probe;
+    }
+
+    /**
+     * Records creation of a probe whose associated source starts on the given line.
+     * <p>
+     * If the line already exists in the internal {@link #lineToProbesMap}, this probe will be added
+     * to the existing collection. If no line already exists in the internal map, then a new key is
+     * added along with a new collection containing the probe.
+     * <p>
+     * This class requires that each added line/probe pair hasn't been previously added. However,
+     * attaching the same probe to a new line location is allowed.
+     *
+     * @param line The {@link LineLocation} to attach the probe to.
+     * @param probe The {@link Probe} to attach for that line location.
+     */
+    protected void addProbeToLine(LineLocation line, Probe probe) {
+
+        if (!lineToProbesMap.containsKey(line)) {
+            // Key does not exist, add new probe list
+            final ArrayList<Probe> newProbeList = new ArrayList<>(2);
+            newProbeList.add(probe);
+            lineToProbesMap.put(line, newProbeList);
+        } else {
+            // Probe list exists, add to existing
+            final Collection<Probe> existingProbeList = lineToProbesMap.get(line);
+            assert !existingProbeList.contains(probe);
+            existingProbeList.add(probe);
+        }
+    }
+
+    /**
+     * 
+     * Returns a collection of {@link Probe}s whose associated source begins at the given
+     * {@link LineLocation}. If there are no probes at that line, an empty list is returned.
+     *
+     * @param line The line to check.
+     * @return A collection of probes at the given line.
+     */
+    public Collection<Probe> getProbesAtLine(LineLocation line) {
+        Collection<Probe> probeList = lineToProbesMap.get(line);
+
+        if (probeList == null)
+            probeList = new ArrayList<>(1);
+
+        return probeList;
+    }
+
+    /**
+     * Convenience method to get probes according to a int line number. Returns a collection of
+     * {@link Probe}s at the given line number. If there are no probes at that line, a new empty
+     * list is returned.
+     *
+     * @param lineNumber The line number to check.
+     * @return A iterable collection of probes at the given line.
+     */
+    public Collection<Probe> getProbesAtLineNumber(int lineNumber) {
+        ArrayList<Probe> probes = new ArrayList<>();
+
+        for (LineLocation line : lineToProbesMap.keySet()) {
+            if (line.getLineNumber() == lineNumber)
+                probes.addAll(lineToProbesMap.get(line));
+        }
+
+        return probes;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/LineLocationToSourceSectionCollectionMap.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.instrument.impl;
+
+import java.util.*;
+
+import com.oracle.truffle.api.instrument.*;
+import com.oracle.truffle.api.source.*;
+
+/**
+ * A mapping from {@link LineLocation} (a line number in a specific piece of {@link Source} code) to
+ * a collection of {@link SourceSection}s that exist on that line. This class assumes that all nodes
+ * are instrumented as it uses the {@link ProbeListener} interface to determine the source sections
+ * that exist in the file.
+ */
+public class LineLocationToSourceSectionCollectionMap implements ProbeListener {
+
+    /**
+     * Map: Source line ==> source sections that exist on the line.
+     */
+    private final Map<LineLocation, Collection<SourceSection>> lineToSourceSectionsMap = new HashMap<>();
+
+    public LineLocationToSourceSectionCollectionMap() {
+
+    }
+
+    public void newProbeInserted(SourceSection sourceSection, Probe probe) {
+        if (sourceSection != null && !(sourceSection instanceof NullSourceSection)) {
+            this.addSourceSectionToLine(sourceSection.getLineLocation(), sourceSection);
+        }
+    }
+
+    public void probeTaggedAs(Probe probe, SyntaxTag tag) {
+        // This map ignores tags, but this subclasses can override this method to operate on tags.
+    }
+
+    /**
+     * Adds a source section to the given line.
+     * <p>
+     * If the line already exists in the internal {@link #lineToSourceSectionsMap}, this source
+     * section will be added to the existing collection. If no line already exists in the internal
+     * map, then a new key is added along with a new collection containing the source section.
+     * <p>
+     * This class does not check if a source section has already been added to a line.
+     *
+     * @param line The {@link LineLocation} to attach the source section to.
+     * @param sourceSection The {@link SourceSection} to attach for that line location.
+     */
+    protected void addSourceSectionToLine(LineLocation line, SourceSection sourceSection) {
+        if (!lineToSourceSectionsMap.containsKey(line)) {
+            // Key does not exist, add new source section list
+            final ArrayList<SourceSection> newSourceSectionList = new ArrayList<>(2);
+            newSourceSectionList.add(sourceSection);
+            lineToSourceSectionsMap.put(line, newSourceSectionList);
+        } else {
+            // Source section list exists, add to existing
+            final Collection<SourceSection> existingSourceSectionList = lineToSourceSectionsMap.get(line);
+            existingSourceSectionList.add(sourceSection);
+        }
+    }
+
+    /**
+     * Returns a collection of {@link SourceSection}s at the given {@link LineLocation}. If there
+     * are no source sections at that line, a new empty list of size 1 is returned.
+     *
+     * @param line The line to check.
+     * @return A iterable collection of source sections at the given line.
+     */
+    public Collection<SourceSection> getSourceSectionsAtLine(LineLocation line) {
+        Collection<SourceSection> sourceSectionList = lineToSourceSectionsMap.get(line);
+
+        if (sourceSectionList == null)
+            sourceSectionList = new ArrayList<>(1);
+
+        return sourceSectionList;
+    }
+
+    /**
+     * Convenience method to get source sections according to a int line number. Returns a
+     * collection of {@link SourceSection}s at the given line number. If there are no source
+     * sections at that line, a new empty list is returned.
+     *
+     * @param lineNumber The line number to check.
+     * @return A iterable collection of source sections at the given line.
+     */
+    public Collection<SourceSection> getSourceSectionsAtLineNumber(int lineNumber) {
+        ArrayList<SourceSection> sourceSections = new ArrayList<>();
+
+        for (LineLocation line : lineToSourceSectionsMap.keySet()) {
+            if (line.getLineNumber() == lineNumber)
+                sourceSections.addAll(lineToSourceSectionsMap.get(line));
+        }
+
+        return sourceSections;
+    }
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/ProbeManager.java	Fri Aug 22 16:03:49 2014 +0200
@@ -36,20 +36,13 @@
  */
 public final class ProbeManager {
 
-    // TODO (mlvdv) use weak references.
-    /**
-     * Map: SourceSection ==> probe associated with that source section in an AST.
-     */
-    private final Map<SourceSection, ProbeImpl> srcToProbe = new HashMap<>();
-
-    // TODO (mlvdv) use weak references.
-    /**
-     * Map: Source line ==> probes associated with source sections starting on the line.
-     */
-    private final Map<LineLocation, Collection<Probe>> lineToProbes = new HashMap<>();
-
     private final List<ProbeListener> probeListeners = new ArrayList<>();
 
+    private final List<ProbeImpl> allProbes = new ArrayList<>();
+
+    /**
+     * Called when a {@link #tagTrap} is activated in a Probe.
+     */
     private final ProbeCallback probeCallback;
 
     /**
@@ -74,11 +67,17 @@
         };
     }
 
+    /**
+     * Adds a {@link ProbeListener} to receive events.
+     */
     public void addProbeListener(ProbeListener listener) {
         assert listener != null;
         probeListeners.add(listener);
     }
 
+    /**
+     * Removes a {@link ProbeListener}. Ignored if listener not found.
+     */
     public void removeProbeListener(ProbeListener removeListener) {
         final List<ProbeListener> listeners = new ArrayList<>(probeListeners);
         for (ProbeListener listener : listeners) {
@@ -88,45 +87,32 @@
         }
     }
 
-    public Probe getProbe(SourceSection sourceSection) {
-        assert sourceSection != null;
-
-        ProbeImpl probe = srcToProbe.get(sourceSection);
-
-        if (probe != null) {
-            return probe;
-        }
-        probe = InstrumentationNode.createProbe(sourceSection, probeCallback);
+    /**
+     * Creates a new {@link Probe} associated with a {@link SourceSection} of code corresponding to
+     * a Truffle AST node.
+     */
+    public Probe createProbe(SourceSection source) {
+        assert source != null;
 
-        // Register new probe by unique SourceSection
-        srcToProbe.put(sourceSection, probe);
-
-        // Register new probe by source line, there may be more than one
-        // Create line location for map key
-        final LineLocation lineLocation = sourceSection.getLineLocation();
-
-        Collection<Probe> probes = lineToProbes.get(lineLocation);
-        if (probes == null) {
-            probes = new ArrayList<>(2);
-            lineToProbes.put(lineLocation, probes);
-        }
-        probes.add(probe);
+        ProbeImpl probe = InstrumentationNode.createProbe(source, probeCallback);
+        allProbes.add(probe);
 
         for (ProbeListener listener : probeListeners) {
-            listener.newProbeInserted(sourceSection, probe);
+            listener.newProbeInserted(source, probe);
         }
 
         return probe;
     }
 
-    public boolean hasProbe(SourceSection sourceSection) {
-        assert sourceSection != null;
-        return srcToProbe.get(sourceSection) != null;
-    }
-
+    /**
+     * Returns the subset of all {@link Probe}s holding a particular {@link SyntaxTag}, or the whole
+     * collection if the specified tag is {@code null}.
+     *
+     * @return A collection of probes containing the given tag.
+     */
     public Collection<Probe> findProbesTaggedAs(SyntaxTag tag) {
         final List<Probe> probes = new ArrayList<>();
-        for (Probe probe : srcToProbe.values()) {
+        for (Probe probe : allProbes) {
             if (tag == null || probe.isTaggedAs(tag)) {
                 probes.add(probe);
             }
@@ -134,15 +120,16 @@
         return probes;
     }
 
-    public Collection<Probe> findProbesByLine(LineLocation lineLocation) {
-        final Collection<Probe> probes = lineToProbes.get(lineLocation);
-        if (probes == null) {
-            return Collections.emptyList();
-        }
-        return new ArrayList<>(probes);
-    }
-
-    public void setTagTrap(SyntaxTagTrap tagTrap) {
+    /**
+     * Sets the current "tag trap", which will cause a callback to be triggered whenever execution
+     * reaches a Probe (existing or subsequently created) with the specified tag. There can only be
+     * one tag trap set at a time.
+     * <p>
+     *
+     * @param tagTrap The {@link SyntaxTagTrap} to set.
+     * @throws IllegalStateException if a trap is currently set.
+     */
+    public void setTagTrap(SyntaxTagTrap tagTrap) throws IllegalStateException {
         assert tagTrap != null;
         if (this.tagTrap != null) {
             throw new IllegalStateException("trap already set");
@@ -150,18 +137,23 @@
         this.tagTrap = tagTrap;
 
         SyntaxTag tag = tagTrap.getTag();
-        for (ProbeImpl probe : srcToProbe.values()) {
+        for (ProbeImpl probe : allProbes) {
             if (probe.isTaggedAs(tag)) {
                 probe.setTrap(tagTrap);
             }
         }
     }
 
+    /**
+     * Clears the current {@link SyntaxTagTrap}.
+     *
+     * @throws IllegalStateException if no trap is currently set.
+     */
     public void clearTagTrap() {
         if (this.tagTrap == null) {
             throw new IllegalStateException("no trap set");
         }
-        for (ProbeImpl probe : srcToProbe.values()) {
+        for (ProbeImpl probe : allProbes) {
             if (probe.isTaggedAs(tagTrap.getTag())) {
                 probe.setTrap(null);
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BinaryConditionProfile.java	Fri Aug 22 16:03:49 2014 +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.*;
+import com.oracle.truffle.api.CompilerDirectives.*;
+
+/**
+ * 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;
+            }
+        } else {
+            if (!wasFalse) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                wasFalse = true;
+            }
+        }
+        return value;
+    }
+
+    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/BooleanConditionProfile.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +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.*;
-
-/**
- * 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.
- *
- * Example usage:
- *
- * <pre>
- * private final ConditionProfile zero = new BooleanConditionProfile();
- * 
- * int value = ...;
- * if (zero.profile(value == 0)) {
- *   return 0;
- * } else {
- *   return value;
- * }
- *
- * </pre>
- *
- * @see ConditionProfile
- * @see IntegerConditionProfile
- */
-public class BooleanConditionProfile extends ConditionProfile {
-
-    @CompilationFinal private boolean wasTrue;
-    @CompilationFinal private boolean wasFalse;
-
-    @Override
-    public boolean profile(boolean value) {
-        if (value) {
-            if (!wasTrue) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                wasTrue = true;
-            }
-        } else {
-            if (!wasFalse) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                wasFalse = true;
-            }
-        }
-        return value;
-    }
-
-    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	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/BranchProfile.java	Fri Aug 22 16:03:49 2014 +0200
@@ -32,6 +32,9 @@
  * 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 {
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ConditionProfile.java	Fri Aug 22 16:03:49 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
  */
 package com.oracle.truffle.api.utilities;
 
+import com.oracle.truffle.api.*;
+
 /**
  * Abstract utility class to speculate on conditions. Condition profiles are intended to be used as
  * part of if conditions.
@@ -31,8 +33,8 @@
  * Example usage:
  *
  * <pre>
- * private final ConditionProfile zero = ...;
- *
+ * private final ConditionProfile zero = ConditionProfile.createBinaryProfile();
+ * 
  * int value = ...;
  * if (zero.profile(value == 0)) {
  *   return 0;
@@ -42,11 +44,40 @@
  *
  * </pre>
  *
- * @see BooleanConditionProfile
- * @see IntegerConditionProfile
+ * 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 {
 
     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 CountingConditionProfile 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#createBinaryProfile()
+     */
+    public static BinaryConditionProfile createBinaryProfile() {
+        return new BinaryConditionProfile();
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/CountingConditionProfile.java	Fri Aug 22 16:03:49 2014 +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.*;
+
+/**
+ * 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/IntegerConditionProfile.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +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.*;
-
-/**
- * Utility class to speculate on conditions to be never true or to be never false. Additionally to
- * {@link BooleanConditionProfile} 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.
- *
- * Example usage:
- *
- * <pre>
- * private final ConditionProfile zero = new IntegerConditionProfile();
- *
- * int value = ...;
- * if (zero.profile(value == 0)) {
- *   return 0;
- * } else {
- *   return value;
- * }
- *
- * </pre>
- *
- * @see ConditionProfile
- * @see IntegerConditionProfile
- */
-public class IntegerConditionProfile extends ConditionProfile {
-
-    @CompilationFinal private int trueCount;
-    @CompilationFinal private int falseCount;
-
-    @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.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java	Fri Aug 22 16:03:49 2014 +0200
@@ -322,12 +322,12 @@
     /**
      * <pre>
      * variant1 $condition != null
-     * 
+     *
      * $type $name = defaultValue($type);
      * if ($condition) {
      *     $name = $value;
      * }
-     * 
+     *
      * variant2 $condition != null
      * $type $name = $value;
      * </pre>
@@ -1590,12 +1590,16 @@
         }
 
         private boolean needsTypeGuard(SpecializationData source, SpecializationGroup group, GuardExpression guard) {
-            int signatureIndex = 0;
             for (Parameter parameter : guard.getResolvedGuard().getParameters()) {
                 if (!parameter.getSpecification().isSignature()) {
                     continue;
                 }
 
+                int signatureIndex = source.getNode().getChildExecutions().indexOf(parameter.getSpecification().getExecution());
+                if (signatureIndex == -1) {
+                    continue;
+                }
+
                 TypeGuard typeGuard = group.findTypeGuard(signatureIndex);
                 if (typeGuard != null) {
                     TypeData requiredType = typeGuard.getType();
@@ -1609,8 +1613,6 @@
                         return true;
                     }
                 }
-
-                signatureIndex++;
             }
             return false;
         }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Fri Aug 22 16:03:49 2014 +0200
@@ -530,7 +530,7 @@
     public static boolean isEnclosedIn(Element enclosedIn, Element element) {
         if (element == null) {
             return false;
-        } else if (enclosedIn.equals(element)) {
+        } else if (typeEquals(enclosedIn.asType(), element.asType())) {
             return true;
         } else {
             return isEnclosedIn(enclosedIn, element.getEnclosingElement());
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/GuardExpression.java	Fri Aug 22 16:03:49 2014 +0200
@@ -27,18 +27,43 @@
 public final class GuardExpression {
 
     private GuardData resolvedGuard;
+    private NodeExecutionData[] resolvedChildren;
 
     private final String guardName;
     private final boolean negated;
+    private final String[] childNames;
 
-    public GuardExpression(String expression) {
-        if (expression.startsWith("!")) {
-            guardName = expression.substring(1, expression.length());
+    public GuardExpression(String expression, boolean allowArguments) {
+        String exp = expression;
+        if (exp.startsWith("!")) {
+            exp = exp.substring(1, exp.length());
             negated = true;
         } else {
-            guardName = expression;
             negated = false;
         }
+
+        int argumentStart = exp.indexOf('(');
+        int endIndex = exp.lastIndexOf(')');
+        if (allowArguments && argumentStart != -1 && endIndex != -1) {
+            guardName = exp.substring(0, argumentStart).trim();
+            String arguments = exp.substring(argumentStart + 1, endIndex);
+            String[] children = arguments.split(",");
+            for (int i = 0; i < children.length; i++) {
+                children[i] = children[i].trim();
+            }
+            if (children.length == 1 && children[0].isEmpty()) {
+                childNames = new String[0];
+            } else {
+                childNames = children;
+            }
+        } else {
+            guardName = exp;
+            childNames = null;
+        }
+    }
+
+    public String[] getChildNames() {
+        return childNames;
     }
 
     public boolean isResolved() {
@@ -49,18 +74,32 @@
         return guardName;
     }
 
-    public void setGuard(GuardData guard) {
+    public NodeExecutionData[] getResolvedChildren() {
+        return resolvedChildren;
+    }
+
+    public void setResolvedChildren(NodeExecutionData[] resolvedChildren) {
+        this.resolvedChildren = resolvedChildren;
+    }
+
+    public void setResolvedGuard(GuardData guard) {
         this.resolvedGuard = guard;
     }
 
     @Override
     public boolean equals(Object obj) {
-        if (obj instanceof GuardExpression) {
+        if (this == obj) {
+            return true;
+        } else if (obj instanceof GuardExpression) {
             GuardExpression other = (GuardExpression) obj;
             if (isResolved() && other.isResolved()) {
-                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated;
+                return resolvedGuard.equals(other.resolvedGuard) && negated == other.negated && Arrays.equals(resolvedChildren, other.resolvedChildren);
             } else {
-                return guardName.equals(other.guardName) && negated == other.negated;
+                boolean equal = guardName.equals(other.guardName) && negated == other.negated;
+                if (childNames != null && other.childNames != null) {
+                    equal &= Arrays.equals(childNames, other.childNames);
+                }
+                return equal;
             }
         }
         return false;
@@ -68,18 +107,13 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(guardName, negated, resolvedGuard);
+        return Objects.hash(guardName, negated, resolvedGuard, resolvedChildren);
     }
 
     public final boolean implies(GuardExpression other) {
-        if (other == this) {
+        if (equals(other)) {
             return true;
         }
-        if (getGuardName().equals(other.getGuardName())) {
-            if (isNegated() == other.isNegated()) {
-                return true;
-            }
-        }
 
         if (isResolved() && other.isResolved()) {
             for (GuardExpression implies : getResolvedGuard().getImpliesExpressions()) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java	Fri Aug 22 16:03:49 2014 +0200
@@ -30,7 +30,6 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality;
-import com.oracle.truffle.dsl.processor.parser.*;
 
 public class NodeData extends Template implements Comparable<NodeData> {
 
@@ -208,6 +207,30 @@
         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.getIndex() == -1 || execution.getIndex() == index)) {
+                return execution;
+            }
+        }
+        return null;
+    }
+
     public List<NodeData> getNodeDeclaringChildren() {
         List<NodeData> nodeChildren = new ArrayList<>();
         for (NodeData child : getEnclosingNodes()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeExecutionData.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,96 @@
+/*
+ * 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.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 boolean shortCircuit;
+
+    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
+        this.child = child;
+        this.index = index;
+        this.shortCircuit = shortCircuit;
+        this.name = createName();
+    }
+
+    private String createName() {
+        return createName(child.getName(), index);
+    }
+
+    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 getIndex() {
+        return index;
+    }
+
+    public boolean isIndexed() {
+        return index > -1;
+    }
+
+    public boolean isShortCircuit() {
+        return shortCircuit;
+    }
+
+    public String getShortCircuitId() {
+        return createShortCircuitId(child, index);
+    }
+
+    public static String createShortCircuitId(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/ParameterSpec.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/ParameterSpec.java	Fri Aug 22 16:03:49 2014 +0200
@@ -28,7 +28,6 @@
 
 import com.oracle.truffle.dsl.processor.java.*;
 import com.oracle.truffle.dsl.processor.model.MethodSpec.TypeDef;
-import com.oracle.truffle.dsl.processor.parser.*;
 
 public class ParameterSpec {
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethod.java	Fri Aug 22 16:03:49 2014 +0200
@@ -163,6 +163,17 @@
         return foundParameters;
     }
 
+    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) {
         for (Parameter param : getReturnTypeAndParameters()) {
             if (param.getLocalName().equals(valueName)) {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TemplateMethodParser.java	Fri Aug 22 15:56:51 2014 +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.model;
-
-import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
-
-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.*;
-
-public abstract class TemplateMethodParser<T extends Template, E extends TemplateMethod> {
-
-    private final ProcessorContext context;
-
-    protected final T template;
-
-    private boolean emitErrors = true;
-    private boolean parseNullOnError = false;
-    private boolean useVarArgs = false;
-
-    public TemplateMethodParser(ProcessorContext context, T template) {
-        this.template = template;
-        this.context = context;
-    }
-
-    protected void setUseVarArgs(boolean useVarArgs) {
-        this.useVarArgs = useVarArgs;
-    }
-
-    public boolean isUseVarArgs() {
-        return useVarArgs;
-    }
-
-    public boolean isEmitErrors() {
-        return emitErrors;
-    }
-
-    public void setParseNullOnError(boolean nullOnError) {
-        this.parseNullOnError = nullOnError;
-    }
-
-    public boolean isParseNullOnError() {
-        return parseNullOnError;
-    }
-
-    public void setEmitErrors(boolean emitErrors) {
-        this.emitErrors = emitErrors;
-    }
-
-    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) && emitErrors) {
-                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 && parseNullOnError) {
-            return null;
-        }
-        return parsedMethods;
-    }
-
-    private E parse(int naturalOrder, ExecutableElement method, AnnotationMirror annotation) {
-        MethodSpec methodSpecification = createSpecification(method, annotation);
-        if (methodSpecification == null) {
-            return null;
-        }
-
-        methodSpecification.applyTypeDefinitions("types");
-
-        String id = method.getSimpleName().toString();
-        TypeMirror returnType = method.getReturnType();
-        List<TypeMirror> parameterTypes = new ArrayList<>();
-        for (VariableElement var : method.getParameters()) {
-            parameterTypes.add(var.asType());
-        }
-
-        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
-    }
-
-    private E parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
-        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
-        if (returnTypeMirror == null) {
-            if (emitErrors) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
-                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) {
-                E invalidMethod = create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, Collections.<Parameter> emptyList()), true);
-                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 create(new TemplateMethod(id, naturalOrder, template, methodSpecification, method, annotation, returnTypeMirror, parameters), false);
-    }
-
-    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 List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
-        List<Parameter> parsedRequired = null;
-        int offset = 0;
-        for (; offset <= parameterTypes.size(); offset++) {
-            List<TypeMirror> 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<TypeMirror> 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 List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> 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++) {
-                TypeMirror actualType = types.get(typeIndex);
-                Parameter optionalParam = matchParameter(specification, actualType, -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 List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> 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) {
-            TypeMirror 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++;
-        }
-
-        if (typeIndex < types.size()) {
-            // additional types available
-            if (spec.isIgnoreAdditionalParameters()) {
-                return parsedParams;
-            } else {
-                return null;
-            }
-        }
-
-        return parsedParams;
-    }
-
-    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 TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
-        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
-            // unpack varargs array argument
-            TypeMirror actualType = types.get(types.size() - 1);
-            if (actualType.getKind() == TypeKind.ARRAY) {
-                actualType = ((ArrayType) actualType).getComponentType();
-            }
-            return actualType;
-        } else if (typeIndex < types.size()) {
-            return types.get(typeIndex);
-        } else {
-            return null;
-        }
-    }
-
-    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
-        TypeMirror resolvedType = mirror;
-        if (hasError(resolvedType)) {
-            return null;
-        }
-
-        if (!specification.matches(resolvedType)) {
-            return null;
-        }
-
-        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
-        if (resolvedTypeData != null) {
-            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
-        } else {
-            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
-        }
-    }
-
-    public final E create(String id, int naturalOrder, ExecutableElement methodMetadata, AnnotationMirror mirror, TypeMirror returnType, List<TypeMirror> parameterTypes) {
-        return parseImpl(createSpecification(methodMetadata, mirror), naturalOrder, id, methodMetadata, mirror, returnType, parameterTypes);
-    }
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/ExecutableTypeMethodParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -35,9 +35,9 @@
 
     public ExecutableTypeMethodParser(ProcessorContext context, NodeData node) {
         super(context, node);
-        setEmitErrors(false);
         setParseNullOnError(false);
-        setUseVarArgs(true);
+        getParser().setEmitErrors(false);
+        getParser().setUseVarArgs(true);
     }
 
     @Override
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/GuardParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -35,14 +35,14 @@
 
 public class GuardParser extends NodeMethodParser<GuardData> {
 
-    private final Set<String> guardNames;
-    private final TemplateMethod compatibleSource;
+    private final GuardExpression expression;
+    private final TemplateMethod guardedMethod;
 
-    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, Set<String> guardNames) {
+    public GuardParser(ProcessorContext context, NodeData node, TemplateMethod compatibleSource, GuardExpression expression) {
         super(context, node);
-        this.guardNames = guardNames;
-        this.compatibleSource = compatibleSource;
-        setEmitErrors(false);
+        this.expression = expression;
+        this.guardedMethod = compatibleSource;
+        getParser().setEmitErrors(false);
         setParseNullOnError(false);
     }
 
@@ -55,21 +55,35 @@
     public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) {
         MethodSpec spec = createDefaultMethodSpec(method, mirror, true, null);
         spec.setIgnoreAdditionalSpecifications(true);
-        if (compatibleSource != null) {
-            spec.getRequired().clear();
-            for (Parameter parameter : compatibleSource.getRequiredParameters()) {
-                List<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType());
-                Set<String> typeIds = new HashSet<>();
-                for (TypeMirror typeMirror : typeMirrors) {
-                    typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
+        spec.getRequired().clear();
+
+        if (expression.getResolvedChildren() != null) {
+            for (NodeExecutionData execution : expression.getResolvedChildren()) {
+                List<Parameter> foundInGuardedMethod = guardedMethod.findByExecutionData(execution);
+                for (Parameter guardedParameter : foundInGuardedMethod) {
+                    spec.addRequired(createParameterSpec(guardedParameter));
                 }
-
-                spec.addRequired(new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds));
+            }
+        } else {
+            for (Parameter parameter : guardedMethod.getRequiredParameters()) {
+                spec.addRequired(createParameterSpec(parameter));
             }
         }
+
         return spec;
     }
 
+    private ParameterSpec createParameterSpec(Parameter parameter) {
+        List<TypeMirror> typeMirrors = ElementUtils.getAssignableTypes(getContext(), parameter.getType());
+        Set<String> typeIds = new HashSet<>();
+        for (TypeMirror typeMirror : typeMirrors) {
+            typeIds.add(ElementUtils.getUniqueIdentifier(typeMirror));
+        }
+        typeIds.retainAll(getTypeSystem().getTypeIdentifiers());
+
+        return new ParameterSpec(parameter.getSpecification(), typeMirrors, typeIds);
+    }
+
     @Override
     protected List<TypeMirror> nodeTypeMirrors(NodeData nodeData) {
         Set<TypeMirror> typeMirrors = new LinkedHashSet<>();
@@ -90,7 +104,7 @@
 
     @Override
     public boolean isParsable(ExecutableElement method) {
-        return guardNames == null || guardNames.contains(method.getSimpleName().toString());
+        return true;
     }
 
     @Override
@@ -102,7 +116,7 @@
         }
         List<GuardExpression> guardExpressions = new ArrayList<>();
         for (String string : impliesExpressions) {
-            guardExpressions.add(new GuardExpression(string));
+            guardExpressions.add(new GuardExpression(string, false));
         }
         return new GuardData(method, guardExpressions);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/MethodSpecParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -0,0 +1,288 @@
+/*
+ * 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.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 TypeSystemData getTypeSystem() {
+        return template.getTypeSystem();
+    }
+
+    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();
+        List<TypeMirror> parameterTypes = new ArrayList<>();
+        for (VariableElement var : method.getParameters()) {
+            parameterTypes.add(var.asType());
+        }
+
+        return parseImpl(methodSpecification, naturalOrder, id, method, annotation, returnType, parameterTypes);
+    }
+
+    public TemplateMethod parseImpl(MethodSpec methodSpecification, int naturalOrder, String id, ExecutableElement method, AnnotationMirror annotation, TypeMirror returnType,
+                    List<TypeMirror> parameterTypes) {
+        ParameterSpec returnTypeSpec = methodSpecification.getReturnType();
+        Parameter returnTypeMirror = matchParameter(returnTypeSpec, returnType, -1, -1);
+        if (returnTypeMirror == null) {
+            if (emitErrors) {
+                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 List<Parameter> parseParameters(MethodSpec spec, List<TypeMirror> parameterTypes, boolean varArgs) {
+        List<Parameter> parsedRequired = null;
+        int offset = 0;
+        for (; offset <= parameterTypes.size(); offset++) {
+            List<TypeMirror> 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<TypeMirror> 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 List<Parameter> parseParametersOptional(MethodSpec spec, List<TypeMirror> 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++) {
+                TypeMirror actualType = types.get(typeIndex);
+                Parameter optionalParam = matchParameter(specification, actualType, -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 List<Parameter> parseParametersRequired(MethodSpec spec, List<TypeMirror> 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) {
+            TypeMirror 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++;
+        }
+
+        if (typeIndex < types.size()) {
+            // additional types available
+            if (spec.isIgnoreAdditionalParameters()) {
+                return parsedParams;
+            } else {
+                return null;
+            }
+        }
+
+        return parsedParams;
+    }
+
+    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 TypeMirror nextActualType(List<TypeMirror> types, int typeIndex, boolean varArgs) {
+        if (varArgs && typeIndex >= types.size() - 1 && !types.isEmpty()) {
+            // unpack varargs array argument
+            TypeMirror actualType = types.get(types.size() - 1);
+            if (actualType.getKind() == TypeKind.ARRAY) {
+                actualType = ((ArrayType) actualType).getComponentType();
+            }
+            return actualType;
+        } else if (typeIndex < types.size()) {
+            return types.get(typeIndex);
+        } else {
+            return null;
+        }
+    }
+
+    private Parameter matchParameter(ParameterSpec specification, TypeMirror mirror, int specificationIndex, int varArgsIndex) {
+        TypeMirror resolvedType = mirror;
+        if (hasError(resolvedType)) {
+            return null;
+        }
+
+        if (!specification.matches(resolvedType)) {
+            return null;
+        }
+
+        TypeData resolvedTypeData = getTypeSystem().findTypeData(resolvedType);
+        if (resolvedTypeData != null) {
+            return new Parameter(specification, resolvedTypeData, specificationIndex, varArgsIndex);
+        } else {
+            return new Parameter(specification, resolvedType, specificationIndex, varArgsIndex);
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeExecutionData.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +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 javax.lang.model.type.*;
-
-import com.oracle.truffle.dsl.processor.model.*;
-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 boolean shortCircuit;
-
-    public NodeExecutionData(NodeChildData child, int index, boolean shortCircuit) {
-        this.child = child;
-        this.index = index;
-        this.shortCircuit = shortCircuit;
-        this.name = createName();
-    }
-
-    private String createName() {
-        if (isIndexed()) {
-            return child.getName() + index;
-        }
-        return child.getName();
-    }
-
-    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 getIndex() {
-        return index;
-    }
-
-    public boolean isIndexed() {
-        return index > -1;
-    }
-
-    public boolean isShortCircuit() {
-        return shortCircuit;
-    }
-
-    public String getShortCircuitId() {
-        return createShortCircuitId(child, index);
-    }
-
-    public static String createShortCircuitId(NodeChildData child, int varArgsIndex) {
-        String shortCircuitName = child.getName();
-        if (child.getCardinality().isMany()) {
-            shortCircuitName = shortCircuitName + "[" + varArgsIndex + "]";
-        }
-        return shortCircuitName;
-    }
-
-}
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -190,12 +190,18 @@
                     continue;
                 }
                 TypeElement typeElement = ElementUtils.fromTypeMirror(importGuardClass);
-                if (!typeElement.getModifiers().contains(Modifier.PUBLIC)) {
+
+                // hack to reload type is necessary for incremental compiling in eclipse.
+                // otherwise methods inside of import guard types are just not found.
+                typeElement = ElementUtils.fromTypeMirror(context.reloadType(typeElement.asType()));
+
+                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;
                 }
 
                 List<? extends ExecutableElement> importMethods = ElementFilter.methodsIn(processingEnv.getElementUtils().getAllMembers(typeElement));
+
                 for (ExecutableElement importMethod : importMethods) {
                     if (!importMethod.getModifiers().contains(Modifier.PUBLIC) || !importMethod.getModifiers().contains(Modifier.STATIC)) {
                         continue;
@@ -883,53 +889,70 @@
     }
 
     private void initializeGuards(List<? extends Element> elements, NodeData node) {
-        Map<String, List<GuardData>> guards = new HashMap<>();
+        Map<String, List<ExecutableElement>> potentialGuards = new HashMap<>();
         for (SpecializationData specialization : node.getSpecializations()) {
             for (GuardExpression exp : specialization.getGuards()) {
-                guards.put(exp.getGuardName(), null);
+                potentialGuards.put(exp.getGuardName(), null);
             }
         }
 
-        GuardParser parser = new GuardParser(context, node, null, guards.keySet());
-        List<GuardData> resolvedGuards = parser.parse(elements);
-        for (GuardData guard : resolvedGuards) {
-            List<GuardData> groupedGuards = guards.get(guard.getMethodName());
-            if (groupedGuards == null) {
-                groupedGuards = new ArrayList<>();
-                guards.put(guard.getMethodName(), groupedGuards);
+        TypeMirror booleanType = context.getType(boolean.class);
+        for (ExecutableElement potentialGuard : ElementFilter.methodsIn(elements)) {
+            if (potentialGuard.getModifiers().contains(Modifier.PRIVATE)) {
+                continue;
+            }
+            String methodName = potentialGuard.getSimpleName().toString();
+            if (!potentialGuards.containsKey(methodName)) {
+                continue;
             }
-            groupedGuards.add(guard);
+
+            if (!ElementUtils.typeEquals(potentialGuard.getReturnType(), booleanType)) {
+                continue;
+            }
+
+            List<ExecutableElement> potentialMethods = potentialGuards.get(methodName);
+            if (potentialMethods == null) {
+                potentialMethods = new ArrayList<>();
+                potentialGuards.put(methodName, potentialMethods);
+            }
+            potentialMethods.add(potentialGuard);
         }
 
         for (SpecializationData specialization : node.getSpecializations()) {
             for (GuardExpression exp : specialization.getGuards()) {
-                resolveGuardExpression(node, specialization, guards, exp);
+                resolveGuardExpression(node, specialization, potentialGuards, exp);
             }
         }
     }
 
-    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<GuardData>> guards, GuardExpression expression) {
-        List<GuardData> availableGuards = guards.get(expression.getGuardName());
+    private void resolveGuardExpression(NodeData node, TemplateMethod source, Map<String, List<ExecutableElement>> guards, GuardExpression expression) {
+        List<ExecutableElement> availableGuards = guards.get(expression.getGuardName());
         if (availableGuards == null) {
-            source.addError("No compatible guard with method name '%s' found. Please note that all signature types of the method guard must be declared in the type system.", expression.getGuardName());
+            source.addError("No compatible guard with method name '%s' found.", expression.getGuardName());
             return;
         }
-        List<ExecutableElement> guardMethods = new ArrayList<>();
-        for (GuardData guard : availableGuards) {
-            guardMethods.add(guard.getMethod());
+
+        String[] childNames = expression.getChildNames();
+        if (childNames != null) {
+            NodeExecutionData[] resolvedExecutions = new NodeExecutionData[childNames.length];
+            for (int i = 0; i < childNames.length; i++) {
+                String childName = childNames[i];
+                NodeExecutionData execution = node.findExecutionByExpression(childName);
+                if (execution == null) {
+                    source.addError("Guard parameter '%s' for guard '%s' could not be mapped to a declared child node.", childName, expression.getGuardName());
+                    return;
+                }
+                resolvedExecutions[i] = execution;
+            }
+            expression.setResolvedChildren(resolvedExecutions);
         }
-        GuardParser parser = new GuardParser(context, node, source, null);
-        List<GuardData> matchingGuards = parser.parse(guardMethods);
+
+        GuardParser parser = new GuardParser(context, node, source, expression);
+        List<GuardData> matchingGuards = parser.parse(availableGuards);
         if (!matchingGuards.isEmpty()) {
             GuardData guard = matchingGuards.get(0);
             // use the shared instance of the guard data
-            for (GuardData guardData : availableGuards) {
-                if (guardData.getMethod() == guard.getMethod()) {
-                    expression.setGuard(guardData);
-                    return;
-                }
-            }
-            throw new AssertionError("Should not reach here.");
+            expression.setResolvedGuard(guard);
         } else {
             MethodSpec spec = parser.createSpecification(source.getMethod(), source.getMarkerAnnotation());
             spec.applyTypeDefinitions("types");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java	Fri Aug 22 16:03:49 2014 +0200
@@ -424,16 +424,15 @@
     }
 
     public boolean isTypeGuardUsedInAnyGuardBelow(ProcessorContext context, SpecializationData source, TypeGuard typeGuard) {
+        NodeExecutionData execution = source.getNode().getChildExecutions().get(typeGuard.getSignatureIndex());
 
         for (GuardExpression guard : guards) {
-            Parameter guardParameter = guard.getResolvedGuard().getSignatureParameter(typeGuard.getSignatureIndex());
-            if (guardParameter == null) {
-                // guardParameters are optional
-                continue;
-            }
+            List<Parameter> guardParameters = guard.getResolvedGuard().findByExecutionData(execution);
             Parameter sourceParameter = source.getSignatureParameter(typeGuard.getSignatureIndex());
-            if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
-                return true;
+            for (Parameter guardParameter : guardParameters) {
+                if (sourceParameter.getTypeSystemType().needsCastTo(guardParameter.getType())) {
+                    return true;
+                }
             }
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationMethodParser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -84,7 +84,7 @@
         List<String> guardDefs = ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "guards");
         List<GuardExpression> guardExpressions = new ArrayList<>();
         for (String guardDef : guardDefs) {
-            guardExpressions.add(new GuardExpression(guardDef));
+            guardExpressions.add(new GuardExpression(guardDef, true));
         }
         specialization.setGuards(guardExpressions);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TemplateMethodParser.java	Fri Aug 22 16:03:49 2014 +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<TypeMirror> 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.sl.test/src/com/oracle/truffle/sl/test/instrument/SLCheckVariableEqualityInstrument.java	Fri Aug 22 15:56:51 2014 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle 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 com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.controlflow.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * This sample instrument provides an example of a naive way to check if two numbers in SL are
- * equivalent using their variable names. This instrument is designed to be attached to an
- * {@link SLReturnNode}, but provides no guards ensuring this.
- */
-public class SLCheckVariableEqualityInstrument extends Instrument {
-
-    private final String varName1;
-    private final String varName2;
-    private final PrintStream output;
-
-    /**
-     * Constructor
-     *
-     * @param varName1 The name of the first variable to compare
-     * @param varName2 The name of the second variable to compare
-     * @param output The {@link PrintStream} from the context used to print results. See
-     *            {@link SLContext#getOutput()} for more info.
-     */
-    public SLCheckVariableEqualityInstrument(String varName1, String varName2, PrintStream output) {
-        this.varName1 = varName1;
-        this.varName2 = varName2;
-        this.output = output;
-    }
-
-    /**
-     * In the instrumentation test, this instrument is attached to a return statement. Since returns
-     * are handled via exceptions in Simple, we need to override the leaveExceptional method. This
-     * method does very limited error checking and simply prints "true" if the passed-in variables
-     * match or "false" if they do not.
-     */
-    @Override
-    public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) {
-        FrameSlot f1 = frame.getFrameDescriptor().findFrameSlot(varName1);
-        FrameSlot f2 = frame.getFrameDescriptor().findFrameSlot(varName2);
-
-        if (f1 == null || f2 == null)
-            output.println("false");
-        else {
-            try {
-                output.println(frame.getLong(f1) == frame.getLong(f2));
-            } catch (FrameSlotTypeException e1) {
-                e1.printStackTrace();
-            }
-        }
-
-    }
-}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestNodeProber.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +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 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.instrument.*;
-import com.oracle.truffle.sl.nodes.local.*;
-import com.oracle.truffle.sl.runtime.*;
-
-/**
- * This sample AST Node Prober for simple is used to instrument the nodes that we are interested in
- * testing. This prober wraps return nodes and assignment nodes. For the purposes of this example,
- * this is appropriate, but ideally there would be only one node prober responsible for
- * instrumenting all the nodes of interest instead of a selective one like this one.
- *
- */
-public final class SLInstrumentTestNodeProber implements SLNodeProber {
-    private final SLContext slContext;
-
-    public SLInstrumentTestNodeProber(SLContext slContext) {
-        this.slContext = slContext;
-    }
-
-    /**
-     * Not implemented, only returns the astNode that was passed in.
-     */
-    public Node probeAs(Node astNode, SyntaxTag tag, Object... args) {
-        // TODO dp: Currently does nothing in the general case
-        return astNode;
-    }
-
-    /**
-     * If the passed in node is a {@link SLStatementWrapper}, then this simply tags it as a
-     * statement. If the passed in node is a {@link SLReturnNode}, then it is instrumented and
-     * tagged as a statement for testing. Only SLReturnNodes are wrapped.
-     */
-    public SLStatementNode probeAsStatement(SLStatementNode node) {
-        assert node != null;
-
-        SLStatementWrapper wrapper = null;
-        if (node instanceof SLStatementWrapper) {
-            wrapper = (SLStatementWrapper) node;
-            wrapper.tagAs(STATEMENT);
-            return wrapper;
-        } else if (node instanceof SLReturnNode) {
-            wrapper = new SLStatementWrapper(slContext, node);
-            wrapper.tagAs(STATEMENT);
-            return wrapper;
-        }
-        return node;
-    }
-
-    /**
-     * Not implemented. Returns the passed in node.
-     */
-    public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) {
-        return node;
-    }
-
-    /**
-     * If the passed in node is a {@link SLExpressionWrapper}, then this simply tags it as an
-     * assignment. If the passed in node is a {@link SLWriteLocalVariableNode}, then it is
-     * instrumented and tagged as a assignment for testing. Only SLWriteLocalVariableNode are
-     * wrapped.
-     */
-    public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) {
-        assert node != null;
-
-        SLExpressionWrapper wrapper = null;
-        if (node instanceof SLExpressionWrapper) {
-            wrapper = (SLExpressionWrapper) node;
-            wrapper.tagAs(ASSIGNMENT);
-            return wrapper;
-        } else if (node instanceof SLWriteLocalVariableNode) {
-            wrapper = new SLExpressionWrapper(slContext, node);
-            wrapper.tagAs(ASSIGNMENT);
-            return wrapper;
-        }
-        return node;
-    }
-
-}
\ No newline at end of file
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Fri Aug 22 16:03:49 2014 +0200
@@ -37,12 +37,11 @@
 import org.junit.runners.model.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.parser.*;
 import com.oracle.truffle.sl.runtime.*;
-import com.oracle.truffle.sl.test.*;
 import com.oracle.truffle.sl.test.instrument.SLInstrumentTestRunner.InstrumentTestCase;
 
 /**
@@ -58,8 +57,7 @@
     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 VISITOR_ASSIGNMENT_COUNT_SUFFIX = "_assnCount";
-    private static final String VISITOR_VARIABLE_COMPARE_SUFFIX = "_varCompare";
+    private static final String ASSIGNMENT_VALUE_SUFFIX = "_assnCount";
 
     private static final String LF = System.getProperty("line.separator");
     private static SLContext slContext;
@@ -128,7 +126,8 @@
     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'.", SLTestSuite.class.getSimpleName(), c.getName(), SLTestRunner.class.getSimpleName()));
+            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();
@@ -200,57 +199,29 @@
         PrintStream printer = new PrintStream(out);
         try {
             // We use the name of the file to determine what visitor to attach to it.
-            if (testCase.baseName.endsWith(VISITOR_ASSIGNMENT_COUNT_SUFFIX) || testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) {
-                NodeVisitor nodeVisitor = null;
+            if (testCase.baseName.endsWith(ASSIGNMENT_VALUE_SUFFIX)) {
+                // Set up the execution context for Simple and register our two listeners
                 slContext = new SLContext(new BufferedReader(new StringReader(testCase.testInput)), printer);
-                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
-                SLASTProber prober = new SLASTProber();
-
-                // Note that the visitor looks for an attachment point via line number
-                if (testCase.baseName.endsWith(VISITOR_ASSIGNMENT_COUNT_SUFFIX)) {
-                    nodeVisitor = new NodeVisitor() {
-
-                        public boolean visit(Node node) {
-                            if (node instanceof SLExpressionWrapper) {
-                                SLExpressionWrapper wrapper = (SLExpressionWrapper) node;
-                                int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber();
 
-                                if (lineNum == 4) {
-                                    wrapper.getProbe().addInstrument(new SLPrintAssigmentValueInstrument(slContext.getOutput()));
-                                }
-                            }
-                            return true;
-                        }
-                    };
-
-                    // Note that the visitor looks for an attachment point via line number
-                } else if (testCase.baseName.endsWith(VISITOR_VARIABLE_COMPARE_SUFFIX)) {
-                    nodeVisitor = new NodeVisitor() {
-
-                        public boolean visit(Node node) {
-                            if (node instanceof SLStatementWrapper) {
-                                SLStatementWrapper wrapper = (SLStatementWrapper) node;
-                                int lineNum = wrapper.getSourceSection().getLineLocation().getLineNumber();
-
-                                if (lineNum == 6) {
-                                    wrapper.getProbe().addInstrument(new SLCheckVariableEqualityInstrument("i", "count", slContext.getOutput()));
-                                }
-                            }
-                            return true;
-                        }
-                    };
-                }
-
-                prober.addNodeProber(new SLInstrumentTestNodeProber(slContext));
-                Parser.parseSL(slContext, source, prober);
+                final Source source = Source.fromText(readAllLines(testCase.path), testCase.sourceName);
+                Parser.parseSL(slContext, source);
                 List<SLFunction> functionList = slContext.getFunctionRegistry().getFunctions();
 
                 // Since only functions can be global in SL, this guarantees that we instrument
                 // everything of interest. Parsing must occur before accepting the visitors since
-                // parsing is what creates our instrumentation points.
+                // the visitor which creates our instrumentation points expects a complete AST.
+
                 for (SLFunction function : functionList) {
                     RootCallTarget rootCallTarget = function.getCallTarget();
-                    rootCallTarget.getRootNode().accept(nodeVisitor);
+                    rootCallTarget.getRootNode().accept(new SLInstrumenter(slContext));
+                }
+
+                // We iterate over all tags the SLInsturmenter tagged as assignments and attach our
+                // test instrument to those.
+                for (Probe probe : slContext.findProbesTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
+                    if (probe.isTaggedAs(StandardSyntaxTag.ASSIGNMENT)) {
+                        probe.addInstrument(new SLPrintAssigmentValueInstrument(printer));
+                    }
                 }
 
                 SLFunction main = slContext.getFunctionRegistry().lookup("main");
@@ -272,7 +243,7 @@
     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);
+        SLInstrumentTestRunner suite = new SLInstrumentTestRunner(testClass);
         if (args.length > 0) {
             suite.filter(new NameFilter(args[0]));
         }
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.output	Fri Aug 22 16:03:49 2014 +0200
@@ -1,3 +1,5 @@
+100
+0
 1
 2
 3
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_assnCount.sl	Fri Aug 22 16:03:49 2014 +0200
@@ -8,5 +8,4 @@
 
 function main() {
   count = loop(100);
-  println(count);
 }
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.output	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-true
-100
--- a/graal/com.oracle.truffle.sl.test/tests_instrumentation/Instrumentation_varCompare.sl	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-function loop(count) {  
-  i = 0;  
-  while (i < count) {  
-    i = i + 1;  
-  }  
-  return i;  
-}
-
-function main() {
-  count = loop(100);
-  println(count);
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Fri Aug 22 16:03:49 2014 +0200
@@ -152,7 +152,7 @@
         if (sourceCallback != null) {
             sourceCallback.startLoading(source);
         }
-        Parser.parseSL(context, source, null);
+        Parser.parseSL(context, source);
         if (sourceCallback != null) {
             sourceCallback.endLoading(source);
         }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLDefineFunctionBuiltin.java	Fri Aug 22 16:03:49 2014 +0200
@@ -50,6 +50,6 @@
     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, null);
+        Parser.parseSL(context, source);
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java	Fri Aug 22 16:03:49 2014 +0200
@@ -29,8 +29,6 @@
 
 public final class SLContextFactory {
 
-    private static SLASTProber astProber;
-
     private SLContextFactory() {
 
     }
@@ -39,12 +37,6 @@
         final SLContext slContext = new SLContext(new BufferedReader(new InputStreamReader(System.in)), System.out);
         slContext.initialize();
         slContext.setVisualizer(new SLDefaultVisualizer());
-        astProber = new SLASTProber();
-        slContext.setASTNodeProber(astProber);
         return slContext;
     }
-
-    public static void addNodeProber(SLNodeProber nodeProber) {
-        astProber.addNodeProber(nodeProber);
-    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLExpressionNode.java	Fri Aug 22 16:03:49 2014 +0200
@@ -24,10 +24,13 @@
 
 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.instrument.*;
 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.*;
 
 /**
@@ -87,4 +90,20 @@
     public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
         return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame));
     }
+
+    @Override
+    public Probe probe(ExecutionContext context) {
+        Node parent = getParent();
+
+        if (parent == null)
+            throw new IllegalStateException("Cannot probe a node without a parent");
+
+        if (parent instanceof SLExpressionWrapper)
+            return ((SLExpressionWrapper) parent).getProbe();
+
+        SLExpressionWrapper wrapper = new SLExpressionWrapper((SLContext) context, this);
+        this.replace(wrapper);
+        wrapper.insertChild();
+        return wrapper.getProbe();
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLStatementNode.java	Fri Aug 22 16:03:49 2014 +0200
@@ -22,9 +22,13 @@
  */
 package com.oracle.truffle.sl.nodes;
 
+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.sl.nodes.instrument.*;
+import com.oracle.truffle.sl.runtime.*;
 
 /**
  * The base class of all Truffle nodes for SL. All nodes (even expressions) can be used as
@@ -32,7 +36,7 @@
  * local variables.
  */
 @NodeInfo(language = "Simple Language", description = "The abstract base node for all statements")
-public abstract class SLStatementNode extends Node {
+public abstract class SLStatementNode extends Node implements Instrumentable {
 
     public SLStatementNode(SourceSection src) {
         super(src);
@@ -46,4 +50,20 @@
     public SLStatementNode getNonWrapperNode() {
         return this;
     }
+
+    @Override
+    public Probe probe(ExecutionContext context) {
+        Node parent = getParent();
+
+        if (parent == null)
+            throw new IllegalStateException("Cannot probe a node without a parent");
+
+        if (parent instanceof SLStatementWrapper)
+            return ((SLStatementWrapper) parent).getProbe();
+
+        SLStatementWrapper wrapper = new SLStatementWrapper((SLContext) context, this);
+        this.replace(wrapper);
+        wrapper.insertChild();
+        return wrapper.getProbe();
+    }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Fri Aug 22 16:03:49 2014 +0200
@@ -48,11 +48,11 @@
     /**
      * 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 IntegerConditionProfile} implementation
-     * (as opposed to {@link BooleanConditionProfile} implementation) transmits the probability of
+     * 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 = new IntegerConditionProfile();
+    private final ConditionProfile condition = ConditionProfile.createCountingProfile();
 
     public SLIfNode(SourceSection src, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
         super(src);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTProber.java	Fri Aug 22 15:56:51 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +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.util.*;
-
-import com.oracle.truffle.api.instrument.*;
-import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-
-/**
- * SLASTProber contains the collection of {@link SLNodeProber}s and methods to attach the probers to
- * nodes.
- */
-public final class SLASTProber implements ASTProber, SLNodeProber {
-
-    private ArrayList<SLNodeProber> nodeProbers = new ArrayList<>();
-
-    public SLASTProber() {
-    }
-
-    /**
-     * Adds a {@link SLNodeProber} to this SLASTProber. Probes must be of type {@link SLNodeProber}
-     * and must not already have been added.
-     *
-     * @param nodeProber the {@link SLNodeProber} to add.
-     */
-    public void addNodeProber(ASTNodeProber nodeProber) {
-        if (nodeProber instanceof SLNodeProber) {
-            assert !nodeProbers.contains(nodeProber);
-            nodeProbers.add((SLNodeProber) nodeProber);
-        } else {
-            throw new IllegalArgumentException("invalid prober for SL implementation");
-        }
-    }
-
-    /**
-     * Unimplemented, does nothing.
-     */
-    public Node probeAs(Node astNode, SyntaxTag tag, Object... args) {
-        return astNode;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLStatementNode} as a statement.
-     *
-     * @param node The {@link SLStatementNode} to attach the stored set of probers to.
-     */
-    @Override
-    public SLStatementNode probeAsStatement(SLStatementNode node) {
-        SLStatementNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsStatement(result);
-        }
-        return result;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLExpressionNode} as a call. This will wrap
-     * the passed in node in an {@link SLExpressionWrapper}, tag it as a call and attach an
-     * instrument to it.
-     *
-     * @param node The {@link SLExpressionNode} to attach the stored set of probers to.
-     * @param callName The name of the call ???
-     *
-     */
-    @Override
-    public SLExpressionNode probeAsCall(SLExpressionNode node, String callName) {
-        SLExpressionNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsCall(node, callName);
-        }
-        return result;
-    }
-
-    /**
-     * Attaches the current probers to the given {@link SLExpressionNode} as an assignment. This
-     * will wrap the passed in node in an {@link SLExpressionWrapper}, tag it as an assignment and
-     * attach an instrument to it.
-     *
-     * @param node The {@link SLExpressionNode} to attached the stored set of probers to.
-     * @param localName The name of the assignment ???
-     *
-     */
-    @Override
-    public SLExpressionNode probeAsLocalAssignment(SLExpressionNode node, String localName) {
-        SLExpressionNode result = node;
-        for (SLNodeProber nodeProber : nodeProbers) {
-            result = nodeProber.probeAsLocalAssignment(result, localName);
-        }
-        return result;
-    }
-
-    public ASTNodeProber getCombinedNodeProber() {
-        return nodeProbers.isEmpty() ? null : this;
-    }
-
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLExpressionWrapper.java	Fri Aug 22 16:03:49 2014 +0200
@@ -46,11 +46,19 @@
 
     private final Probe probe;
 
+    /**
+     * Constructor.
+     *
+     * @param context The current Simple execution context
+     * @param child The {@link SLExpressionNode} that this wrapper is wrapping
+     */
     public SLExpressionWrapper(SLContext context, SLExpressionNode child) {
         super(child.getSourceSection());
         assert !(child instanceof SLExpressionWrapper);
-        this.child = insert(child);
-        this.probe = context.getProbe(child.getSourceSection());
+        this.probe = context.createProbe(child.getSourceSection());
+        this.child = child;
+        // The child should only be inserted after a replace, so we defer inserting the child to the
+        // creator of the wrapper.
     }
 
     @Override
@@ -145,4 +153,11 @@
     public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
         return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame));
     }
+
+    /**
+     * Sets the parent pointer of this wrapper's child.
+     */
+    public void insertChild() {
+        insert(this.child);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLInstrumenter.java	Fri Aug 22 16:03:49 2014 +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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle 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.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * This is a general purpose visitor which traverses a completely parsed Simple AST and instruments
+ * all the nodes within it. This visitor is designed to visit the tree immediately after it has been
+ * parsed.
+ *
+ */
+public class SLInstrumenter implements NodeVisitor {
+
+    private final SLContext context;
+
+    public SLInstrumenter(SLContext context) {
+        this.context = context;
+    }
+
+    /**
+     * 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) {
+        // We have to distinguish between SLExpressionNode and SLStatementNode since some of the
+        // generated factories have methods that require SLExpressionNodes as parameters. Since
+        // SLExpressionNodes are a subclass of SLStatementNode, we check if something is an
+        // SLExpressionNode first.
+        if (node instanceof SLExpressionNode && node.getParent() != null) {
+            SLExpressionNode expressionNode = (SLExpressionNode) node;
+            if (expressionNode.getSourceSection() != null) {
+                Probe probe = expressionNode.probe(context);
+                // probe.tagAs(STATEMENT);
+
+                if (node instanceof SLWriteLocalVariableNode)
+                    probe.tagAs(ASSIGNMENT);
+            }
+        } else if (node instanceof SLStatementNode && node.getParent() != null) {
+
+            SLStatementNode statementNode = (SLStatementNode) node;
+            if (statementNode.getSourceSection() != null) {
+                Probe probe = statementNode.probe(context);
+                probe.tagAs(STATEMENT);
+
+                if (node instanceof SLWhileNode)
+                    probe.tagAs(START_LOOP);
+            }
+        }
+
+        return true;
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLStatementWrapper.java	Fri Aug 22 16:03:49 2014 +0200
@@ -48,8 +48,10 @@
     public SLStatementWrapper(SLContext context, SLStatementNode child) {
         super(child.getSourceSection());
         assert !(child instanceof SLStatementWrapper);
-        this.child = insert(child);
-        this.probe = context.getProbe(child.getSourceSection());
+        this.probe = context.createProbe(child.getSourceSection());
+        this.child = child;
+        // The child should only be inserted after a replace, so we defer inserting the child to the
+        // creator of the wrapper.
     }
 
     @Override
@@ -94,6 +96,12 @@
             probe.leaveExceptional(child, frame, e);
             throw (e);
         }
+    }
 
+    /**
+     * Sets the parent pointer of this wrapper's child.
+     */
+    public void insertChild() {
+        insert(this.child);
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Fri Aug 22 16:03:49 2014 +0200
@@ -33,7 +33,6 @@
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.runtime.*;
 
 // Checkstyle: stop
@@ -52,9 +51,9 @@
     public final Errors errors;
     private final SLNodeFactory factory;
     -->declarations
-    public Parser(SLContext context, Source source, SLNodeProber astProber) {
+    public Parser(SLContext context, Source source) {
         this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source, astProber);
+        this.factory = new SLNodeFactory(context, source);
         errors = new Errors();
     }
 
@@ -135,8 +134,8 @@
 -->initialization
     };
 
-    public static void parseSL(SLContext context, Source source, SLNodeProber astProber) {
-        Parser parser = new Parser(context, source, astProber);
+    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");
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Fri Aug 22 16:03:49 2014 +0200
@@ -30,7 +30,6 @@
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.runtime.*;
 
 // Checkstyle: stop
@@ -53,10 +52,10 @@
     public final Scanner scanner;
     public final Errors errors;
     private final SLNodeFactory factory;
-    
-    public Parser(SLContext context, Source source, SLNodeProber astProber) {
+
+    public Parser(SLContext context, Source source) {
         this.scanner = new Scanner(source.getInputStream());
-        this.factory = new SLNodeFactory(context, source, astProber);
+        this.factory = new SLNodeFactory(context, source);
         errors = new Errors();
     }
 
@@ -134,43 +133,43 @@
 	void Function() {
 		Expect(4);
 		Expect(1);
-		Token identifierToken = t; 
+		Token identifierToken = t;
 		Expect(5);
-		int bodyStartPos = t.charPos; 
-		factory.startFunction(identifierToken, bodyStartPos); 
+		int bodyStartPos = t.charPos;
+		factory.startFunction(identifierToken, bodyStartPos);
 		if (la.kind == 1) {
 			Get();
-			factory.addFormalParameter(t); 
+			factory.addFormalParameter(t);
 			while (la.kind == 6) {
 				Get();
 				Expect(1);
-				factory.addFormalParameter(t); 
+				factory.addFormalParameter(t);
 			}
 		}
 		Expect(7);
 		SLStatementNode body = Block(false);
-		factory.finishFunction(body); 
+		factory.finishFunction(body);
 	}
 
 	SLStatementNode  Block(boolean inLoop) {
 		SLStatementNode  result;
 		factory.startBlock();
-		List<SLStatementNode> body = new ArrayList<>(); 
+		List<SLStatementNode> body = new ArrayList<>();
 		Expect(8);
-		int start = t.charPos; 
+		int start = t.charPos;
 		while (StartOf(1)) {
 			SLStatementNode s = Statement(inLoop);
-			body.add(s); 
+			body.add(s);
 		}
 		Expect(9);
-		int length = (t.charPos + t.val.length()) - start; 
-		result = factory.finishBlock(body, start, length); 
+		int length = (t.charPos + t.val.length()) - start;
+		result = factory.finishBlock(body, start, length);
 		return result;
 	}
 
 	SLStatementNode  Statement(boolean inLoop) {
 		SLStatementNode  result;
-		result = null; 
+		result = null;
 		switch (la.kind) {
 		case 13: {
 			result = WhileStatement();
@@ -178,13 +177,13 @@
 		}
 		case 10: {
 			Get();
-			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } 
+			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"); } 
+			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); }
 			Expect(11);
 			break;
 		}
@@ -209,29 +208,29 @@
 	SLStatementNode  WhileStatement() {
 		SLStatementNode  result;
 		Expect(13);
-		Token whileToken = t; 
+		Token whileToken = t;
 		Expect(5);
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode body = Block(true);
-		result = factory.createWhile(whileToken, condition, body); 
+		result = factory.createWhile(whileToken, condition, body);
 		return result;
 	}
 
 	SLStatementNode  IfStatement(boolean inLoop) {
 		SLStatementNode  result;
 		Expect(14);
-		Token ifToken = t; 
+		Token ifToken = t;
 		Expect(5);
 		SLExpressionNode condition = Expression();
 		Expect(7);
 		SLStatementNode thenPart = Block(inLoop);
-		SLStatementNode elsePart = null; 
+		SLStatementNode elsePart = null;
 		if (la.kind == 15) {
 			Get();
 			elsePart = Block(inLoop);
 		}
-		result = factory.createIf(ifToken, condition, thenPart, elsePart); 
+		result = factory.createIf(ifToken, condition, thenPart, elsePart);
 		return result;
 	}
 
@@ -239,11 +238,11 @@
 		SLStatementNode  result;
 		Expect(16);
 		Token returnToken = t;
-		SLExpressionNode value = null; 
+		SLExpressionNode value = null;
 		if (StartOf(2)) {
 			value = Expression();
 		}
-		result = factory.createReturn(returnToken, value); 
+		result = factory.createReturn(returnToken, value);
 		Expect(11);
 		return result;
 	}
@@ -253,9 +252,9 @@
 		result = LogicTerm();
 		while (la.kind == 17) {
 			Get();
-			Token op = t; 
+			Token op = t;
 			SLExpressionNode right = LogicTerm();
-			result = factory.createBinary(op, result, right); 
+			result = factory.createBinary(op, result, right);
 		}
 		return result;
 	}
@@ -265,9 +264,9 @@
 		result = LogicFactor();
 		while (la.kind == 18) {
 			Get();
-			Token op = t; 
+			Token op = t;
 			SLExpressionNode right = LogicFactor();
-			result = factory.createBinary(op, result, right); 
+			result = factory.createBinary(op, result, right);
 		}
 		return result;
 	}
@@ -302,9 +301,9 @@
 				break;
 			}
 			}
-			Token op = t; 
+			Token op = t;
 			SLExpressionNode right = Arithmetic();
-			result = factory.createBinary(op, result, right); 
+			result = factory.createBinary(op, result, right);
 		}
 		return result;
 	}
@@ -318,9 +317,9 @@
 			} else {
 				Get();
 			}
-			Token op = t; 
+			Token op = t;
 			SLExpressionNode right = Term();
-			result = factory.createBinary(op, result, right); 
+			result = factory.createBinary(op, result, right);
 		}
 		return result;
 	}
@@ -334,56 +333,56 @@
 			} else {
 				Get();
 			}
-			Token op = t; 
+			Token op = t;
 			SLExpressionNode right = Factor();
-			result = factory.createBinary(op, result, right); 
+			result = factory.createBinary(op, result, right);
 		}
 		return result;
 	}
 
 	SLExpressionNode  Factor() {
 		SLExpressionNode  result;
-		result = null; 
+		result = null;
 		if (la.kind == 1) {
 			Get();
-			Token nameToken = t; 
+			Token nameToken = t;
 			if (la.kind == 5) {
 				Get();
 				List<SLExpressionNode> parameters = new ArrayList<>();
-				SLExpressionNode parameter; 
+				SLExpressionNode parameter;
 				if (StartOf(2)) {
 					parameter = Expression();
-					parameters.add(parameter); 
+					parameters.add(parameter);
 					while (la.kind == 6) {
 						Get();
 						parameter = Expression();
-						parameters.add(parameter); 
+						parameters.add(parameter);
 					}
 				}
 				Expect(7);
-				Token finalToken = t; 
-				result = factory.createCall(nameToken, parameters, finalToken); 
+				Token finalToken = t;
+				result = factory.createCall(nameToken, parameters, finalToken);
 			} else if (la.kind == 29) {
 				Get();
 				SLExpressionNode value = Expression();
-				result = factory.createAssignment(nameToken, value); 
+				result = factory.createAssignment(nameToken, value);
 			} else if (StartOf(4)) {
-				result = factory.createRead(nameToken); 
+				result = factory.createRead(nameToken);
 			} else SynErr(32);
 		} else if (la.kind == 2) {
 			Get();
-			result = factory.createStringLiteral(t); 
+			result = factory.createStringLiteral(t);
 		} else if (la.kind == 3) {
 			Get();
-			result = factory.createNumericLiteral(t); 
+			result = factory.createNumericLiteral(t);
 		} else if (la.kind == 5) {
 			Get();
-			int start = t.charPos; 
+			int start = t.charPos;
 			result = Expression();
-			SLExpressionNode expr = result; 
+			SLExpressionNode expr = result;
 			Expect(7);
-			int length = (t.charPos + t.val.length()) - start; 
-			result = factory.createParenExpression(expr, start, length); 
+			int length = (t.charPos + t.val.length()) - start;
+			result = factory.createParenExpression(expr, start, length);
 		} else SynErr(33);
 		return result;
 	}
@@ -408,8 +407,8 @@
 
     };
 
-    public static void parseSL(SLContext context, Source source, SLNodeProber astProber) {
-        Parser parser = new Parser(context, source, astProber);
+    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");
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Fri Aug 22 16:03:49 2014 +0200
@@ -32,7 +32,6 @@
 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.runtime.*;
 
@@ -75,12 +74,9 @@
     /* State while parsing a block. */
     private LexicalScope lexicalScope;
 
-    private final SLNodeProber prober;
-
-    public SLNodeFactory(SLContext context, Source source, SLNodeProber prober) {
+    public SLNodeFactory(SLContext context, Source source) {
         this.context = context;
         this.source = source;
-        this.prober = prober;
     }
 
     public void startFunction(Token nameToken, int bodyStartPos) {
@@ -156,114 +152,69 @@
     }
 
     /**
-     * Returns a {@link SLBreakNode} for the given token. This node will be instrumented, tagged as
-     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * Returns an {@link SLBreakNode} for the given token.
      *
-     * @param breakToken The token containing the break node's info
-     * @return either:
-     *         <ul>
-     *         <li>An un-instrumented SLBreakNode if there is no prober</li>
-     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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));
-        if (prober != null) {
-            return prober.probeAsStatement(breakNode);
-        }
         return breakNode;
     }
 
     /**
-     * Returns a {@link SLContinueNode} for the given token. This node will be instrumented, tagged
-     * as a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * Returns an {@link SLContinueNode} for the given token.
      *
-     * @param continueToken The token containing the continue node's info
-     * @return either:
-     *         <ul>
-     *         <li>An un-instrumented SLContinueNode if there is no prober</li>
-     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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));
-        if (prober != null) {
-            return prober.probeAsStatement(continueNode);
-        }
         return continueNode;
     }
 
     /**
-     * Returns a {@link SLWhileNode} for the given token. This node will be instrumented, tagged as
-     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * 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 either:
-     *         <ul>
-     *         <li>An un-instrumented SLWhileNode if there is no prober</li>
-     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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);
-        if (prober != null) {
-            return prober.probeAsStatement(whileNode);
-        }
         return whileNode;
     }
 
     /**
-     * Returns a {@link SLIfNode} for the given token. This node will be instrumented, tagged as a
-     * statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * 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 either:
-     *         <ul>
-     *         <li>An un-instrumented SLIfNode if there is no prober</li>
-     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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);
-        if (prober != null) {
-            return prober.probeAsStatement(ifNode);
-        }
         return ifNode;
     }
 
     /**
-     * Returns a {@link SLReturnNode} for the given token. This node will be instrumented, tagged as
-     * a statement and wrapped in an {@link SLStatementWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * 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 either:
-     *         <ul>
-     *         <li>An un-instrumented SLReturnNode if there is no prober</li>
-     *         <li>An {@link SLStatementWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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);
-        if (prober != null) {
-            return prober.probeAsStatement(returnNode);
-        }
         return returnNode;
     }
 
@@ -274,7 +225,7 @@
      * @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 for the operation given by opToken.
+     * @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();
@@ -311,54 +262,33 @@
     }
 
     /**
-     * Returns a {@link SLInvokeNode} for the given token. This node will be instrumented, tagged as
-     * a call and wrapped in an {@link SLExpressionWrapper} if an {@link SLASTProber} was
-     * initialized in this class. ({@link #prober} != null)
+     * Returns an {@link SLInvokeNode} for the given parameters.
      *
      * @param nameToken The name of 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 either:
-     *         <ul>
-     *         <li>An un-instrumented SLInvokeNode if there is no prober</li>
-     *         <li>An {@link SLExpressionWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @return An SLInvokeNode for the given parameters.
      */
     public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes, Token finalToken) {
         final int startPos = nameToken.charPos;
         final int endPos = finalToken.charPos + finalToken.val.length();
         final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos);
         SLExpressionNode functionNode = createRead(nameToken);
-        if (prober != null) {
-            SLExpressionNode wrappedNode = prober.probeAsCall(functionNode, nameToken.val);
-            return SLInvokeNode.create(src, wrappedNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
-        }
         return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
     }
 
     /**
-     * Returns a {@link SLWriteLocalVariableNode} for the given token. This node will be
-     * instrumented, tagged as an assignment and wrapped in an {@link SLExpressionWrapper} if an
-     * {@link SLASTProber} was initialized in this class. ({@link #prober} != null)
+     * 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 either:
-     *         <ul>
-     *         <li>An un-instrumented SLWriteLocalVariableNode if there is no prober</li>
-     *         <li>An {@link SLExpressionWrapper} instrumenting this node.</li>
-     *         </ul>
+     * @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;
-        if (prober != null) {
-            SLWriteLocalVariableNode writeNode = SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot);
-            final SLExpressionNode wrappedNode = prober.probeAsLocalAssignment(writeNode, nameToken.val);
-            return wrappedNode;
-        }
         return SLWriteLocalVariableNodeFactory.create(source.createSection("=", start, length), valueNode, frameSlot);
     }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Fri Aug 22 16:03:49 2014 +0200
@@ -33,7 +33,6 @@
 import com.oracle.truffle.sl.*;
 import com.oracle.truffle.sl.builtins.*;
 import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.nodes.instrument.*;
 import com.oracle.truffle.sl.nodes.local.*;
 import com.oracle.truffle.sl.parser.*;
 
@@ -52,7 +51,6 @@
     private final PrintStream output;
     private final SLFunctionRegistry functionRegistry;
     private SourceCallback sourceCallback = null;
-    private SLASTProber astProber;
 
     public SLContext(BufferedReader input, PrintStream output) {
         this.input = input;
@@ -154,7 +152,7 @@
             sourceCallback.startLoading(source);
         }
 
-        Parser.parseSL(this, source, astProber);
+        Parser.parseSL(this, source);
 
         if (sourceCallback != null) {
             sourceCallback.endLoading(source);
@@ -166,13 +164,4 @@
         }
         main.getCallTarget().call();
     }
-
-    /**
-     * Sets the {@link SLASTProber} for the executeMain method.
-     *
-     * @param astProber The prober to use for adding instrumentation for this context.
-     */
-    public void setASTNodeProber(SLASTProber astProber) {
-        this.astProber = astProber;
-    }
 }
--- a/mx/mx_graal.py	Fri Aug 22 15:56:51 2014 +0200
+++ b/mx/mx_graal.py	Fri Aug 22 16:03:49 2014 +0200
@@ -459,10 +459,14 @@
             _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
 
     if installJars:
-        _installDistInJdks(mx.distribution('GRAAL'))
-        _installDistInJdks(mx.distribution('GRAAL_LOADER'))
-        _installDistInJdks(mx.distribution('TRUFFLE'))
-        _installDistInJdks(mx.distribution('GRAAL_TRUFFLE'))
+        def _installDistInJdksIfExists(dist):
+            if exists(dist.path):
+                _installDistInJdks(dist)
+
+        _installDistInJdksIfExists(mx.distribution('GRAAL'))
+        _installDistInJdksIfExists(mx.distribution('GRAAL_LOADER'))
+        _installDistInJdksIfExists(mx.distribution('TRUFFLE'))
+        _installDistInJdksIfExists(mx.distribution('GRAAL_TRUFFLE'))
 
     if vmToCheck is not None:
         jvmCfg = _vmCfgInJdk(jdk)
@@ -546,7 +550,7 @@
         os.unlink(javaSource)
         os.unlink(javaClass)
 
-def _copyToJdk(src, dst):
+def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE):
     name = os.path.basename(src)
     dstLib = join(dst, name)
     if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true':
@@ -556,17 +560,14 @@
         if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src:
             if exists(dstLib):
                 os.remove(dstLib)
-                os.symlink(src, dstLib)
+            os.symlink(src, dstLib)
     else:
         # do a copy and then a move to get atomic updating (on Unix)
         fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst)
         shutil.copyfile(src, tmp)
         os.close(fd)
         shutil.move(tmp, dstLib)
-        os.chmod(dstLib, JDK_UNIX_PERMISSIONS_FILE)
-
-def _installDistInJdksExt(dist):
-    _installDistInJdks(dist, True)
+        os.chmod(dstLib, permissions)
 
 def _installDistInJdks(dist, ext=False):
     """
@@ -685,17 +686,19 @@
         # extract latest release tag for graal
         try:
             tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")]
-            current_revision = subprocess.check_output(['hg', '-R', _graal_home, 'id', '-i']).strip()
+            current_id = subprocess.check_output(['hg', '-R', _graal_home, 'log', '--template', '{rev}\n', '--rev', 'tip']).strip()
         except:
             # not a mercurial repository or hg commands are not available.
             tags = None
 
-        if tags and current_revision:
+        if tags and current_id:
             sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True)
             most_recent_tag_name, most_recent_tag_revision = sorted_tags[0]
+            most_recent_tag_id = most_recent_tag_revision[:most_recent_tag_revision.index(":")]
             most_recent_tag_version = most_recent_tag_name[len("graal-"):]
 
-            if current_revision == most_recent_tag_revision:
+            # tagged commit is one-off with commit that tags it
+            if int(current_id) - int(most_recent_tag_id) <= 1:
                 cached_graal_version = most_recent_tag_version
             else:
                 major, minor = map(int, most_recent_tag_version.split('.'))
@@ -771,7 +774,7 @@
             if build is None or len(build) == 0:
                 continue
 
-        jdk = _jdk(build, create=True, installJars=not opts2.java)
+        jdk = _jdk(build, create=True, installJars=vm != 'original' and not opts2.java)
 
         if vm == 'original':
             if build != 'product':
@@ -987,6 +990,10 @@
         if  len(ignoredArgs) > 0:
             mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
 
+    if vm == 'original':
+        truffle_jar = mx.archive(['@TRUFFLE'])[0]
+        args = ['-Xbootclasspath/p:' + truffle_jar] + args
+
     args = mx.java().processArgs(args)
     return (pfx, exe, vm, args, cwd)
 
--- a/mx/projects	Fri Aug 22 15:56:51 2014 +0200
+++ b/mx/projects	Fri Aug 22 16:03:49 2014 +0200
@@ -128,14 +128,14 @@
 project@com.oracle.nfi@sourceDirs=src
 project@com.oracle.nfi@dependencies=
 project@com.oracle.nfi@checkstyle=com.oracle.graal.graph
-project@com.oracle.nfi@javaCompliance=1.8
+project@com.oracle.nfi@javaCompliance=1.7
 
 # nfi.test
 project@com.oracle.nfi.test@subDir=graal
 project@com.oracle.nfi.test@sourceDirs=test
 project@com.oracle.nfi.test@dependencies=com.oracle.nfi,com.oracle.graal.compiler.common,JUNIT
 project@com.oracle.nfi.test@checkstyle=com.oracle.graal.graph
-project@com.oracle.nfi.test@javaCompliance=1.8
+project@com.oracle.nfi.test@javaCompliance=1.7
 
 # graal.api.collections
 project@com.oracle.graal.api.collections@subDir=graal
--- a/mxtool/mx.py	Fri Aug 22 15:56:51 2014 +0200
+++ b/mxtool/mx.py	Fri Aug 22 16:03:49 2014 +0200
@@ -2516,9 +2516,10 @@
                 log('Compiling {} failed'.format(t.proj.name))
             abort('{} Java compilation tasks failed'.format(len(failed)))
 
-    for dist in sorted_dists():
-        if dist not in updatedAnnotationProcessorDists:
-            archive(['@' + dist.name])
+    if args.java:
+        for dist in sorted_dists():
+            if dist not in updatedAnnotationProcessorDists:
+                archive(['@' + dist.name])
 
     if suppliedParser:
         return args
--- a/src/gpu/hsail/vm/gpu_hsail.cpp	Fri Aug 22 15:56:51 2014 +0200
+++ b/src/gpu/hsail/vm/gpu_hsail.cpp	Fri Aug 22 16:03:49 2014 +0200
@@ -140,6 +140,8 @@
                                                 jint num_tlabs, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) {
   ResourceMark rm(THREAD);
   objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args);
+  // Note this length does not include the iteration variable since it is replaced by the HSA workitemid
+  int argsArrayLength = argsArray->length();
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
 
   // We avoid HSAILAllocationInfo logic if kernel does not allocate
@@ -296,7 +298,8 @@
             KlassHandle methKlass = mh->method_holder();
             Thread* THREAD = Thread::current();
             JavaValue result(T_VOID);
-            JavaCallArguments javaArgs;
+            // Add the iteration variable to the HSA args length
+            JavaCallArguments javaArgs(argsArrayLength + 1);
             // re-resolve the args_handle here
             objArrayOop resolvedArgsArray = (objArrayOop) JNIHandles::resolve(args);
 
@@ -344,8 +347,11 @@
   // The kernel entrypoint is always run for the time being  
   const char* entryPointName = "&run";
   jlong okra_kernel;
-  jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel);
-  guarantee(okra_status==0, "_okra_create_kernel failed");
+  {
+    TraceTime t("generate kernel ", TraceGPUInteraction);
+    jint okra_status = _okra_create_kernel(_device_context, code, entryPointName, (void**)&okra_kernel);
+    guarantee(okra_status==0, "_okra_create_kernel failed");
+  }
   return (jlong) okra_kernel;
 GPU_END
 
--- a/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Fri Aug 22 15:56:51 2014 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java	Fri Aug 22 16:03:49 2014 +0200
@@ -283,8 +283,8 @@
 
     @Override
     public void mouseDragged(MouseEvent e) {
-        // Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
-        // scrollRectToVisible(r);
+        Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
+        scrollRectToVisible(r);
 
         if (state == State.DragBar) {
             float firstX = this.getStartXPosition(model.getFirstPosition());
--- a/src/share/vm/graal/graalRuntime.cpp	Fri Aug 22 15:56:51 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Fri Aug 22 16:03:49 2014 +0200
@@ -487,7 +487,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
+JRT_LEAF(void, GraalRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
   bool string =  mask_bits_are_true(flags, LOG_OBJECT_STRING);
   bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS);
   bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE);
@@ -600,7 +600,7 @@
   }
 JRT_END
 
-JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
+JRT_LEAF(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline))
   union {
       jlong l;
       jdouble d;
@@ -728,7 +728,8 @@
 JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c))
   HandleMark hm;
   KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c)));
-  return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false);
+  bool result = GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false);
+  return result;
 JVM_END
 
 jint GraalRuntime::check_arguments(TRAPS) {
@@ -774,7 +775,7 @@
   return CITime || CITimeEach;
 }
 
-void GraalRuntime::check_required_value(const char* name, int name_len, const char* value, TRAPS) {
+void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) {
   if (value == NULL) {
     char buf[200];
     jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=<value>' format for %.*s option", name_len, name, name_len, name);
@@ -790,7 +791,7 @@
   if (first == '+' || first == '-') {
     name = arg + 1;
     name_len = strlen(name);
-    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, arg, CHECK);
+    recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK);
   } else {
     char* sep = strchr(arg, '=');
     name = arg;
@@ -801,13 +802,13 @@
     } else {
       name_len = strlen(name);
     }
-    recognized = set_option(hotSpotOptionsClass, name, (int)name_len, value, CHECK);
+    recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK);
   }
 
   if (!recognized) {
     bool throw_err = hotSpotOptionsClass.is_null();
     if (!hotSpotOptionsClass.is_null()) {
-      set_option_helper(hotSpotOptionsClass, name, (int)name_len, Handle(), ' ', Handle(), 0L);
+      set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L);
       if (!HAS_PENDING_EXCEPTION) {
         throw_err = true;
       }
@@ -823,7 +824,7 @@
 
 void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) {
   const char* home = Arguments::get_java_home();
-  int path_len = (int)strlen(home) + (int)strlen("/lib/graal.options") + 1;
+  size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1;
   char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len);
   char sep = os::file_separator()[0];
   sprintf(path, "%s%clib%cgraal.options", home, sep, sep);
@@ -868,7 +869,7 @@
   }
 }
 
-jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS) {
+jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) {
   check_required_value(name, name_len, value, CHECK_(0L));
   union {
     jint i;
@@ -905,11 +906,11 @@
   THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L);
 }
 
-void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
+void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) {
   Thread* THREAD = Thread::current();
   Handle name_handle;
   if (name != NULL) {
-    if ((int) strlen(name) > name_len) {
+    if (strlen(name) > name_len) {
       // Temporarily replace '=' with NULL to create the Java string for the option name
       char save = name[name_len];
       name[name_len] = '\0';
@@ -919,7 +920,7 @@
         return;
       }
     } else {
-      assert((int) strlen(name) == name_len, "must be");
+      assert(strlen(name) == name_len, "must be");
       name_handle = java_lang_String::create_from_str(name, CHECK);
     }
   }
--- a/src/share/vm/graal/graalRuntime.hpp	Fri Aug 22 15:56:51 2014 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Fri Aug 22 16:03:49 2014 +0200
@@ -52,7 +52,7 @@
    * @param value string value to parse
    * @throws InternalError if value could not be parsed according to spec
    */
-  static jlong parse_primitive_option_value(char spec, const char* name, int name_len, const char* value, TRAPS);
+  static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Loads default option value overrides from a <jre_home>/lib/graal.options if it exists. Each
@@ -70,6 +70,21 @@
   static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS);
 
   /**
+   * Searches for a Boolean Graal option denoted by a given name and sets it value.
+   *
+   * The definition of this method is in graalRuntime.inline.hpp
+   * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.
+   *
+   * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option
+   * @param name option name
+   * @param name_len length of option name
+   * @param value '+' to set the option, '-' to reset the option
+   * @returns true if the option was found
+   * @throws InternalError if there was a problem setting the option's value
+   */
+  static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS);
+
+  /**
    * Searches for a Graal option denoted by a given name and sets it value.
    *
    * The definition of this method is in graalRuntime.inline.hpp
@@ -81,12 +96,12 @@
    * @returns true if the option was found
    * @throws InternalError if there was a problem setting the option's value
    */
-  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, int name_len, const char* value, TRAPS);
+  static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Raises an InternalError for an option that expects a value but was specified without a "=<value>" prefix.
    */
-  static void check_required_value(const char* name, int name_len, const char* value, TRAPS);
+  static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS);
 
   /**
    * Java call to HotSpotOptions.setOption(String name, OptionValue<?> option, char spec, String stringValue, long primitiveValue)
@@ -94,7 +109,7 @@
    * @param name option name
    * @param name_len length of option name
    */
-  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, int name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
+  static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue);
 
   /**
    * Instantiates a service object, calls its default constructor and returns it.
--- a/src/share/vm/runtime/os.cpp	Fri Aug 22 15:56:51 2014 +0200
+++ b/src/share/vm/runtime/os.cpp	Fri Aug 22 16:03:49 2014 +0200
@@ -1269,6 +1269,8 @@
 #endif
 #ifdef GRAAL
         "%/lib/graal-loader.jar:"
+#endif
+#ifndef NO_TRUFFLE_JAR
         "%/lib/truffle.jar:"
 #endif
         "%/classes";