changeset 21757:f60f7994c5a5

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 05 Jun 2015 17:12:08 +0200
parents 30b4de402a58 (current diff) 2e850dbf82ae (diff)
children 532f9b06f54e
files graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/DisassemblerProvider.java
diffstat 39 files changed, 1444 insertions(+), 1565 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java	Fri Jun 05 17:12:08 2015 +0200
@@ -26,6 +26,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.code.*;
 import com.oracle.graal.test.*;
 import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.debug.*;
@@ -67,8 +68,10 @@
             InstalledCode code = codeCache.addMethod(method, compResult, null, null);
 
             for (DisassemblerProvider dis : Services.load(DisassemblerProvider.class)) {
-                String disasm = dis.disassemble(code);
-                Assert.assertTrue(code.toString(), disasm == null || disasm.length() > 0);
+                String disasm1 = dis.disassembleCompiledCode(codeCache, compResult);
+                Assert.assertTrue(compResult.toString(), disasm1 == null || disasm1.length() > 0);
+                String disasm2 = dis.disassembleInstalledCode(codeCache, compResult, code);
+                Assert.assertTrue(code.toString(), disasm2 == null || disasm2.length() > 0);
             }
             return code;
         } catch (Throwable e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.code/src/com/oracle/graal/code/DisassemblerProvider.java	Fri Jun 05 17:12:08 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.code;
+
+import com.oracle.jvmci.code.*;
+import com.oracle.jvmci.service.*;
+
+/**
+ * Interface providing capability for disassembling machine code.
+ */
+public interface DisassemblerProvider extends Service {
+
+    /**
+     * Gets a textual disassembly of a given compilation result.
+     *
+     * @param codeCache the object used for code {@link CodeCacheProvider#addMethod code
+     *            installation}
+     * @param compResult a compilation result
+     * @return a non-zero length string containing a disassembly of {@code compResult} or null it
+     *         could not be disassembled
+     */
+    default String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) {
+        return null;
+    }
+
+    /**
+     * Gets a textual disassembly of a given installed code.
+     *
+     * @param codeCache the object used for code {@link CodeCacheProvider#addMethod code
+     *            installation}
+     * @param compResult a compiled code that was installed to produce {@code installedCode}. This
+     *            will be null if not available.
+     * @param installedCode
+     * @return a non-zero length string containing a disassembly of {@code code} or null if
+     *         {@code code} is {@link InstalledCode#isValid() invalid} or it could not be
+     *         disassembled for some other reason
+     */
+    default String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) {
+        return null;
+    }
+
+    /**
+     * Gets the name denoting the format of the disassmembly return by this object.
+     */
+    String getName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFile.java	Fri Jun 05 17:12:08 2015 +0200
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.code;
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import com.oracle.jvmci.code.*;
+import com.oracle.jvmci.code.CompilationResult.CodeAnnotation;
+import com.oracle.jvmci.code.CompilationResult.CodeComment;
+import com.oracle.jvmci.code.CompilationResult.JumpTable;
+
+/**
+ * A HexCodeFile is a textual format for representing a chunk of machine code along with extra
+ * information that can be used to enhance a disassembly of the code.
+ *
+ * A pseudo grammar for a HexCodeFile is given below.
+ *
+ * <pre>
+ *     HexCodeFile ::= Platform Delim HexCode Delim (OptionalSection Delim)*
+ *
+ *     OptionalSection ::= Comment | OperandComment | JumpTable | LookupTable
+ *
+ *     Platform ::= "Platform" ISA WordWidth
+ *
+ *     HexCode ::= "HexCode" StartAddress HexDigits
+ *
+ *     Comment ::= "Comment" Position String
+ *
+ *     OperandComment ::= "OperandComment" Position String
+ *
+ *     JumpTable ::= "JumpTable" Position EntrySize Low High
+ *
+ *     LookupTable ::= "LookupTable" Position NPairs KeySize OffsetSize
+ *
+ *     Position, EntrySize, Low, High, NPairs KeySize OffsetSize ::= int
+ *
+ *     Delim := "&lt;||@"
+ * </pre>
+ *
+ * There must be exactly one HexCode and Platform part in a HexCodeFile. The length of HexDigits
+ * must be even as each pair of digits represents a single byte.
+ * <p>
+ * Below is an example of a valid Code input:
+ *
+ * <pre>
+ *
+ *  Platform AMD64 64  &lt;||@
+ *  HexCode 0 e8000000009090904883ec084889842410d0ffff48893c24e800000000488b3c24488bf0e8000000004883c408c3  &lt;||@
+ *  Comment 24 frame-ref-map: +0 {0}
+ *  at java.lang.String.toLowerCase(String.java:2496) [bci: 1]
+ *              |0
+ *     locals:  |stack:0:a
+ *     stack:   |stack:0:a
+ *    &lt;||@
+ *  OperandComment 24 {java.util.Locale.getDefault()}  &lt;||@
+ *  Comment 36 frame-ref-map: +0 {0}
+ *  at java.lang.String.toLowerCase(String.java:2496) [bci: 4]
+ *              |0
+ *     locals:  |stack:0:a
+ *    &lt;||@
+ *  OperandComment 36 {java.lang.String.toLowerCase(Locale)}  lt;||@
+ *
+ * </pre>
+ */
+public class HexCodeFile {
+
+    public static final String NEW_LINE = CodeUtil.NEW_LINE;
+    public static final String SECTION_DELIM = " <||@";
+    public static final String COLUMN_END = " <|@";
+    public static final Pattern SECTION = Pattern.compile("(\\S+)\\s+(.*)", Pattern.DOTALL);
+    public static final Pattern COMMENT = Pattern.compile("(\\d+)\\s+(.*)", Pattern.DOTALL);
+    public static final Pattern OPERAND_COMMENT = COMMENT;
+    public static final Pattern JUMP_TABLE = Pattern.compile("(\\d+)\\s+(\\d+)\\s+(-{0,1}\\d+)\\s+(-{0,1}\\d+)\\s*");
+    public static final Pattern LOOKUP_TABLE = Pattern.compile("(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s*");
+    public static final Pattern HEX_CODE = Pattern.compile("(\\p{XDigit}+)(?:\\s+(\\p{XDigit}*))?");
+    public static final Pattern PLATFORM = Pattern.compile("(\\S+)\\s+(\\S+)", Pattern.DOTALL);
+
+    /**
+     * Delimiter placed before a HexCodeFile when embedded in a string/stream.
+     */
+    public static final String EMBEDDED_HCF_OPEN = "<<<HexCodeFile";
+
+    /**
+     * Delimiter placed after a HexCodeFile when embedded in a string/stream.
+     */
+    public static final String EMBEDDED_HCF_CLOSE = "HexCodeFile>>>";
+
+    /**
+     * Map from a machine code position to a list of comments for the position.
+     */
+    public final Map<Integer, List<String>> comments = new TreeMap<>();
+
+    /**
+     * Map from a machine code position to a comment for the operands of the instruction at the
+     * position.
+     */
+    public final Map<Integer, String> operandComments = new TreeMap<>();
+
+    public final byte[] code;
+
+    public final ArrayList<JumpTable> jumpTables = new ArrayList<>();
+
+    public final String isa;
+
+    public final int wordWidth;
+
+    public final long startAddress;
+
+    public HexCodeFile(byte[] code, long startAddress, String isa, int wordWidth) {
+        this.code = code;
+        this.startAddress = startAddress;
+        this.isa = isa;
+        this.wordWidth = wordWidth;
+    }
+
+    /**
+     * Parses a string in the format produced by {@link #toString()} to produce a
+     * {@link HexCodeFile} object.
+     */
+    public static HexCodeFile parse(String input, int sourceOffset, String source, String sourceName) {
+        return new Parser(input, sourceOffset, source, sourceName).hcf;
+    }
+
+    /**
+     * Formats this HexCodeFile as a string that can be parsed with
+     * {@link #parse(String, int, String, String)}.
+     */
+    @Override
+    public String toString() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        writeTo(baos);
+        return baos.toString();
+    }
+
+    public String toEmbeddedString() {
+        return EMBEDDED_HCF_OPEN + NEW_LINE + toString() + EMBEDDED_HCF_CLOSE;
+    }
+
+    public void writeTo(OutputStream out) {
+        PrintStream ps = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
+        ps.printf("Platform %s %d %s%n", isa, wordWidth, SECTION_DELIM);
+        ps.printf("HexCode %x %s %s%n", startAddress, HexCodeFile.hexCodeString(code), SECTION_DELIM);
+
+        for (JumpTable table : jumpTables) {
+            ps.printf("JumpTable %d %d %d %d %s%n", table.position, table.entrySize, table.low, table.high, SECTION_DELIM);
+        }
+
+        for (Map.Entry<Integer, List<String>> e : comments.entrySet()) {
+            int pos = e.getKey();
+            for (String comment : e.getValue()) {
+                ps.printf("Comment %d %s %s%n", pos, comment, SECTION_DELIM);
+            }
+        }
+
+        for (Map.Entry<Integer, String> e : operandComments.entrySet()) {
+            ps.printf("OperandComment %d %s %s%n", e.getKey(), e.getValue(), SECTION_DELIM);
+        }
+        ps.flush();
+    }
+
+    /**
+     * Formats a byte array as a string of hex digits.
+     */
+    public static String hexCodeString(byte[] code) {
+        if (code == null) {
+            return "";
+        } else {
+            StringBuilder sb = new StringBuilder(code.length * 2);
+            for (int b : code) {
+                String hex = Integer.toHexString(b & 0xff);
+                if (hex.length() == 1) {
+                    sb.append('0');
+                }
+                sb.append(hex);
+            }
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Adds a comment to the list of comments for a given position.
+     */
+    public void addComment(int pos, String comment) {
+        List<String> list = comments.get(pos);
+        if (list == null) {
+            list = new ArrayList<>();
+            comments.put(pos, list);
+        }
+        list.add(encodeString(comment));
+    }
+
+    /**
+     * Sets an operand comment for a given position.
+     *
+     * @return the previous operand comment for {@code pos}
+     */
+    public String addOperandComment(int pos, String comment) {
+        return operandComments.put(pos, encodeString(comment));
+    }
+
+    /**
+     * Adds any jump tables, lookup tables or code comments from a list of code annotations.
+     */
+    public static void addAnnotations(HexCodeFile hcf, List<CodeAnnotation> annotations) {
+        if (annotations == null || annotations.isEmpty()) {
+            return;
+        }
+        for (CodeAnnotation a : annotations) {
+            if (a instanceof JumpTable) {
+                JumpTable table = (JumpTable) a;
+                hcf.jumpTables.add(table);
+            } else if (a instanceof CodeComment) {
+                CodeComment comment = (CodeComment) a;
+                hcf.addComment(comment.position, comment.value);
+            }
+        }
+    }
+
+    /**
+     * Modifies a string to mangle any substrings matching {@link #SECTION_DELIM} and
+     * {@link #COLUMN_END}.
+     */
+    public static String encodeString(String input) {
+        int index;
+        String s = input;
+        while ((index = s.indexOf(SECTION_DELIM)) != -1) {
+            s = s.substring(0, index) + " < |@" + s.substring(index + SECTION_DELIM.length());
+        }
+        while ((index = s.indexOf(COLUMN_END)) != -1) {
+            s = s.substring(0, index) + " < @" + s.substring(index + COLUMN_END.length());
+        }
+        return s;
+    }
+
+    /**
+     * Helper class to parse a string in the format produced by {@link HexCodeFile#toString()} and
+     * produce a {@link HexCodeFile} object.
+     */
+    static class Parser {
+
+        final String input;
+        final String inputSource;
+        String isa;
+        int wordWidth;
+        byte[] code;
+        long startAddress;
+        HexCodeFile hcf;
+
+        Parser(String input, int sourceOffset, String source, String sourceName) {
+            this.input = input;
+            this.inputSource = sourceName;
+            parseSections(sourceOffset, source);
+        }
+
+        void makeHCF() {
+            if (hcf == null) {
+                if (isa != null && wordWidth != 0 && code != null) {
+                    hcf = new HexCodeFile(code, startAddress, isa, wordWidth);
+                }
+            }
+        }
+
+        void checkHCF(String section, int offset) {
+            check(hcf != null, offset, section + " section must be after Platform and HexCode section");
+        }
+
+        void check(boolean condition, int offset, String message) {
+            if (!condition) {
+                error(offset, message);
+            }
+        }
+
+        Error error(int offset, String message) {
+            throw new Error(errorMessage(offset, message));
+        }
+
+        void warning(int offset, String message) {
+            PrintStream err = System.err;
+            err.println("Warning: " + errorMessage(offset, message));
+        }
+
+        String errorMessage(int offset, String message) {
+            assert offset < input.length();
+            InputPos inputPos = filePos(offset);
+            int lineEnd = input.indexOf(HexCodeFile.NEW_LINE, offset);
+            int lineStart = offset - inputPos.col;
+            String line = lineEnd == -1 ? input.substring(lineStart) : input.substring(lineStart, lineEnd);
+            return String.format("%s:%d: %s%n%s%n%" + (inputPos.col + 1) + "s", inputSource, inputPos.line, message, line, "^");
+        }
+
+        static class InputPos {
+
+            final int line;
+            final int col;
+
+            public InputPos(int line, int col) {
+                this.line = line;
+                this.col = col;
+            }
+        }
+
+        InputPos filePos(int index) {
+            assert input != null;
+            int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1;
+
+            String l = input.substring(lineStart, lineStart + 10);
+            PrintStream out = System.out;
+            out.println("YYY" + input.substring(index, index + 10) + "...");
+            out.println("XXX" + l + "...");
+
+            int pos = input.indexOf(HexCodeFile.NEW_LINE, 0);
+            int line = 1;
+            while (pos > 0 && pos < index) {
+                line++;
+                pos = input.indexOf(HexCodeFile.NEW_LINE, pos + 1);
+            }
+            return new InputPos(line, index - lineStart);
+        }
+
+        void parseSections(int offset, String source) {
+            assert input.startsWith(source, offset);
+            int index = 0;
+            int endIndex = source.indexOf(SECTION_DELIM);
+            while (endIndex != -1) {
+                while (source.charAt(index) <= ' ') {
+                    index++;
+                }
+                String section = source.substring(index, endIndex).trim();
+                parseSection(offset + index, section);
+                index = endIndex + SECTION_DELIM.length();
+                endIndex = source.indexOf(SECTION_DELIM, index);
+            }
+        }
+
+        int parseInt(int offset, String value) {
+            try {
+                return Integer.parseInt(value);
+            } catch (NumberFormatException e) {
+                throw error(offset, "Not a valid integer: " + value);
+            }
+        }
+
+        void parseSection(int offset, String section) {
+            if (section.isEmpty()) {
+                return;
+            }
+            assert input.startsWith(section, offset);
+            Matcher m = HexCodeFile.SECTION.matcher(section);
+            check(m.matches(), offset, "Section does not match pattern " + HexCodeFile.SECTION);
+
+            String header = m.group(1);
+            String body = m.group(2);
+            int headerOffset = offset + m.start(1);
+            int bodyOffset = offset + m.start(2);
+
+            if (header.equals("Platform")) {
+                check(isa == null, bodyOffset, "Duplicate Platform section found");
+                m = HexCodeFile.PLATFORM.matcher(body);
+                check(m.matches(), bodyOffset, "Platform does not match pattern " + HexCodeFile.PLATFORM);
+                isa = m.group(1);
+                wordWidth = parseInt(bodyOffset + m.start(2), m.group(2));
+                makeHCF();
+            } else if (header.equals("HexCode")) {
+                check(code == null, bodyOffset, "Duplicate Code section found");
+                m = HexCodeFile.HEX_CODE.matcher(body);
+                check(m.matches(), bodyOffset, "Code does not match pattern " + HexCodeFile.HEX_CODE);
+                String hexAddress = m.group(1);
+                startAddress = Long.valueOf(hexAddress, 16);
+                String hexCode = m.group(2);
+                if (hexCode == null) {
+                    code = new byte[0];
+                } else {
+                    check((hexCode.length() % 2) == 0, bodyOffset, "Hex code length must be even");
+                    code = new byte[hexCode.length() / 2];
+                    for (int i = 0; i < code.length; i++) {
+                        String hexByte = hexCode.substring(i * 2, (i + 1) * 2);
+                        code[i] = (byte) Integer.parseInt(hexByte, 16);
+                    }
+                }
+                makeHCF();
+            } else if (header.equals("Comment")) {
+                checkHCF("Comment", headerOffset);
+                m = HexCodeFile.COMMENT.matcher(body);
+                check(m.matches(), bodyOffset, "Comment does not match pattern " + HexCodeFile.COMMENT);
+                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
+                String comment = m.group(2);
+                hcf.addComment(pos, comment);
+            } else if (header.equals("OperandComment")) {
+                checkHCF("OperandComment", headerOffset);
+                m = HexCodeFile.OPERAND_COMMENT.matcher(body);
+                check(m.matches(), bodyOffset, "OperandComment does not match pattern " + HexCodeFile.OPERAND_COMMENT);
+                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
+                String comment = m.group(2);
+                hcf.addOperandComment(pos, comment);
+            } else if (header.equals("JumpTable")) {
+                checkHCF("JumpTable", headerOffset);
+                m = HexCodeFile.JUMP_TABLE.matcher(body);
+                check(m.matches(), bodyOffset, "JumpTable does not match pattern " + HexCodeFile.JUMP_TABLE);
+                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
+                int entrySize = parseInt(bodyOffset + m.start(2), m.group(2));
+                int low = parseInt(bodyOffset + m.start(3), m.group(3));
+                int high = parseInt(bodyOffset + m.start(4), m.group(4));
+                hcf.jumpTables.add(new JumpTable(pos, low, high, entrySize));
+            } else {
+                error(offset, "Unknown section header: " + header);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFileDisassemblerProvider.java	Fri Jun 05 17:12:08 2015 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.code;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.jvmci.code.*;
+import com.oracle.jvmci.code.CodeUtil.DefaultRefMapFormatter;
+import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
+import com.oracle.jvmci.code.CompilationResult.Call;
+import com.oracle.jvmci.code.CompilationResult.DataPatch;
+import com.oracle.jvmci.code.CompilationResult.Infopoint;
+import com.oracle.jvmci.code.CompilationResult.Mark;
+import com.oracle.jvmci.service.*;
+
+/**
+ * {@link HexCodeFile} based implementation of {@link DisassemblerProvider}.
+ */
+@ServiceProvider(DisassemblerProvider.class)
+public class HexCodeFileDisassemblerProvider implements DisassemblerProvider {
+
+    @Override
+    public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) {
+        assert compResult != null;
+        return disassemble(codeCache, compResult, null);
+    }
+
+    public String getName() {
+        return "hcf";
+    }
+
+    @Override
+    public String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) {
+        assert installedCode != null;
+        return installedCode.isValid() ? disassemble(codeCache, compResult, installedCode) : null;
+    }
+
+    private static String disassemble(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) {
+        TargetDescription target = codeCache.getTarget();
+        RegisterConfig regConfig = codeCache.getRegisterConfig();
+        byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
+        if (code == null) {
+            // Method was deoptimized/invalidated
+            return "";
+        }
+        long start = installedCode == null ? 0L : installedCode.getStart();
+        HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
+        if (compResult != null) {
+            HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
+            addExceptionHandlersComment(compResult, hcf);
+            Register fp = regConfig.getFrameRegister();
+            RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0);
+            for (Infopoint infopoint : compResult.getInfopoints()) {
+                if (infopoint instanceof Call) {
+                    Call call = (Call) infopoint;
+                    if (call.debugInfo != null) {
+                        hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
+                    }
+                    addOperandComment(hcf, call.pcOffset, "{" + codeCache.getTargetName(call) + "}");
+                } else {
+                    if (infopoint.debugInfo != null) {
+                        hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
+                    }
+                    addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
+                }
+            }
+            for (DataPatch site : compResult.getDataPatches()) {
+                hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}");
+            }
+            for (Mark mark : compResult.getMarks()) {
+                hcf.addComment(mark.pcOffset, codeCache.getMarkName(mark));
+            }
+        }
+        String hcfEmbeddedString = hcf.toEmbeddedString();
+        return HexCodeFileDisTool.tryDisassemble(hcfEmbeddedString);
+    }
+
+    private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) {
+        if (!compResult.getExceptionHandlers().isEmpty()) {
+            String nl = HexCodeFile.NEW_LINE;
+            StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl);
+            for (CompilationResult.ExceptionHandler e : compResult.getExceptionHandlers()) {
+                buf.append("    ").append(e.pcOffset).append(" -> ").append(e.handlerPos).append(nl);
+                hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]");
+                hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]");
+            }
+            hcf.addComment(0, buf.toString());
+        }
+    }
+
+    private static void addOperandComment(HexCodeFile hcf, int pos, String comment) {
+        String oldValue = hcf.addOperandComment(pos, comment);
+        assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue;
+    }
+
+    /**
+     * Interface to the tool for disassembling an {@link HexCodeFile#toEmbeddedString() embedded}
+     * {@link HexCodeFile}.
+     */
+    static class HexCodeFileDisTool {
+        static final Method processMethod;
+        static {
+            Method toolMethod = null;
+            try {
+                Class<?> toolClass = Class.forName("com.oracle.max.hcfdis.HexCodeFileDis", true, ClassLoader.getSystemClassLoader());
+                toolMethod = toolClass.getDeclaredMethod("processEmbeddedString", String.class);
+            } catch (Exception e) {
+                // Tool not available on the class path
+            }
+            processMethod = toolMethod;
+        }
+
+        public static String tryDisassemble(String hcfEmbeddedString) {
+            if (processMethod != null) {
+                try {
+                    return (String) processMethod.invoke(null, hcfEmbeddedString);
+                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+                    // If the tool is available, for now let's be noisy when it fails
+                    throw new InternalError(e);
+                }
+            }
+            return hcfEmbeddedString;
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotDisassemblerProvider.java	Fri Jun 05 17:12:08 2015 +0200
@@ -24,6 +24,7 @@
 
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
+import com.oracle.graal.code.*;
 import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.hotspot.*;
 import com.oracle.jvmci.service.*;
@@ -34,11 +35,20 @@
 @ServiceProvider(DisassemblerProvider.class)
 public class HotSpotDisassemblerProvider implements DisassemblerProvider {
 
-    public String disassemble(InstalledCode code) {
+    public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) {
+        return null;
+    }
+
+    @Override
+    public String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode code) {
         if (code.isValid()) {
             long codeBlob = ((HotSpotInstalledCode) code).getAddress();
             return runtime().getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
     }
+
+    public String getName() {
+        return "hsdis";
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Jun 05 17:12:08 2015 +0200
@@ -33,6 +33,8 @@
 import com.oracle.jvmci.meta.ResolvedJavaMethod;
 import com.oracle.jvmci.meta.DeoptimizationAction;
 import com.oracle.jvmci.meta.ForeignCallDescriptor;
+
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.nodes.BeginLockScopeNode.*;
 import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*;
 import static com.oracle.graal.hotspot.nodes.EndLockScopeNode.*;
@@ -135,6 +137,7 @@
             // First check to see whether biasing is enabled for this object
             if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern())))) {
                 // Biasing not enabled -> fall through to lightweight locking
+                unbiasable.inc();
             } else {
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
@@ -148,6 +151,7 @@
                 if (probability(FREQUENT_PROBABILITY, tmp.equal(0))) {
                     // Object is already biased to current thread -> done
                     traceObject(trace, "+lock{bias:existing}", object, true);
+                    lockBiasExisting.inc();
                     return;
                 }
 
@@ -184,12 +188,14 @@
                         if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object, true);
+                            lockBiasAcquired.inc();
                             return;
                         }
                         // If the biasing toward our thread failed, this means that another thread
                         // owns the bias and we need to revoke that bias. The revocation will occur
                         // in the interpreter runtime.
                         traceObject(trace, "+lock{stub:revoke}", object, true);
+                        lockStubRevoke.inc();
                     } else {
                         // At this point we know the epoch has expired, meaning that the
                         // current bias owner, if any, is actually invalid. Under these
@@ -202,12 +208,14 @@
                         if (probability(VERY_FAST_PATH_PROBABILITY, compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object, true);
+                            lockBiasTransfer.inc();
                             return;
                         }
                         // If the biasing toward our thread failed, then another thread
                         // succeeded in biasing it toward itself and we need to revoke that
                         // bias. The revocation will occur in the runtime in the slow case.
                         traceObject(trace, "+lock{stub:epoch-expired}", object, true);
+                        lockStubEpochExpired.inc();
                     }
                     monitorenterStubC(MONITORENTER, object, lock);
                     return;
@@ -229,6 +237,7 @@
                     if (ENABLE_BREAKPOINT) {
                         bkpt(object, mark, tmp, result);
                     }
+                    revokeBias.inc();
                 }
             }
         }
@@ -265,15 +274,18 @@
             if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) {
                 // Most likely not a recursive lock, go into a slow runtime call
                 traceObject(trace, "+lock{stub:failed-cas}", object, true);
+                lockStubFailedCas.inc();
                 monitorenterStubC(MONITORENTER, object, lock);
                 return;
             } else {
                 // Recursively locked => write 0 to the lock slot
                 lock.writeWord(lockDisplacedMarkOffset(), Word.zero(), DISPLACED_MARK_WORD_LOCATION);
-                traceObject(trace, "+lock{recursive}", object, true);
+                traceObject(trace, "+lock{cas:recursive}", object, true);
+                lockCasRecursive.inc();
             }
         } else {
             traceObject(trace, "+lock{cas}", object, true);
+            lockCas.inc();
         }
     }
 
@@ -310,6 +322,7 @@
                 endLockScope();
                 decCounter();
                 traceObject(trace, "-lock{bias}", object, false);
+                unlockBias.inc();
                 return;
             }
         }
@@ -323,6 +336,7 @@
         if (displacedMark.equal(0)) {
             // Recursive locking => done
             traceObject(trace, "-lock{recursive}", object, false);
+            unlockCasRecursive.inc();
         } else {
             verifyOop(object);
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
@@ -332,9 +346,11 @@
                 // The object's mark word was not pointing to the displaced header,
                 // we do unlocking via runtime call.
                 traceObject(trace, "-lock{stub}", object, false);
+                unlockStub.inc();
                 monitorexitStubC(MONITOREXIT, object, lock);
             } else {
                 traceObject(trace, "-lock{cas}", object, false);
+                unlockCas.inc();
             }
         }
         endLockScope();
@@ -543,4 +559,31 @@
     @NodeIntrinsic(ForeignCallNode.class)
     private static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock);
 
+    /**
+     * Counters for the various paths for acquiring a lock. The counters whose names start with
+     * {@code "lock"} are mutually exclusive. The other counters are for paths that may be shared.
+     */
+    private static final SnippetCounter.Group lockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorEnters") : null;
+    static final SnippetCounter lockBiasExisting = new SnippetCounter(lockCounters, "lock{bias:existing}", "bias-locked previously biased object");
+    static final SnippetCounter lockBiasAcquired = new SnippetCounter(lockCounters, "lock{bias:acquired}", "bias-locked newly biased object");
+    static final SnippetCounter lockBiasTransfer = new SnippetCounter(lockCounters, "lock{bias:transfer}", "bias-locked, biased transferred");
+    static final SnippetCounter lockCas = new SnippetCounter(lockCounters, "lock{cas}", "cas-locked an object");
+    static final SnippetCounter lockCasRecursive = new SnippetCounter(lockCounters, "lock{cas:recursive}", "cas-locked, recursive");
+    static final SnippetCounter lockStubEpochExpired = new SnippetCounter(lockCounters, "lock{stub:epoch-expired}", "stub-locked, epoch expired");
+    static final SnippetCounter lockStubRevoke = new SnippetCounter(lockCounters, "lock{stub:revoke}", "stub-locked, biased revoked");
+    static final SnippetCounter lockStubFailedCas = new SnippetCounter(lockCounters, "lock{stub:failed-cas}", "stub-locked, failed cas");
+
+    static final SnippetCounter unbiasable = new SnippetCounter(lockCounters, "unbiasable", "object with unbiasable type");
+    static final SnippetCounter revokeBias = new SnippetCounter(lockCounters, "revokeBias", "object had bias revoked");
+
+    /**
+     * Counters for the various paths for releasing a lock. The counters whose names start with
+     * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be shared.
+     */
+    private static final SnippetCounter.Group unlockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorExits") : null;
+    static final SnippetCounter unlockBias = new SnippetCounter(unlockCounters, "unlock{bias}", "bias-unlocked an object");
+    static final SnippetCounter unlockCas = new SnippetCounter(unlockCounters, "unlock{cas}", "cas-unlocked an object");
+    static final SnippetCounter unlockCasRecursive = new SnippetCounter(unlockCounters, "unlock{cas:recursive}", "cas-unlocked an object, recursive");
+    static final SnippetCounter unlockStub = new SnippetCounter(unlockCounters, "unlock{stub}", "stub-unlocked an object");
+
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Jun 05 17:12:08 2015 +0200
@@ -64,8 +64,6 @@
     public static final class LabelOp extends LIRInstruction {
         public static final LIRInstructionClass<LabelOp> TYPE = LIRInstructionClass.create(LabelOp.class);
 
-        private static final Value[] NO_VALUES = new Value[0];
-
         /**
          * In the LIR, every register and variable must be defined before it is used. For method
          * parameters that are passed in fixed registers, exception objects passed to the exception
@@ -83,7 +81,7 @@
             super(TYPE);
             this.label = label;
             this.align = align;
-            this.incomingValues = NO_VALUES;
+            this.incomingValues = Value.NO_VALUES;
         }
 
         public void setIncomingValues(Value[] values) {
@@ -101,7 +99,7 @@
         }
 
         public void clearIncomingValues() {
-            incomingValues = NO_VALUES;
+            incomingValues = Value.NO_VALUES;
         }
 
         @Override
@@ -130,8 +128,6 @@
     public static class JumpOp extends LIRInstruction implements BlockEndOp {
         public static final LIRInstructionClass<JumpOp> TYPE = LIRInstructionClass.create(JumpOp.class);
 
-        private static final Value[] NO_VALUES = new Value[0];
-
         @Alive({REG, STACK, CONST}) private Value[] outgoingValues;
 
         private final LabelRef destination;
@@ -143,7 +139,7 @@
         protected JumpOp(LIRInstructionClass<? extends JumpOp> c, LabelRef destination) {
             super(c);
             this.destination = destination;
-            this.outgoingValues = NO_VALUES;
+            this.outgoingValues = Value.NO_VALUES;
         }
 
         public void setOutgoingValues(Value[] values) {
@@ -161,7 +157,7 @@
         }
 
         public void clearOutgoingValues() {
-            outgoingValues = NO_VALUES;
+            outgoingValues = Value.NO_VALUES;
         }
 
         @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java	Fri Jun 05 17:12:08 2015 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.jvmci.code.ValueUtil.*;
 
 import java.util.*;
+import java.util.function.*;
 
 import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
@@ -104,51 +105,203 @@
         }
     }
 
-    private static final class LiveValueSet implements Iterable<Value> {
-        private static final Object MARKER = new Object();
+    private static final class ValueSet {
+        private Value[] values;
 
-        private final HashMap<Value, Object> map;
-
-        public LiveValueSet() {
-            map = new HashMap<>();
+        ValueSet() {
+            values = Value.NO_VALUES;
         }
 
-        public LiveValueSet(LiveValueSet s) {
-            map = new HashMap<>(s.map);
+        ValueSet(ValueSet other) {
+            int limit = other.values.length;
+            while (limit > 0) {
+                if (other.values[limit - 1] == null) {
+                    limit--;
+                    continue;
+                }
+                break;
+            }
+            values = new Value[limit];
+            System.arraycopy(other.values, 0, values, 0, values.length);
         }
 
-        public void put(Value v) {
-            map.put(v, MARKER);
+        void put(int index, Value value) {
+            if (value != null && value.getLIRKind().isValue()) {
+                return;
+            }
+            if (values.length <= index) {
+                if (value == null) {
+                    return;
+                }
+                Value[] newValues = new Value[index + 1];
+                System.arraycopy(values, 0, newValues, 0, values.length);
+                values = newValues;
+                values[index] = value;
+            } else {
+                values[index] = value;
+            }
         }
 
-        public void putAll(LiveValueSet v) {
-            map.putAll(v.map);
-        }
-
-        public void remove(Value v) {
-            map.remove(v);
-        }
-
-        public Iterator<Value> iterator() {
-            return map.keySet().iterator();
+        public void putAll(ValueSet stack) {
+            Value[] otherValues = stack.values;
+            int limit = otherValues.length;
+            if (limit > values.length) {
+                while (limit > 0) {
+                    if (otherValues[limit - 1] == null) {
+                        limit--;
+                        continue;
+                    }
+                    break;
+                }
+                if (limit > values.length) {
+                    Value[] newValues = new Value[limit];
+                    System.arraycopy(values, 0, newValues, 0, values.length);
+                    values = newValues;
+                }
+            }
+            for (int i = 0; i < limit; i++) {
+                Value value = otherValues[i];
+                if (value != null) {
+                    values[i] = value;
+                }
+            }
         }
 
         @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof LiveValueSet) {
-                return map.equals(((LiveValueSet) obj).map);
-            } else {
-                return false;
+        public boolean equals(Object other) {
+            if (other instanceof ValueSet) {
+                ValueSet that = (ValueSet) other;
+                int limit = Math.min(values.length, that.values.length);
+                for (int i = 0; i < limit; i++) {
+                    if (!Objects.equals(values[i], that.values[i])) {
+                        return false;
+                    }
+                }
+                for (int i = limit; i < values.length; i++) {
+                    if (values[i] != null) {
+                        return false;
+                    }
+                }
+                for (int i = limit; i < that.values.length; i++) {
+                    if (that.values[i] != null) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+
+        public void addLiveValues(ReferenceMap refMap) {
+            for (Value v : values) {
+                if (v != null) {
+                    refMap.addLiveValue(v);
+                }
             }
         }
 
         @Override
         public int hashCode() {
-            return map.hashCode();
+            throw new UnsupportedOperationException();
         }
     }
 
     private static final class Marker<T extends AbstractBlockBase<T>> {
+
+        private final class LiveValueSet implements Consumer<AbstractBlockBase<T>> {
+
+            public void accept(AbstractBlockBase<T> succ) {
+                putAll(liveInMap.get(succ));
+            }
+
+            private final ValueSet registers;
+            private final ValueSet stack;
+            private Set<Value> extraStack;
+
+            public LiveValueSet() {
+                registers = new ValueSet();
+                stack = new ValueSet();
+            }
+
+            public LiveValueSet(LiveValueSet s) {
+                registers = new ValueSet(s.registers);
+                stack = new ValueSet(s.stack);
+                if (s.extraStack != null) {
+                    extraStack = new HashSet<>(s.extraStack);
+                }
+            }
+
+            public void put(Value v) {
+                if (isRegister(v)) {
+                    int index = asRegister(v).getReferenceMapIndex();
+                    registers.put(index, v);
+                } else if (isStackSlot(v)) {
+                    int index = frameMap.offsetForStackSlot(asStackSlot(v));
+                    assert index >= 0;
+                    if (index % 4 == 0) {
+                        stack.put(index / 4, v);
+                    } else {
+                        if (extraStack == null) {
+                            extraStack = new HashSet<>();
+                        }
+                        extraStack.add(v);
+                    }
+                }
+            }
+
+            public void putAll(LiveValueSet v) {
+                registers.putAll(v.registers);
+                stack.putAll(v.stack);
+                if (v.extraStack != null) {
+                    if (extraStack == null) {
+                        extraStack = new HashSet<>();
+                    }
+                    extraStack.addAll(v.extraStack);
+                }
+            }
+
+            public void remove(Value v) {
+                if (isRegister(v)) {
+                    int index = asRegister(v).getReferenceMapIndex();
+                    registers.put(index, null);
+                } else if (isStackSlot(v)) {
+                    int index = frameMap.offsetForStackSlot(asStackSlot(v));
+                    assert index >= 0;
+                    if (index % 4 == 0) {
+                        stack.put(index / 4, null);
+                    } else if (extraStack != null) {
+                        extraStack.remove(v);
+                    }
+                }
+            }
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public boolean equals(Object obj) {
+                if (obj instanceof Marker.LiveValueSet) {
+                    LiveValueSet other = (LiveValueSet) obj;
+                    return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack);
+                } else {
+                    return false;
+                }
+            }
+
+            @Override
+            public int hashCode() {
+                throw new UnsupportedOperationException();
+            }
+
+            public void addLiveValues(ReferenceMap refMap) {
+                registers.addLiveValues(refMap);
+                stack.addLiveValues(refMap);
+                if (extraStack != null) {
+                    for (Value v : extraStack) {
+                        refMap.addLiveValue(v);
+                    }
+                }
+            }
+        }
+
         private final LIR lir;
         private final FrameMap frameMap;
         private final RegisterAttributes[] registerAttributes;
@@ -181,9 +334,9 @@
         /**
          * Merge outSet with in-set of successors.
          */
-        private boolean updateOutBlock(AbstractBlockBase<?> block) {
+        private boolean updateOutBlock(AbstractBlockBase<T> block) {
             LiveValueSet union = new LiveValueSet();
-            block.getSuccessors().forEach(succ -> union.putAll(liveInMap.get(succ)));
+            block.getSuccessors().forEach(union);
             LiveValueSet outSet = liveOutMap.get(block);
             // check if changed
             if (outSet == null || !union.equals(outSet)) {
@@ -196,13 +349,14 @@
         private void processBlock(AbstractBlockBase<T> block, UniqueWorkList<T> worklist) {
             if (updateOutBlock(block)) {
                 try (Indent indent = Debug.logAndIndent("handle block %s", block)) {
-                    BlockClosure closure = new BlockClosure(new LiveValueSet(liveOutMap.get(block)));
+                    currentSet = new LiveValueSet(liveOutMap.get(block));
                     List<LIRInstruction> instructions = lir.getLIRforBlock(block);
                     for (int i = instructions.size() - 1; i >= 0; i--) {
                         LIRInstruction inst = instructions.get(i);
-                        closure.processInstructionBottomUp(inst);
+                        processInstructionBottomUp(inst);
                     }
-                    liveInMap.put(block, closure.getCurrentSet());
+                    liveInMap.put(block, currentSet);
+                    currentSet = null;
                     worklist.addAll(block.getPredecessors());
                 }
             }
@@ -211,78 +365,68 @@
         private static final EnumSet<OperandFlag> REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG);
         private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object);
 
-        private final class BlockClosure {
-            private final LiveValueSet currentSet;
+        private LiveValueSet currentSet;
 
-            private BlockClosure(LiveValueSet set) {
-                currentSet = set;
-            }
+        /**
+         * Process all values of an instruction bottom-up, i.e. definitions before usages. Values
+         * that start or end at the current operation are not included.
+         */
+        private void processInstructionBottomUp(LIRInstruction op) {
+            try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) {
+                // kills
 
-            private LiveValueSet getCurrentSet() {
-                return currentSet;
-            }
+                op.visitEachTemp(defConsumer);
+                op.visitEachOutput(defConsumer);
+                if (op.destroysCallerSavedRegisters()) {
+                    for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
+                        defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET);
+                    }
+                }
 
-            /**
-             * Process all values of an instruction bottom-up, i.e. definitions before usages.
-             * Values that start or end at the current operation are not included.
-             */
-            private void processInstructionBottomUp(LIRInstruction op) {
-                try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) {
-                    // kills
+                // gen - values that are considered alive for this state
+                op.visitEachAlive(useConsumer);
+                op.visitEachState(useConsumer);
+                // mark locations
+                op.forEachState(stateConsumer);
+                // gen
+                op.visitEachInput(useConsumer);
+            }
+        }
 
-                    op.visitEachTemp(defConsumer);
-                    op.visitEachOutput(defConsumer);
-                    if (op.destroysCallerSavedRegisters()) {
-                        for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
-                            defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET);
-                        }
-                    }
+        InstructionStateProcedure stateConsumer = new InstructionStateProcedure() {
+            public void doState(LIRInstruction inst, LIRFrameState info) {
+                markLocation(inst, info, currentSet);
+            }
+        };
 
-                    // gen - values that are considered alive for this state
-                    op.visitEachAlive(useConsumer);
-                    op.visitEachState(useConsumer);
-                    // mark locations
-                    op.forEachState(stateConsumer);
-                    // gen
-                    op.visitEachInput(useConsumer);
+        ValueConsumer useConsumer = new ValueConsumer() {
+            public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (shouldProcessValue(operand)) {
+                    // no need to insert values and derived reference
+                    if (Debug.isLogEnabled()) {
+                        Debug.log("set operand: %s", operand);
+                    }
+                    currentSet.put(operand);
                 }
             }
-
-            InstructionStateProcedure stateConsumer = new InstructionStateProcedure() {
-                public void doState(LIRInstruction inst, LIRFrameState info) {
-                    markLocation(inst, info, getCurrentSet());
-                }
-            };
+        };
 
-            ValueConsumer useConsumer = new ValueConsumer() {
-                public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                    if (shouldProcessValue(operand)) {
-                        // no need to insert values and derived reference
-                        if (Debug.isLogEnabled()) {
-                            Debug.log("set operand: %s", operand);
-                        }
-                        currentSet.put(operand);
+        ValueConsumer defConsumer = new ValueConsumer() {
+            public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (shouldProcessValue(operand)) {
+                    if (Debug.isLogEnabled()) {
+                        Debug.log("clear operand: %s", operand);
                     }
+                    currentSet.remove(operand);
+                } else {
+                    assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s",
+                                    operand, mode);
                 }
-            };
+            }
+        };
 
-            ValueConsumer defConsumer = new ValueConsumer() {
-                public void visitValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                    if (shouldProcessValue(operand)) {
-                        if (Debug.isLogEnabled()) {
-                            Debug.log("clear operand: %s", operand);
-                        }
-                        currentSet.remove(operand);
-                    } else {
-                        assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format(
-                                        "Illegal PlatformKind is only allowed for TEMP mode: %s, %s", operand, mode);
-                    }
-                }
-            };
-
-            protected boolean shouldProcessValue(Value operand) {
-                return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal;
-            }
+        protected boolean shouldProcessValue(Value operand) {
+            return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal;
         }
 
         /**
@@ -294,9 +438,10 @@
             }
 
             ReferenceMap refMap = info.debugInfo().getReferenceMap();
-            for (Value v : values) {
-                frameMap.setReference(v, refMap);
-            }
+            refMap.reset();
+            frameMap.addLiveValues(refMap);
+            values.addLiveValues(refMap);
+            refMap.finish();
         }
 
         /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java	Fri Jun 05 17:12:08 2015 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.lir.framemap;
 
-import static com.oracle.jvmci.code.ValueUtil.*;
-
 import java.util.*;
 
 import com.oracle.graal.asm.*;
@@ -103,6 +101,12 @@
         return target;
     }
 
+    public void addLiveValues(ReferenceMap refMap) {
+        for (Value value : objectStackSlots) {
+            refMap.addLiveValue(value);
+        }
+    }
+
     protected int returnAddressSize() {
         return getTarget().arch.getReturnAddressSize();
     }
@@ -322,29 +326,6 @@
 
     public ReferenceMap initReferenceMap(boolean hasRegisters) {
         ReferenceMap refMap = getTarget().createReferenceMap(hasRegisters, frameSize() / getTarget().wordSize);
-        for (StackSlot slot : objectStackSlots) {
-            setReference(slot, refMap);
-        }
         return refMap;
     }
-
-    /**
-     * Marks the specified location as a reference in the reference map of the debug information.
-     * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a
-     * {@link JavaConstant} is automatically tracked.
-     *
-     * @param location The location to be added to the reference map.
-     * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}.
-     */
-    public void setReference(Value location, ReferenceMap refMap) {
-        LIRKind kind = location.getLIRKind();
-        if (isRegister(location)) {
-            refMap.setRegister(asRegister(location).getReferenceMapIndex(), kind);
-        } else if (isStackSlot(location)) {
-            int offset = offsetForStackSlot(asStackSlot(location));
-            refMap.setStackSlot(offset, kind);
-        } else {
-            assert isConstant(location);
-        }
-    }
 }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Jun 05 17:12:08 2015 +0200
@@ -459,9 +459,9 @@
                 inst.forEachState(state -> {
                     if (state.hasDebugInfo()) {
                         DebugInfo di = state.debugInfo();
-                        stateString.append(debugInfoToString(di.getBytecodePosition(), di.getReferenceMap(), di.getCalleeSaveInfo(), target.arch));
+                        stateString.append(debugInfoToString(di.getBytecodePosition(), di.getReferenceMap(), di.getCalleeSaveInfo()));
                     } else {
-                        stateString.append(debugInfoToString(state.topFrame, null, null, target.arch));
+                        stateString.append(debugInfoToString(state.topFrame, null, null));
                     }
                 });
                 if (stateString.length() > 0) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Fri Jun 05 17:12:08 2015 +0200
@@ -23,10 +23,10 @@
 package com.oracle.graal.printer;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import com.oracle.graal.code.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
@@ -37,15 +37,10 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.jvmci.code.*;
-import com.oracle.jvmci.code.CodeUtil.DefaultRefMapFormatter;
-import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
-import com.oracle.jvmci.code.CompilationResult.Call;
-import com.oracle.jvmci.code.CompilationResult.DataPatch;
-import com.oracle.jvmci.code.CompilationResult.Infopoint;
-import com.oracle.jvmci.code.CompilationResult.Mark;
 import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.debug.*;
 import com.oracle.jvmci.meta.*;
+import com.oracle.jvmci.service.*;
 
 /**
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the
@@ -201,99 +196,35 @@
 
     }
 
-    /**
-     * Returns a disassembly of some compiled code.
-     *
-     * @param compResult some compiled code
-     * @param installedCode the result of installing the code in {@code compResult} or null if the
-     *            code has not yet been installed
-     */
-    private static String disassemble(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) {
-        TargetDescription target = codeCache.getTarget();
-        RegisterConfig regConfig = codeCache.getRegisterConfig();
-        byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode();
-        if (code == null) {
-            // Method was deoptimized/invalidated
-            return "";
+    private static DisassemblerProvider disassembler;
+
+    private static final DisassemblerProvider NOP_DISASSEMBLER = new DisassemblerProvider() {
+        public String getName() {
+            return null;
         }
-        long start = installedCode == null ? 0L : installedCode.getStart();
-        HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
-        if (compResult != null) {
-            HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
-            addExceptionHandlersComment(compResult, hcf);
-            Register fp = regConfig.getFrameRegister();
-            RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0);
-            for (Infopoint infopoint : compResult.getInfopoints()) {
-                if (infopoint instanceof Call) {
-                    Call call = (Call) infopoint;
-                    if (call.debugInfo != null) {
-                        hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString());
-                    }
-                    addOperandComment(hcf, call.pcOffset, "{" + codeCache.getTargetName(call) + "}");
-                } else {
-                    if (infopoint.debugInfo != null) {
-                        hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString());
-                    }
-                    addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}");
+    };
+
+    private static DisassemblerProvider getDisassembler() {
+        if (disassembler == null) {
+            DisassemblerProvider selected = NOP_DISASSEMBLER;
+            for (DisassemblerProvider d : Services.load(DisassemblerProvider.class)) {
+                String name = d.getName().toLowerCase();
+                if (name.contains("hcf") || name.contains("hexcodefile")) {
+                    selected = d;
+                    break;
                 }
             }
-            for (DataPatch site : compResult.getDataPatches()) {
-                hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}");
-            }
-            for (Mark mark : compResult.getMarks()) {
-                hcf.addComment(mark.pcOffset, codeCache.getMarkName(mark));
-            }
+            disassembler = selected;
         }
-        String hcfEmbeddedString = hcf.toEmbeddedString();
-        return HexCodeFileDisTool.tryDisassemble(hcfEmbeddedString);
+        return disassembler;
     }
 
-    /**
-     * Interface to the tool for disassembling an {@link HexCodeFile#toEmbeddedString() embedded}
-     * {@link HexCodeFile}.
-     */
-    static class HexCodeFileDisTool {
-        static final Method processMethod;
-        static {
-            Method toolMethod = null;
-            try {
-                Class<?> toolClass = Class.forName("com.oracle.max.hcfdis.HexCodeFileDis", true, ClassLoader.getSystemClassLoader());
-                toolMethod = toolClass.getDeclaredMethod("processEmbeddedString", String.class);
-            } catch (Exception e) {
-                // Tool not available on the class path
-            }
-            processMethod = toolMethod;
+    private static String disassemble(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) {
+        DisassemblerProvider dis = getDisassembler();
+        if (installedCode != null) {
+            return dis.disassembleInstalledCode(codeCache, compResult, installedCode);
         }
-
-        public static String tryDisassemble(String hcfEmbeddedString) {
-            if (processMethod != null) {
-                try {
-                    return (String) processMethod.invoke(null, hcfEmbeddedString);
-                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-                    // If the tool is available, for now let's be noisy when it fails
-                    throw new JVMCIError(e);
-                }
-            }
-            return hcfEmbeddedString;
-        }
-    }
-
-    private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) {
-        if (!compResult.getExceptionHandlers().isEmpty()) {
-            String nl = HexCodeFile.NEW_LINE;
-            StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl);
-            for (CompilationResult.ExceptionHandler e : compResult.getExceptionHandlers()) {
-                buf.append("    ").append(e.pcOffset).append(" -> ").append(e.handlerPos).append(nl);
-                hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]");
-                hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]");
-            }
-            hcf.addComment(0, buf.toString());
-        }
-    }
-
-    private static void addOperandComment(HexCodeFile hcf, int pos, String comment) {
-        String oldValue = hcf.addOperandComment(pos, comment);
-        assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue;
+        return dis.disassembleCompiledCode(codeCache, compResult);
     }
 
     private static boolean isCompilationResultAndInstalledCode(Object object) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Fri Jun 05 17:12:08 2015 +0200
@@ -22,22 +22,12 @@
  */
 package com.oracle.graal.printer;
 
-import com.oracle.jvmci.code.Architecture;
-import com.oracle.jvmci.code.VirtualObject;
-import com.oracle.jvmci.code.BytecodePosition;
-import com.oracle.jvmci.code.BytecodeFrame;
-import com.oracle.jvmci.code.Register;
-import com.oracle.jvmci.code.CodeUtil;
-import com.oracle.jvmci.code.RegisterSaveLayout;
-import com.oracle.jvmci.code.ReferenceMap;
-import com.oracle.jvmci.meta.MetaUtil;
-import com.oracle.jvmci.meta.Value;
-import com.oracle.jvmci.meta.JavaMethod;
 import java.io.*;
 import java.util.*;
 
-import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
+import com.oracle.jvmci.code.*;
 import com.oracle.jvmci.debug.*;
+import com.oracle.jvmci.meta.*;
 
 /**
  * Utility for printing compilation related data structures at various compilation phases. The
@@ -122,19 +112,10 @@
     /**
      * Formats given debug info as a multi line string.
      */
-    protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) {
+    protected String debugInfoToString(BytecodePosition codePos, ReferenceMap refMap, RegisterSaveLayout calleeSaveInfo) {
         StringBuilder sb = new StringBuilder();
-        RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter();
-
-        if (refMap != null && refMap.hasRegisterRefMap()) {
-            sb.append("reg-ref-map:");
-            refMap.appendRegisterMap(sb, arch != null ? new CodeUtil.DefaultRegFormatter(arch) : formatter);
-            sb.append("\n");
-        }
-
-        if (refMap != null && refMap.hasFrameRefMap()) {
-            sb.append("frame-ref-map:");
-            refMap.appendFrameMap(sb, formatter);
+        if (refMap != null) {
+            sb.append(refMap.toString());
             sb.append("\n");
         }
 
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/HexCodeFile.java	Fri Jun 05 17:11:50 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.printer;
-
-import java.io.*;
-import java.util.*;
-import java.util.regex.*;
-
-import com.oracle.jvmci.code.*;
-import com.oracle.jvmci.code.CompilationResult.CodeAnnotation;
-import com.oracle.jvmci.code.CompilationResult.CodeComment;
-import com.oracle.jvmci.code.CompilationResult.JumpTable;
-
-/**
- * A HexCodeFile is a textual format for representing a chunk of machine code along with extra
- * information that can be used to enhance a disassembly of the code.
- *
- * A pseudo grammar for a HexCodeFile is given below.
- *
- * <pre>
- *     HexCodeFile ::= Platform Delim HexCode Delim (OptionalSection Delim)*
- *
- *     OptionalSection ::= Comment | OperandComment | JumpTable | LookupTable
- *
- *     Platform ::= "Platform" ISA WordWidth
- *
- *     HexCode ::= "HexCode" StartAddress HexDigits
- *
- *     Comment ::= "Comment" Position String
- *
- *     OperandComment ::= "OperandComment" Position String
- *
- *     JumpTable ::= "JumpTable" Position EntrySize Low High
- *
- *     LookupTable ::= "LookupTable" Position NPairs KeySize OffsetSize
- *
- *     Position, EntrySize, Low, High, NPairs KeySize OffsetSize ::= int
- *
- *     Delim := "&lt;||@"
- * </pre>
- *
- * There must be exactly one HexCode and Platform part in a HexCodeFile. The length of HexDigits
- * must be even as each pair of digits represents a single byte.
- * <p>
- * Below is an example of a valid Code input:
- *
- * <pre>
- *
- *  Platform AMD64 64  &lt;||@
- *  HexCode 0 e8000000009090904883ec084889842410d0ffff48893c24e800000000488b3c24488bf0e8000000004883c408c3  &lt;||@
- *  Comment 24 frame-ref-map: +0 {0}
- *  at java.lang.String.toLowerCase(String.java:2496) [bci: 1]
- *              |0
- *     locals:  |stack:0:a
- *     stack:   |stack:0:a
- *    &lt;||@
- *  OperandComment 24 {java.util.Locale.getDefault()}  &lt;||@
- *  Comment 36 frame-ref-map: +0 {0}
- *  at java.lang.String.toLowerCase(String.java:2496) [bci: 4]
- *              |0
- *     locals:  |stack:0:a
- *    &lt;||@
- *  OperandComment 36 {java.lang.String.toLowerCase(Locale)}  lt;||@
- *
- * </pre>
- */
-public class HexCodeFile {
-
-    public static final String NEW_LINE = CodeUtil.NEW_LINE;
-    public static final String SECTION_DELIM = " <||@";
-    public static final String COLUMN_END = " <|@";
-    public static final Pattern SECTION = Pattern.compile("(\\S+)\\s+(.*)", Pattern.DOTALL);
-    public static final Pattern COMMENT = Pattern.compile("(\\d+)\\s+(.*)", Pattern.DOTALL);
-    public static final Pattern OPERAND_COMMENT = COMMENT;
-    public static final Pattern JUMP_TABLE = Pattern.compile("(\\d+)\\s+(\\d+)\\s+(-{0,1}\\d+)\\s+(-{0,1}\\d+)\\s*");
-    public static final Pattern LOOKUP_TABLE = Pattern.compile("(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s*");
-    public static final Pattern HEX_CODE = Pattern.compile("(\\p{XDigit}+)(?:\\s+(\\p{XDigit}*))?");
-    public static final Pattern PLATFORM = Pattern.compile("(\\S+)\\s+(\\S+)", Pattern.DOTALL);
-
-    /**
-     * Delimiter placed before a HexCodeFile when embedded in a string/stream.
-     */
-    public static final String EMBEDDED_HCF_OPEN = "<<<HexCodeFile";
-
-    /**
-     * Delimiter placed after a HexCodeFile when embedded in a string/stream.
-     */
-    public static final String EMBEDDED_HCF_CLOSE = "HexCodeFile>>>";
-
-    /**
-     * Map from a machine code position to a list of comments for the position.
-     */
-    public final Map<Integer, List<String>> comments = new TreeMap<>();
-
-    /**
-     * Map from a machine code position to a comment for the operands of the instruction at the
-     * position.
-     */
-    public final Map<Integer, String> operandComments = new TreeMap<>();
-
-    public final byte[] code;
-
-    public final ArrayList<JumpTable> jumpTables = new ArrayList<>();
-
-    public final String isa;
-
-    public final int wordWidth;
-
-    public final long startAddress;
-
-    public HexCodeFile(byte[] code, long startAddress, String isa, int wordWidth) {
-        this.code = code;
-        this.startAddress = startAddress;
-        this.isa = isa;
-        this.wordWidth = wordWidth;
-    }
-
-    /**
-     * Parses a string in the format produced by {@link #toString()} to produce a
-     * {@link HexCodeFile} object.
-     */
-    public static HexCodeFile parse(String input, int sourceOffset, String source, String sourceName) {
-        return new Parser(input, sourceOffset, source, sourceName).hcf;
-    }
-
-    /**
-     * Formats this HexCodeFile as a string that can be parsed with
-     * {@link #parse(String, int, String, String)}.
-     */
-    @Override
-    public String toString() {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        writeTo(baos);
-        return baos.toString();
-    }
-
-    public String toEmbeddedString() {
-        return EMBEDDED_HCF_OPEN + NEW_LINE + toString() + EMBEDDED_HCF_CLOSE;
-    }
-
-    public void writeTo(OutputStream out) {
-        PrintStream ps = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
-        ps.printf("Platform %s %d %s%n", isa, wordWidth, SECTION_DELIM);
-        ps.printf("HexCode %x %s %s%n", startAddress, HexCodeFile.hexCodeString(code), SECTION_DELIM);
-
-        for (JumpTable table : jumpTables) {
-            ps.printf("JumpTable %d %d %d %d %s%n", table.position, table.entrySize, table.low, table.high, SECTION_DELIM);
-        }
-
-        for (Map.Entry<Integer, List<String>> e : comments.entrySet()) {
-            int pos = e.getKey();
-            for (String comment : e.getValue()) {
-                ps.printf("Comment %d %s %s%n", pos, comment, SECTION_DELIM);
-            }
-        }
-
-        for (Map.Entry<Integer, String> e : operandComments.entrySet()) {
-            ps.printf("OperandComment %d %s %s%n", e.getKey(), e.getValue(), SECTION_DELIM);
-        }
-        ps.flush();
-    }
-
-    /**
-     * Formats a byte array as a string of hex digits.
-     */
-    public static String hexCodeString(byte[] code) {
-        if (code == null) {
-            return "";
-        } else {
-            StringBuilder sb = new StringBuilder(code.length * 2);
-            for (int b : code) {
-                String hex = Integer.toHexString(b & 0xff);
-                if (hex.length() == 1) {
-                    sb.append('0');
-                }
-                sb.append(hex);
-            }
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Adds a comment to the list of comments for a given position.
-     */
-    public void addComment(int pos, String comment) {
-        List<String> list = comments.get(pos);
-        if (list == null) {
-            list = new ArrayList<>();
-            comments.put(pos, list);
-        }
-        list.add(encodeString(comment));
-    }
-
-    /**
-     * Sets an operand comment for a given position.
-     *
-     * @return the previous operand comment for {@code pos}
-     */
-    public String addOperandComment(int pos, String comment) {
-        return operandComments.put(pos, encodeString(comment));
-    }
-
-    /**
-     * Adds any jump tables, lookup tables or code comments from a list of code annotations.
-     */
-    public static void addAnnotations(HexCodeFile hcf, List<CodeAnnotation> annotations) {
-        if (annotations == null || annotations.isEmpty()) {
-            return;
-        }
-        for (CodeAnnotation a : annotations) {
-            if (a instanceof JumpTable) {
-                JumpTable table = (JumpTable) a;
-                hcf.jumpTables.add(table);
-            } else if (a instanceof CodeComment) {
-                CodeComment comment = (CodeComment) a;
-                hcf.addComment(comment.position, comment.value);
-            }
-        }
-    }
-
-    /**
-     * Modifies a string to mangle any substrings matching {@link #SECTION_DELIM} and
-     * {@link #COLUMN_END}.
-     */
-    public static String encodeString(String input) {
-        int index;
-        String s = input;
-        while ((index = s.indexOf(SECTION_DELIM)) != -1) {
-            s = s.substring(0, index) + " < |@" + s.substring(index + SECTION_DELIM.length());
-        }
-        while ((index = s.indexOf(COLUMN_END)) != -1) {
-            s = s.substring(0, index) + " < @" + s.substring(index + COLUMN_END.length());
-        }
-        return s;
-    }
-
-    /**
-     * Helper class to parse a string in the format produced by {@link HexCodeFile#toString()} and
-     * produce a {@link HexCodeFile} object.
-     */
-    static class Parser {
-
-        final String input;
-        final String inputSource;
-        String isa;
-        int wordWidth;
-        byte[] code;
-        long startAddress;
-        HexCodeFile hcf;
-
-        Parser(String input, int sourceOffset, String source, String sourceName) {
-            this.input = input;
-            this.inputSource = sourceName;
-            parseSections(sourceOffset, source);
-        }
-
-        void makeHCF() {
-            if (hcf == null) {
-                if (isa != null && wordWidth != 0 && code != null) {
-                    hcf = new HexCodeFile(code, startAddress, isa, wordWidth);
-                }
-            }
-        }
-
-        void checkHCF(String section, int offset) {
-            check(hcf != null, offset, section + " section must be after Platform and HexCode section");
-        }
-
-        void check(boolean condition, int offset, String message) {
-            if (!condition) {
-                error(offset, message);
-            }
-        }
-
-        Error error(int offset, String message) {
-            throw new Error(errorMessage(offset, message));
-        }
-
-        void warning(int offset, String message) {
-            PrintStream err = System.err;
-            err.println("Warning: " + errorMessage(offset, message));
-        }
-
-        String errorMessage(int offset, String message) {
-            assert offset < input.length();
-            InputPos inputPos = filePos(offset);
-            int lineEnd = input.indexOf(HexCodeFile.NEW_LINE, offset);
-            int lineStart = offset - inputPos.col;
-            String line = lineEnd == -1 ? input.substring(lineStart) : input.substring(lineStart, lineEnd);
-            return String.format("%s:%d: %s%n%s%n%" + (inputPos.col + 1) + "s", inputSource, inputPos.line, message, line, "^");
-        }
-
-        static class InputPos {
-
-            final int line;
-            final int col;
-
-            public InputPos(int line, int col) {
-                this.line = line;
-                this.col = col;
-            }
-        }
-
-        InputPos filePos(int index) {
-            assert input != null;
-            int lineStart = input.lastIndexOf(HexCodeFile.NEW_LINE, index) + 1;
-
-            String l = input.substring(lineStart, lineStart + 10);
-            PrintStream out = System.out;
-            out.println("YYY" + input.substring(index, index + 10) + "...");
-            out.println("XXX" + l + "...");
-
-            int pos = input.indexOf(HexCodeFile.NEW_LINE, 0);
-            int line = 1;
-            while (pos > 0 && pos < index) {
-                line++;
-                pos = input.indexOf(HexCodeFile.NEW_LINE, pos + 1);
-            }
-            return new InputPos(line, index - lineStart);
-        }
-
-        void parseSections(int offset, String source) {
-            assert input.startsWith(source, offset);
-            int index = 0;
-            int endIndex = source.indexOf(SECTION_DELIM);
-            while (endIndex != -1) {
-                while (source.charAt(index) <= ' ') {
-                    index++;
-                }
-                String section = source.substring(index, endIndex).trim();
-                parseSection(offset + index, section);
-                index = endIndex + SECTION_DELIM.length();
-                endIndex = source.indexOf(SECTION_DELIM, index);
-            }
-        }
-
-        int parseInt(int offset, String value) {
-            try {
-                return Integer.parseInt(value);
-            } catch (NumberFormatException e) {
-                throw error(offset, "Not a valid integer: " + value);
-            }
-        }
-
-        void parseSection(int offset, String section) {
-            if (section.isEmpty()) {
-                return;
-            }
-            assert input.startsWith(section, offset);
-            Matcher m = HexCodeFile.SECTION.matcher(section);
-            check(m.matches(), offset, "Section does not match pattern " + HexCodeFile.SECTION);
-
-            String header = m.group(1);
-            String body = m.group(2);
-            int headerOffset = offset + m.start(1);
-            int bodyOffset = offset + m.start(2);
-
-            if (header.equals("Platform")) {
-                check(isa == null, bodyOffset, "Duplicate Platform section found");
-                m = HexCodeFile.PLATFORM.matcher(body);
-                check(m.matches(), bodyOffset, "Platform does not match pattern " + HexCodeFile.PLATFORM);
-                isa = m.group(1);
-                wordWidth = parseInt(bodyOffset + m.start(2), m.group(2));
-                makeHCF();
-            } else if (header.equals("HexCode")) {
-                check(code == null, bodyOffset, "Duplicate Code section found");
-                m = HexCodeFile.HEX_CODE.matcher(body);
-                check(m.matches(), bodyOffset, "Code does not match pattern " + HexCodeFile.HEX_CODE);
-                String hexAddress = m.group(1);
-                startAddress = Long.valueOf(hexAddress, 16);
-                String hexCode = m.group(2);
-                if (hexCode == null) {
-                    code = new byte[0];
-                } else {
-                    check((hexCode.length() % 2) == 0, bodyOffset, "Hex code length must be even");
-                    code = new byte[hexCode.length() / 2];
-                    for (int i = 0; i < code.length; i++) {
-                        String hexByte = hexCode.substring(i * 2, (i + 1) * 2);
-                        code[i] = (byte) Integer.parseInt(hexByte, 16);
-                    }
-                }
-                makeHCF();
-            } else if (header.equals("Comment")) {
-                checkHCF("Comment", headerOffset);
-                m = HexCodeFile.COMMENT.matcher(body);
-                check(m.matches(), bodyOffset, "Comment does not match pattern " + HexCodeFile.COMMENT);
-                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
-                String comment = m.group(2);
-                hcf.addComment(pos, comment);
-            } else if (header.equals("OperandComment")) {
-                checkHCF("OperandComment", headerOffset);
-                m = HexCodeFile.OPERAND_COMMENT.matcher(body);
-                check(m.matches(), bodyOffset, "OperandComment does not match pattern " + HexCodeFile.OPERAND_COMMENT);
-                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
-                String comment = m.group(2);
-                hcf.addOperandComment(pos, comment);
-            } else if (header.equals("JumpTable")) {
-                checkHCF("JumpTable", headerOffset);
-                m = HexCodeFile.JUMP_TABLE.matcher(body);
-                check(m.matches(), bodyOffset, "JumpTable does not match pattern " + HexCodeFile.JUMP_TABLE);
-                int pos = parseInt(bodyOffset + m.start(1), m.group(1));
-                int entrySize = parseInt(bodyOffset + m.start(2), m.group(2));
-                int low = parseInt(bodyOffset + m.start(3), m.group(3));
-                int high = parseInt(bodyOffset + m.start(4), m.group(4));
-                hcf.jumpTables.add(new JumpTable(pos, low, high, entrySize));
-            } else {
-                error(offset, "Unknown section header: " + header);
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/LoopNodeFactory.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/LoopNodeFactory.java	Fri Jun 05 17:12:08 2015 +0200
@@ -22,9 +22,10 @@
  */
 package com.oracle.graal.truffle;
 
+import com.oracle.jvmci.service.*;
 import com.oracle.truffle.api.nodes.*;
 
-public interface LoopNodeFactory extends PrioritizedServiceProvider {
+public interface LoopNodeFactory extends PrioritizedServiceProvider, Service {
 
     LoopNode create(RepeatingNode repeatingNode);
 
--- a/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CodeUtil.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CodeUtil.java	Fri Jun 05 17:12:08 2015 +0200
@@ -429,15 +429,8 @@
         }
         String nl = NEW_LINE;
         ReferenceMap refMap = info.getReferenceMap();
-        if (refMap != null && refMap.hasRegisterRefMap()) {
-            sb.append("  reg-ref-map:");
-            refMap.appendRegisterMap(sb, formatter);
-            sb.append(nl);
-        }
-        if (refMap != null && refMap.hasFrameRefMap()) {
-            sb.append("frame-ref-map:");
-            refMap.appendFrameMap(sb, formatter);
-            sb.append(nl);
+        if (refMap != null) {
+            sb.append(refMap.toString());
         }
         RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
         if (calleeSaveInfo != null) {
--- a/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CompilationResult.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CompilationResult.java	Fri Jun 05 17:12:08 2015 +0200
@@ -27,7 +27,6 @@
 
 import java.util.*;
 
-import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
 import com.oracle.jvmci.meta.Assumptions.Assumption;
 import com.oracle.jvmci.meta.*;
 
@@ -858,17 +857,8 @@
         if (info != null) {
             ReferenceMap refMap = info.getReferenceMap();
             if (refMap != null) {
-                RefMapFormatter formatter = new CodeUtil.NumberedRefMapFormatter();
-                if (refMap.hasFrameRefMap()) {
-                    sb.append(" stackMap[");
-                    refMap.appendFrameMap(sb, formatter);
-                    sb.append(']');
-                }
-                if (refMap.hasRegisterRefMap()) {
-                    sb.append(" registerMap[");
-                    refMap.appendRegisterMap(sb, formatter);
-                    sb.append(']');
-                }
+                sb.append(refMap.toString());
+                sb.append(']');
             }
             RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
             if (calleeSaveInfo != null) {
--- a/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/DisassemblerProvider.java	Fri Jun 05 17:11:50 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +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.jvmci.code;
-
-/**
- * Interface providing capability for disassembling machine code.
- */
-public interface DisassemblerProvider {
-
-    /**
-     * Gets a textual disassembly of some given installed code.
-     *
-     * @return a non-zero length string containing a disassembly of {@code code} or null if
-     *         {@code code} is {@link InstalledCode#isValid() invalid} or it could not be
-     *         disassembled for some other reason
-     */
-    String disassemble(InstalledCode code);
-}
--- a/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/ReferenceMap.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/ReferenceMap.java	Fri Jun 05 17:12:08 2015 +0200
@@ -22,20 +22,24 @@
  */
 package com.oracle.jvmci.code;
 
-import com.oracle.jvmci.meta.LIRKind;
-import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
+import com.oracle.jvmci.meta.*;
+
+public abstract class ReferenceMap {
 
-public abstract class ReferenceMap implements Cloneable {
-
-    public abstract void setRegister(int idx, LIRKind kind);
-
-    public abstract void setStackSlot(int offset, LIRKind kind);
+    /**
+     * Empty out the reference map.
+     */
+    public abstract void reset();
 
-    public abstract boolean hasRegisterRefMap();
-
-    public abstract boolean hasFrameRefMap();
+    /**
+     * Add {@code value} to the current set of reference values.
+     *
+     * @param v
+     */
+    public abstract void addLiveValue(Value v);
 
-    public abstract void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg);
-
-    public abstract void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg);
+    /**
+     * Perform any final encoding needed before use.
+     */
+    public abstract void finish();
 }
--- a/graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotReferenceMap.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotReferenceMap.java	Fri Jun 05 17:12:08 2015 +0200
@@ -22,351 +22,60 @@
  */
 package com.oracle.jvmci.hotspot;
 
+import static com.oracle.jvmci.code.ValueUtil.*;
+
 import java.util.*;
 
-import com.oracle.jvmci.code.CodeUtil.RefMapFormatter;
 import com.oracle.jvmci.code.*;
-import com.oracle.jvmci.common.*;
 import com.oracle.jvmci.meta.*;
 
 public final class HotSpotReferenceMap extends ReferenceMap {
 
-    static final int OOP64 = 0b1010;
-    static final int OOP32 = 0b01;
-    static final int NARROW_LOW = OOP32;
-    static final int NARROW_HIGH = OOP32 << 2;
-    static final int NARROW_BOTH = NARROW_LOW | NARROW_HIGH;
+    private Value[] objects;
+    private int[] bytesPerElement;
+    private int maxRegisterSize;
+    private ArrayList<Value> objectValues;
 
-    private enum MapEntry {
-        NoReference(0),
-        WideOop(OOP64),
-        NarrowOopLowerHalf(NARROW_LOW),
-        NarrowOopUpperHalf(NARROW_HIGH),
-        TwoNarrowOops(NARROW_BOTH),
-        Illegal(-1);
+    private final TargetDescription target;
 
-        MapEntry(int pattern) {
-            this.pattern = pattern;
-        }
-
-        final int pattern;
+    public HotSpotReferenceMap(TargetDescription target) {
+        this.target = target;
+        this.objects = Value.NO_VALUES;
+    }
 
-        /**
-         * Create enum values from OopMap.
-         * <p>
-         * These bits can have the following values (MSB first):
-         *
-         * <pre>
-         * 0000 - contains no references
-         * 1010 - contains a wide oop
-         * 0001 - contains a narrow oop in the lower half
-         * 0101 - contains a narrow oop in the upper half
-         * 0101 - contains two narrow oops
-         * </pre>
-         *
-         * @see HotSpotReferenceMap#registerRefMap
-         * @see HotSpotReferenceMap#frameRefMap
-         */
-        static MapEntry getFromBits(int idx, HotSpotOopMap set) {
-            int n = set.get(idx);
-            switch (n) {
-                case 0:
-                    return NoReference;
-                case OOP64:
-                    return WideOop;
-                case NARROW_LOW:
-                    return NarrowOopLowerHalf;
-                case NARROW_HIGH:
-                    return NarrowOopUpperHalf;
-                case NARROW_BOTH:
-                    return TwoNarrowOops;
-                default:
-                    return Illegal;
+    @Override
+    public void reset() {
+        objectValues = new ArrayList<>();
+        objects = Value.NO_VALUES;
+        bytesPerElement = null;
+        maxRegisterSize = 0;
+    }
+
+    @Override
+    public void addLiveValue(Value v) {
+        if (isConstant(v)) {
+            return;
+        }
+        LIRKind lirKind = v.getLIRKind();
+        if (!lirKind.isValue()) {
+            objectValues.add(v);
+        }
+        if (isRegister(v)) {
+            int size = target.getSizeInBytes(lirKind.getPlatformKind());
+            if (size > maxRegisterSize) {
+                maxRegisterSize = size;
             }
         }
-
-        String toBitString() {
-            int bits = toBit(this);
-            if (bits == -1) {
-                return "---";
-            }
-            return String.format("%3s", Integer.toBinaryString(bits)).replace(' ', '0');
-        }
-
-        static int toBit(MapEntry type) {
-            return type.pattern;
-        }
     }
 
-    /**
-     * A specialized bit set that represents both wide and narrow oops in an efficient manner. The
-     * map consists of 4 bit entries that represent 8 bytes of memory.
-     *
-     */
-    class HotSpotOopMap implements Cloneable {
-
-        /**
-         * Each entry is 4 bits long and covers 8 bytes of memory.
-         */
-        private static final int BITS_PER_ENTRY = 4;
-        private static final int BITS_PER_ELEMENT = 64;
-
-        public HotSpotOopMap(int i) {
-            words = new long[(i * BITS_PER_ENTRY + BITS_PER_ELEMENT) / BITS_PER_ELEMENT];
-        }
-
-        public HotSpotOopMap(HotSpotOopMap other) {
-            words = other.words.clone();
-        }
-
-        private long[] words;
-
-        private int get(int i) {
-            return getEntry(i);
-        }
-
-        public void or(HotSpotOopMap src) {
-            if (words.length < src.words.length) {
-                long[] newWords = new long[src.words.length];
-                System.arraycopy(src.words, 0, newWords, 0, src.words.length);
-                for (int i = 0; i < words.length; i++) {
-                    newWords[i] |= words[i];
-                }
-                words = newWords;
-            } else {
-                for (int i = 0; i < src.words.length; i++) {
-                    words[i] |= src.words[i];
-                }
-            }
-        }
-
-        private void setOop(int regIdx) {
-            setEntry(regIdx, OOP64);
-        }
-
-        public int size() {
-            return words.length * BITS_PER_ELEMENT / BITS_PER_ENTRY;
-        }
-
-        @Override
-        public HotSpotOopMap clone() {
-            return new HotSpotOopMap(this);
-        }
-
-        private void setNarrowOop(int offset) {
-            setNarrowEntry(offset, OOP32);
-        }
-
-        private void setEntry(int regIdx, int value) {
-            assert regIdx % 2 == 0 : "must be alinged";
-            int bitIndex = (regIdx >> 1) * BITS_PER_ENTRY;
-            int wordIndex = bitIndex / BITS_PER_ELEMENT;
-            int shift = bitIndex - wordIndex * BITS_PER_ELEMENT;
-            if (wordIndex >= words.length) {
-                if (value == 0) {
-                    // Nothing to do since bits are clear
-                    return;
-                }
-                words = Arrays.copyOf(words, wordIndex + 1);
-            }
-            assert verifyUpdate(this, this);
-            long orig = words[wordIndex];
-            words[wordIndex] = (orig & (~(0b1111L << shift))) | ((long) value << shift);
-            assert get(regIdx / 2) == value;
-            assert verifyUpdate(this, this);
-        }
-
-        private void setNarrowEntry(int offset, int value) {
-            int regIdx = offset >> 1;
-            boolean low = offset % 2 == 0;
-            int bitIndex = regIdx * BITS_PER_ENTRY;
-            int wordIndex = bitIndex / BITS_PER_ELEMENT;
-            int shift = bitIndex - wordIndex * BITS_PER_ELEMENT;
-            if (wordIndex >= words.length) {
-                if (value == 0) {
-                    // Nothing to do since bits are clear
-                    return;
-                }
-                words = Arrays.copyOf(words, wordIndex + 1);
-            }
-            long originalValue = words[wordIndex];
-            int current = ((int) (originalValue >> shift)) & 0b1111;
-            if (current == OOP64) {
-                current = 0;
-            }
-            long newValue;
-            if (value != 0) {
-                newValue = current | (low ? value : (value << 2));
-            } else {
-                newValue = current & (low ? 0b1100 : 0b0011);
-            }
-            long masked = originalValue & (~(0b1111L << shift));
-            words[wordIndex] = masked | (newValue << shift);
-            assert verifyUpdate(this, this);
-        }
-
-        private int getEntry(int regIdx) {
-            int bitIndex = regIdx * BITS_PER_ENTRY;
-            int wordIndex = bitIndex / BITS_PER_ELEMENT;
-            int shift = bitIndex - wordIndex * BITS_PER_ELEMENT;
-            return ((int) (words[wordIndex] >>> shift)) & 0b1111;
+    @Override
+    public void finish() {
+        objects = objectValues.toArray(new Value[objectValues.size()]);
+        this.bytesPerElement = new int[objects.length];
+        for (int i = 0; i < objects.length; i++) {
+            bytesPerElement[i] = bytesPerElement(objects[i].getLIRKind());
         }
-
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) {
-                return true;
-            }
-
-            if (other instanceof HotSpotOopMap) {
-                HotSpotOopMap otherMap = (HotSpotOopMap) other;
-                int limit = Math.min(words.length, otherMap.words.length);
-                for (int i = 0; i < limit; i++) {
-                    if (words[i] != otherMap.words[i]) {
-                        return false;
-                    }
-                }
-                for (int i = limit; i < words.length; i++) {
-                    if (words[i] != 0) {
-                        return false;
-                    }
-                }
-                for (int i = limit; i < otherMap.words.length; i++) {
-                    if (otherMap.words[i] != 0) {
-                        return false;
-                    }
-                }
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            long h = 1234;
-            for (int i = words.length; --i >= 0;) {
-                h ^= words[i] * (i + 1);
-            }
-            return (int) ((h >> 32) ^ h);
-        }
-
-        @Override
-        public String toString() {
-            int count = 0;
-            StringBuilder sb = new StringBuilder();
-            sb.append("[");
-            for (int idx = 0; idx < size(); idx++) {
-                MapEntry dstType = MapEntry.getFromBits(idx, this);
-                if (dstType == MapEntry.NoReference) {
-                    continue;
-                }
-                if (count > 0) {
-                    sb.append(", ");
-                }
-                if (dstType == MapEntry.Illegal) {
-                    int value = get(idx);
-                    sb.append("0x");
-                    sb.append(Integer.toHexString(value));
-                } else {
-                    sb.append(idx);
-                    sb.append(':');
-                    sb.append(dstType);
-                }
-                count++;
-            }
-            sb.append("]");
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Contains 3 bits per scalar register, and n*3 bits per n-word vector register (e.g., on a
-     * 64-bit system, a 256-bit vector register requires 12 reference map bits).
-     * <p>
-     * These bits can have the following values (LSB first):
-     *
-     * <pre>
-     * 000 - contains no references
-     * 100 - contains a wide oop
-     * 110 - contains a narrow oop in the lower half
-     * 101 - contains a narrow oop in the upper half
-     * 111 - contains two narrow oops
-     * </pre>
-     */
-    private final HotSpotOopMap registerRefMap;
-
-    /**
-     * Contains 3 bits per stack word.
-     * <p>
-     * These bits can have the following values (LSB first):
-     *
-     * <pre>
-     * 000 - contains no references
-     * 100 - contains a wide oop
-     * 110 - contains a narrow oop in the lower half
-     * 101 - contains a narrow oop in the upper half
-     * 111 - contains two narrow oops
-     * </pre>
-     */
-    private final HotSpotOopMap frameRefMap;
-
-    private final TargetDescription target;
-
-    public HotSpotReferenceMap(int registerCount, int frameSlotCount, TargetDescription target) {
-        if (registerCount > 0) {
-            this.registerRefMap = new HotSpotOopMap(registerCount);
-        } else {
-            this.registerRefMap = null;
-        }
-        this.frameRefMap = new HotSpotOopMap(frameSlotCount);
-        this.target = target;
-    }
-
-    private HotSpotReferenceMap(HotSpotReferenceMap other) {
-        this.registerRefMap = other.registerRefMap.clone();
-        this.frameRefMap = other.frameRefMap.clone();
-        this.target = other.target;
-    }
-
-    @Override
-    public ReferenceMap clone() {
-        return new HotSpotReferenceMap(this);
-    }
-
-    // setters
-    @Override
-    public void setRegister(int idx, LIRKind kind) {
-        set(registerRefMap, idx * 2, kind);
-    }
-
-    @Override
-    public void setStackSlot(int offset, LIRKind kind) {
-        assert offset % bytesPerElement(kind) == 0 : "unaligned value in ReferenceMap";
-        set(frameRefMap, offset / 4, kind);
-    }
-
-    private void set(HotSpotOopMap refMap, int index, LIRKind kind) {
-        if (kind.isDerivedReference()) {
-            throw new JVMCIError("derived reference cannot be inserted in ReferenceMap");
-        }
-
-        int bytesPerElement = bytesPerElement(kind);
-        int length = kind.getPlatformKind().getVectorLength();
-        if (bytesPerElement == 8) {
-            for (int i = 0; i < length; i++) {
-                if (kind.isReference(i)) {
-                    refMap.setOop(index + i * 2);
-                }
-            }
-        } else if (bytesPerElement == 4) {
-            for (int i = 0; i < length; i++) {
-                if (kind.isReference(i)) {
-                    refMap.setNarrowOop(index + i);
-                }
-            }
-        } else {
-            assert kind.isValue() : "unknown reference kind " + kind;
-        }
+        objectValues = null;
     }
 
     private int bytesPerElement(LIRKind kind) {
@@ -374,74 +83,6 @@
         return target.getSizeInBytes(platformKind) / platformKind.getVectorLength();
     }
 
-    public HotSpotOopMap getFrameMap() {
-        return frameRefMap == null ? null : (HotSpotOopMap) frameRefMap.clone();
-    }
-
-    public HotSpotOopMap getRegisterMap() {
-        return registerRefMap == null ? null : (HotSpotOopMap) registerRefMap.clone();
-    }
-
-    static MapEntry[] entries(HotSpotOopMap fixedMap) {
-        MapEntry[] result = new MapEntry[fixedMap.size()];
-        for (int idx = 0; idx < fixedMap.size(); idx++) {
-            MapEntry dstType = MapEntry.getFromBits(idx, fixedMap);
-            result[idx] = dstType;
-        }
-        return result;
-    }
-
-    private static boolean verifyUpdate(HotSpotOopMap dst, HotSpotOopMap src) {
-        return verifyUpdate(dst, src, true);
-    }
-
-    private static boolean verifyUpdate(HotSpotOopMap dst, HotSpotOopMap src, boolean doAssert) {
-        for (int idx = 0; idx < Math.min(src.size(), dst.size()); idx++) {
-            if (!verifyUpdateEntry(idx, dst, src, doAssert)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static boolean verifyUpdateEntry(int idx, HotSpotOopMap dst, HotSpotOopMap src, boolean doAssert) {
-        MapEntry dstType = MapEntry.getFromBits(idx, dst);
-        MapEntry srcType = MapEntry.getFromBits(idx, src);
-
-        if (dstType == MapEntry.Illegal || srcType == MapEntry.Illegal) {
-            assert !doAssert : String.format("Illegal RefMap bit pattern: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString());
-            return false;
-        }
-        switch (dstType) {
-            case NoReference:
-                return true;
-            case WideOop:
-                switch (srcType) {
-                    case NoReference:
-                    case WideOop:
-                        return true;
-                    default:
-                        assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString());
-                        return false;
-                }
-            case TwoNarrowOops:
-            case NarrowOopLowerHalf:
-            case NarrowOopUpperHalf:
-                switch (srcType) {
-                    case TwoNarrowOops:
-                    case NarrowOopLowerHalf:
-                    case NarrowOopUpperHalf:
-                    case NoReference:
-                        return true;
-                    default:
-                        assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString());
-                        return false;
-                }
-            default:
-                return false;
-        }
-    }
-
     @Override
     public int hashCode() {
         throw new UnsupportedOperationException();
@@ -454,7 +95,7 @@
         }
         if (obj instanceof HotSpotReferenceMap) {
             HotSpotReferenceMap that = (HotSpotReferenceMap) obj;
-            if (this.frameRefMap.equals(that.frameRefMap) && Objects.equals(this.registerRefMap, that.registerRefMap) && this.target.equals(that.target)) {
+            if (Arrays.equals(objects, that.objects) && this.target.equals(that.target)) {
                 return true;
             }
         }
@@ -462,49 +103,7 @@
     }
 
     @Override
-    public boolean hasRegisterRefMap() {
-        return registerRefMap != null && registerRefMap.size() > 0;
-    }
-
-    @Override
-    public boolean hasFrameRefMap() {
-        return frameRefMap != null && frameRefMap.size() > 0;
-    }
-
-    @Override
-    public void appendRegisterMap(StringBuilder sb, RefMapFormatter formatter) {
-        for (int idx = 0; idx < registerRefMap.size(); idx++) {
-            MapEntry dstType = MapEntry.getFromBits(idx, registerRefMap);
-            if (dstType != MapEntry.NoReference) {
-                sb.append(' ').append(formatter.formatRegister(idx)).append(':').append(dstType);
-            }
-        }
-    }
-
-    @Override
-    public void appendFrameMap(StringBuilder sb, RefMapFormatter formatter) {
-        for (int idx = 0; idx < frameRefMap.size(); idx++) {
-            MapEntry dstType = MapEntry.getFromBits(idx, frameRefMap);
-            if (dstType != MapEntry.NoReference) {
-                sb.append(' ').append(formatter.formatStackSlot(idx)).append(':').append(dstType);
-            }
-        }
-    }
-
-    @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        if (registerRefMap != null) {
-            sb.append("Registers = ");
-            sb.append(registerRefMap);
-        }
-        sb.append("Stack = ");
-        sb.append(frameRefMap);
-        return sb.toString();
-    }
-
-    public void verify() {
-        assert verifyUpdate(frameRefMap, frameRefMap);
-        assert registerRefMap == null || verifyUpdate(registerRefMap, registerRefMap);
+        return Arrays.toString(objects);
     }
 }
--- a/graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotTargetDescription.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotTargetDescription.java	Fri Jun 05 17:12:08 2015 +0200
@@ -32,6 +32,6 @@
 
     @Override
     public ReferenceMap createReferenceMap(boolean hasRegisters, int stackSlotCount) {
-        return new HotSpotReferenceMap(hasRegisters ? arch.getRegisterReferenceMapSize() : 0, stackSlotCount, this);
+        return new HotSpotReferenceMap(this);
     }
 }
--- a/graal/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/Value.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/Value.java	Fri Jun 05 17:12:08 2015 +0200
@@ -28,7 +28,14 @@
  */
 public interface Value extends KindProvider, TrustedInterface {
 
-    AllocatableValue ILLEGAL = new AllocatableValue(LIRKind.Illegal) {
+    Value[] NO_VALUES = new Value[0];
+
+    AllocatableValue ILLEGAL = new IllegalValue();
+
+    public final class IllegalValue extends AllocatableValue {
+        private IllegalValue() {
+            super(LIRKind.Illegal);
+        }
 
         @Override
         public String toString() {
@@ -39,9 +46,9 @@
         public boolean equals(Object other) {
             // Due to de-serialization this object may exist multiple times. So we compare classes
             // instead of the individual objects. (This anonymous class has always the same meaning)
-            return other != null && this.getClass() == other.getClass();
+            return other instanceof IllegalValue;
         }
-    };
+    }
 
     LIRKind getLIRKind();
 
--- a/graal/com.oracle.jvmci.service.processor/src/com/oracle/jvmci/service/processor/ServiceProviderProcessor.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.jvmci.service.processor/src/com/oracle/jvmci/service/processor/ServiceProviderProcessor.java	Fri Jun 05 17:12:08 2015 +0200
@@ -38,6 +38,7 @@
 public class ServiceProviderProcessor extends AbstractProcessor {
 
     private final Set<TypeElement> processed = new HashSet<>();
+    private TypeElement baseJVMCIServiceInterface;
 
     @Override
     public SourceVersion getSupportedSourceVersion() {
@@ -45,6 +46,11 @@
     }
 
     private boolean verifyAnnotation(TypeMirror serviceInterface, TypeElement serviceProvider) {
+        if (!processingEnv.getTypeUtils().isSubtype(serviceInterface, baseJVMCIServiceInterface.asType())) {
+            String msg = String.format("Service interface class %s doesn't extend JVMCI service interface %s", serviceInterface, baseJVMCIServiceInterface);
+            processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
+            return false;
+        }
         if (!processingEnv.getTypeUtils().isSubtype(serviceProvider.asType(), serviceInterface)) {
             String msg = String.format("Service provider class %s doesn't implement service interface %s", serviceProvider.getSimpleName(), serviceInterface);
             processingEnv.getMessager().printMessage(Kind.ERROR, msg, serviceProvider);
@@ -101,6 +107,8 @@
             return true;
         }
 
+        baseJVMCIServiceInterface = processingEnv.getElementUtils().getTypeElement("com.oracle.jvmci.service.Service");
+
         for (Element element : roundEnv.getElementsAnnotatedWith(ServiceProvider.class)) {
             assert element.getKind().isClass();
             processElement((TypeElement) element);
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ShortCircuitTest.java	Fri Jun 05 17:12:08 2015 +0200
@@ -29,6 +29,7 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.DoubleChildNodeFactory;
+import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.ShortCircuitWithImplicitCastNodeFactory;
 import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.SingleChildNodeFactory;
 import com.oracle.truffle.api.dsl.test.ShortCircuitTestFactory.VarArgsNodeFactory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.ArgumentNode;
@@ -160,4 +161,38 @@
 
     }
 
+    @Test
+    public void testShortCircuitWithImplicitCastNode() {
+        ArgumentNode arg0 = new ArgumentNode(0);
+        ArgumentNode arg1 = new ArgumentNode(1);
+        CallTarget callTarget = TestHelper.createCallTarget(ShortCircuitWithImplicitCastNodeFactory.create(new ValueNode[]{arg0, arg1}));
+        assertEquals(42, callTarget.call(new Object[]{42, 41}));
+    }
+
+    @TypeSystem(int.class)
+    abstract static class ShortCircuitWithImplicitCastTypes {
+
+        @ImplicitCast
+        public static int doAnImplicitCast(String foo) {
+            return Integer.parseInt(foo);
+        }
+
+    }
+
+    @NodeChild(value = "children", type = ValueNode[].class)
+    @TypeSystemReference(ShortCircuitWithImplicitCastTypes.class)
+    abstract static class ShortCircuitWithImplicitCastNode extends ValueNode {
+
+        @ShortCircuit("children[1]")
+        public boolean needsRightNode(Object left) {
+            return (int) left == 41;
+        }
+
+        @Specialization
+        public int doInteger(int left, boolean needsRight, int right) {
+            return needsRight ? right : left;
+        }
+
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Fri Jun 05 17:11:50 2015 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.java	Fri Jun 05 17:12:08 2015 +0200
@@ -410,6 +410,11 @@
                 builder.end();
             }
 
+            builder.startElseIf().string(LOCAL_VALUE).string(" == ").nullLiteral().end();
+            builder.startBlock();
+            builder.startReturn().typeLiteral(context.getType(Object.class)).end();
+            builder.end();
+
             builder.startElseBlock();
             builder.tree(createTransferToInterpreterAndInvalidate());
             builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
--- a/make/Makefile	Fri Jun 05 17:11:50 2015 +0200
+++ b/make/Makefile	Fri Jun 05 17:12:08 2015 +0200
@@ -309,21 +309,25 @@
 			$(MAKE_ARGS) $(VM_TARGET) 
 
 
-
-ifeq (, $(shell python2.7 --version 2>/dev/null && echo ok))
-  ifeq (, $(shell python2.6 --version 2>/dev/null && echo ok))
-    PYTHON=python
+ifeq ($(JVMCI_USE_MAKE),)
+  ifeq (, $(shell python2.7 --version 2>/dev/null && echo ok))
+    ifeq (, $(shell python2.6 --version 2>/dev/null && echo ok))
+      PYTHON=python
+    else
+      PYTHON=python2.6
+    endif
   else
-    PYTHON=python2.6
+    PYTHON=python2.7
   endif
+  
+  # Builds code that can be shared among different build flavors
+buildshared:
+	$(PYTHON) -u $(GAMMADIR)/mxtool/mx.py build --no-native --export-dir $(SHARED_DIR)
 else
-  PYTHON=python2.7
+buildshared:
+	cd .. && $(MAKE) -f make/jvmci.make TARGET=build/make MX_TARGET=. HS_COMMON_SRC=$(HS_COMMON_SRC) JDK=$(ABS_BOOTDIR) EXPORT_DIR=$(SHARED_DIR) export
 endif
 
-# Builds code that can be shared among different build flavors
-buildshared:
-	$(PYTHON) -u $(GAMMADIR)/mxtool/mx.py build --no-native --export-dir $(SHARED_DIR)
-	#cd .. && $(MAKE) -f make/jvmci.make TARGET=build/make MX_TARGET=. HS_COMMON_SRC=$(HS_COMMON_SRC) JDK=$(ABS_BOOTDIR) EXPORT_DIR=$(SHARED_DIR) VERBOSE=0 export
 
 # Export file rule
 generic_export: $(EXPORT_LIST)
--- a/make/defs.make	Fri Jun 05 17:11:50 2015 +0200
+++ b/make/defs.make	Fri Jun 05 17:12:08 2015 +0200
@@ -360,36 +360,42 @@
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h
 EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h
 EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/jvmci-service.jar
-EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/truffle.jar
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/graal.jar
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/graal-truffle.jar
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/jvmci-api.jar
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/jvmci-hotspot.jar
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.hotspot.HotSpotJVMCIBackendFactory
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.hotspot.HotSpotVMEventListener
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.debug.DebugInitializationPropertyProvider
 
 ifneq ("$(wildcard $(SHARED_DIR)/services/com.oracle.jvmci.hotspot.events.EventProvider)","")
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.hotspot.events.EventProvider
 endif
 
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotConstantReflectionProvider
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotJVMCIRuntime
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotResolvedJavaFieldImpl
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotResolvedJavaMethodImpl
+
+ifeq ($(JVMCI_USE_MAKE),)
+EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/truffle.jar
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/graal.jar
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_DIR)/graal-truffle.jar
+
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.hotspot.HotSpotVMEventListener
+
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.debug.DebugInitializationPropertyProvider
+
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.api.runtime.GraalRuntimeAccess
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.code.DisassemblerProvider
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.compiler.match.MatchStatementSet
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.hotspot.HotSpotBackendFactory
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.nodes.spi.ReplacementsProvider
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.phases.tiers.CompilerConfiguration
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.truffle.hotspot.nfi.RawNativeCallNodeFactory
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.truffle.OptimizedCallTargetInstrumentationFactory
+EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.graal.truffle.LoopNodeFactory
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.truffle.api.TruffleRuntimeAccess
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.nfi.api.NativeFunctionInterfaceAccess
 
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotConstantReflectionProvider
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotJVMCIRuntime
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotResolvedJavaFieldImpl
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.jvmci.hotspot.HotSpotResolvedJavaMethodImpl
-
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.compiler.common.GraalOptions
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.compiler.GraalCompiler
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.compiler.GraalDebugConfig
@@ -423,6 +429,7 @@
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.virtual.phases.ea.PartialEscapePhase
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.lir.asm.CompilationResultBuilder
 EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/com.oracle.graal.java.BytecodeParser
+endif
 
 .PHONY: $(HS_ALT_MAKE)/defs.make
 
--- a/make/jvmci.make	Fri Jun 05 17:11:50 2015 +0200
+++ b/make/jvmci.make	Fri Jun 05 17:12:08 2015 +0200
@@ -1,4 +1,4 @@
-[?1034hVERBOSE=
+VERBOSE=
 TARGET=.
 JDK=
 
@@ -27,7 +27,7 @@
     $(eval services=$(1)/$(SERVICES_INF))
     $(eval options=$(1)/$(OPTIONS_INF))
     test -d $(services) || mkdir -p $(services)
-    test ! -d $(providers) || (cd $(providers) && for i in $$(ls $(providers)); do c=$$(cat $$i); echo $$i >> $(services)$$c; rm $$i; done)
+    test ! -d $(providers) || (cd $(providers) && for i in $$(ls); do c=$$(cat $$i); echo $$i >> $(abspath $(services))/$$c; rm $$i; done)
 
     # We're building all projects together with one javac call; thus we cannot determine, from which project the generated file is thus we hardcode it for now
     $(eval vmconfig=$(1)/hotspot/HotSpotVMConfig.inline.hpp)
@@ -36,8 +36,8 @@
 endef
 
 define extract =
-    $(eval TMP := $(shell mktemp -d))
-    mkdir -p $(2);
+    $(eval TMP := $(shell mktemp -d $(1)_XXXXX))
+    mkdir -p $(2)
     cd $(TMP) && $(JAR) xf $(abspath $(1)) &&         ((test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2))) &&  (test ! -d .$(OPTIONS_INF) || cp -r .$(OPTIONS_INF) $(abspath $(2))))
     rm -r $(TMP)
     cp $(1) $(2)
@@ -53,12 +53,6 @@
 
 
 
-EXPORTED_FILES += $(MX_TARGET)/build/truffle.jar
-
-EXPORTED_FILES += $(MX_TARGET)/build/graal.jar
-
-EXPORTED_FILES += $(MX_TARGET)/build/graal-truffle.jar
-
 JDK_BOOTCLASSPATH = $(JDK)/jre/lib/resources.jar:$(JDK)/jre/lib/rt.jar:$(JDK)/jre/lib/jsse.jar:$(JDK)/jre/lib/jce.jar:$(JDK)/jre/lib/charsets.jar:$(JDK)/jre/lib/jfr.jar
 
 COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_SRC = $(shell find graal/com.oracle.jvmci.hotspotvmconfig/src -type f -name *.java 2> /dev/null)
@@ -78,18 +72,26 @@
 
 COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR = $(TARGET)/graal/com.oracle.jvmci.options.processor/ap/com.oracle.jvmci.options.processor.jar
 
-JVMCI_UTIL_SRC = $(shell find graal/com.oracle.jvmci.bytecode/src -type f -name *.java 2> /dev/null)
-JVMCI_UTIL_SRC += $(shell find graal/com.oracle.jvmci.asm/src -type f -name *.java 2> /dev/null)
-JVMCI_UTIL_SRC += $(shell find graal/com.oracle.jvmci.amd64/src -type f -name *.java 2> /dev/null)
-JVMCI_UTIL_SRC += $(shell find graal/com.oracle.jvmci.asm.amd64/src -type f -name *.java 2> /dev/null)
-JVMCI_UTIL_SRC += $(shell find graal/com.oracle.jvmci.sparc/src -type f -name *.java 2> /dev/null)
-JVMCI_UTIL_SRC += $(shell find graal/com.oracle.jvmci.asm.sparc/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC = $(shell find graal/com.oracle.jvmci.hotspotvmconfig/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspotvmconfig/graal/com.oracle.jvmci.hotspotvmconfig/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.amd64/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.amd64/graal/com.oracle.jvmci.amd64/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot/graal/com.oracle.jvmci.hotspot/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.amd64/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.amd64/graal/com.oracle.jvmci.hotspot.amd64/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.sparc/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.sparc/graal/com.oracle.jvmci.sparc/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.sparc/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.sparc/graal/com.oracle.jvmci.hotspot.sparc/src_gen -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.jfr/src -type f -name *.java 2> /dev/null)
+JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.jfr/graal/com.oracle.jvmci.hotspot.jfr/src_gen -type f -name *.java 2> /dev/null)
 
-JVMCI_UTIL_JAR = $(TARGET)/build/jvmci-util.jar
+JVMCI_HOTSPOT_JAR = $(TARGET)/build/jvmci-hotspot.jar
 
-JVMCI_UTIL_DEP_JARS = $(TARGET)/build/jvmci-service.jar $(TARGET)/build/jvmci-api.jar
+JVMCI_HOTSPOT_DEP_JARS = $(TARGET)/build/jvmci-service.jar $(TARGET)/build/jvmci-api.jar graal/findbugs-SuppressFBWarnings.jar
 
-EXPORTED_FILES += $(JVMCI_UTIL_JAR)
+EXPORTED_FILES += $(JVMCI_HOTSPOT_JAR)
 
 JVMCI_SERVICE_SRC = $(shell find graal/com.oracle.jvmci.service/src -type f -name *.java 2> /dev/null)
 
@@ -99,23 +101,6 @@
 
 EXPORTED_FILES += $(JVMCI_SERVICE_JAR)
 
-JVMCI_HOTSPOT_SRC = $(shell find graal/com.oracle.jvmci.hotspotvmconfig/src -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspotvmconfig/graal/com.oracle.jvmci.hotspotvmconfig/src_gen -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot/src -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot/graal/com.oracle.jvmci.hotspot/src_gen -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.amd64/src -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.amd64/graal/com.oracle.jvmci.hotspot.amd64/src_gen -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.sparc/src -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.sparc/graal/com.oracle.jvmci.hotspot.sparc/src_gen -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.jfr/src -type f -name *.java 2> /dev/null)
-JVMCI_HOTSPOT_SRC += $(shell find graal/com.oracle.jvmci.hotspot.jfr/graal/com.oracle.jvmci.hotspot.jfr/src_gen -type f -name *.java 2> /dev/null)
-
-JVMCI_HOTSPOT_JAR = $(TARGET)/build/jvmci-hotspot.jar
-
-JVMCI_HOTSPOT_DEP_JARS = $(TARGET)/build/jvmci-util.jar $(TARGET)/build/jvmci-service.jar $(TARGET)/build/jvmci-api.jar graal/findbugs-SuppressFBWarnings.jar
-
-EXPORTED_FILES += $(JVMCI_HOTSPOT_JAR)
-
 JVMCI_API_SRC = $(shell find graal/com.oracle.jvmci.meta/src -type f -name *.java 2> /dev/null)
 JVMCI_API_SRC += $(shell find graal/com.oracle.jvmci.code/src -type f -name *.java 2> /dev/null)
 JVMCI_API_SRC += $(shell find graal/com.oracle.jvmci.runtime/src -type f -name *.java 2> /dev/null)
@@ -130,7 +115,7 @@
 EXPORTED_FILES += $(JVMCI_API_JAR)
 
 $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_JAR): $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_SRC)  
-	$(eval TMP := $(shell mktemp -d))
+	$(eval TMP := $(shell mktemp -d COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_XXXXX))
 	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH)  $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_SRC)
 	cp -r graal/com.oracle.jvmci.hotspotvmconfig.processor/src/META-INF $(TMP)
 	$(call process_options,$(TMP),False)
@@ -139,7 +124,7 @@
 	rm -r $(TMP)
 
 $(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_JAR): $(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_SRC)  
-	$(eval TMP := $(shell mktemp -d))
+	$(eval TMP := $(shell mktemp -d COM_ORACLE_JVMCI_SERVICE_PROCESSOR_XXXXX))
 	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH)  $(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_SRC)
 	cp -r graal/com.oracle.jvmci.service.processor/src/META-INF $(TMP)
 	$(call process_options,$(TMP),False)
@@ -148,7 +133,7 @@
 	rm -r $(TMP)
 
 $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR): $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_SRC)  
-	$(eval TMP := $(shell mktemp -d))
+	$(eval TMP := $(shell mktemp -d COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_XXXXX))
 	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH)  $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_SRC)
 	cp -r graal/com.oracle.jvmci.options.processor/src/META-INF $(TMP)
 	$(call process_options,$(TMP),False)
@@ -156,17 +141,17 @@
 	$(JAR) cf $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR) -C $(TMP) .
 	rm -r $(TMP)
 
-$(JVMCI_UTIL_JAR): $(JVMCI_UTIL_SRC)  $(JVMCI_UTIL_DEP_JARS)
-	$(eval TMP := $(shell mktemp -d))
-	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH) -cp $(TARGET)/build/jvmci-service.jar:$(TARGET)/build/jvmci-api.jar $(JVMCI_UTIL_SRC)
+$(JVMCI_HOTSPOT_JAR): $(JVMCI_HOTSPOT_SRC) $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_JAR) $(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_JAR) $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR) $(JVMCI_HOTSPOT_DEP_JARS)
+	$(eval TMP := $(shell mktemp -d JVMCI_HOTSPOT_XXXXX))
+	$(JAVAC) -d $(TMP) -processorpath $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_JAR):$(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_JAR):$(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR) -bootclasspath $(JDK_BOOTCLASSPATH) -cp $(TARGET)/build/jvmci-service.jar:$(TARGET)/build/jvmci-api.jar:graal/findbugs-SuppressFBWarnings.jar $(JVMCI_HOTSPOT_SRC)
 	
 	$(call process_options,$(TMP),True)
-	mkdir -p $$(dirname $(JVMCI_UTIL_JAR))
-	$(JAR) cf $(JVMCI_UTIL_JAR) -C $(TMP) .
+	mkdir -p $$(dirname $(JVMCI_HOTSPOT_JAR))
+	$(JAR) cf $(JVMCI_HOTSPOT_JAR) -C $(TMP) .
 	rm -r $(TMP)
 
 $(JVMCI_SERVICE_JAR): $(JVMCI_SERVICE_SRC)  $(JVMCI_SERVICE_DEP_JARS)
-	$(eval TMP := $(shell mktemp -d))
+	$(eval TMP := $(shell mktemp -d JVMCI_SERVICE_XXXXX))
 	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH) -cp graal/findbugs-SuppressFBWarnings.jar $(JVMCI_SERVICE_SRC)
 	
 	$(call process_options,$(TMP),True)
@@ -174,17 +159,8 @@
 	$(JAR) cf $(JVMCI_SERVICE_JAR) -C $(TMP) .
 	rm -r $(TMP)
 
-$(JVMCI_HOTSPOT_JAR): $(JVMCI_HOTSPOT_SRC) $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_JAR) $(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_JAR) $(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR) $(JVMCI_HOTSPOT_DEP_JARS)
-	$(eval TMP := $(shell mktemp -d))
-	$(JAVAC) -d $(TMP) -processorpath $(COM_ORACLE_JVMCI_HOTSPOTVMCONFIG_PROCESSOR_JAR):$(COM_ORACLE_JVMCI_SERVICE_PROCESSOR_JAR):$(COM_ORACLE_JVMCI_OPTIONS_PROCESSOR_JAR) -bootclasspath $(JDK_BOOTCLASSPATH) -cp $(TARGET)/build/jvmci-util.jar:$(TARGET)/build/jvmci-service.jar:$(TARGET)/build/jvmci-api.jar:graal/findbugs-SuppressFBWarnings.jar $(JVMCI_HOTSPOT_SRC)
-	
-	$(call process_options,$(TMP),True)
-	mkdir -p $$(dirname $(JVMCI_HOTSPOT_JAR))
-	$(JAR) cf $(JVMCI_HOTSPOT_JAR) -C $(TMP) .
-	rm -r $(TMP)
-
 $(JVMCI_API_JAR): $(JVMCI_API_SRC)  $(JVMCI_API_DEP_JARS)
-	$(eval TMP := $(shell mktemp -d))
+	$(eval TMP := $(shell mktemp -d JVMCI_API_XXXXX))
 	$(JAVAC) -d $(TMP)  -bootclasspath $(JDK_BOOTCLASSPATH) -cp $(TARGET)/build/jvmci-service.jar:graal/findbugs-SuppressFBWarnings.jar $(JVMCI_API_SRC)
 	
 	$(call process_options,$(TMP),True)
@@ -192,5 +168,5 @@
 	$(JAR) cf $(JVMCI_API_JAR) -C $(TMP) .
 	rm -r $(TMP)
 
-default: $(JVMCI_UTIL_JAR) $(JVMCI_SERVICE_JAR) $(JVMCI_HOTSPOT_JAR) $(JVMCI_API_JAR)
-.PHONY: default
+default: $(JVMCI_HOTSPOT_JAR) $(JVMCI_SERVICE_JAR) $(JVMCI_API_JAR)
+.PHONY: default
\ No newline at end of file
--- a/make/solaris/makefiles/defs.make	Fri Jun 05 17:11:50 2015 +0200
+++ b/make/solaris/makefiles/defs.make	Fri Jun 05 17:12:08 2015 +0200
@@ -304,4 +304,3 @@
   endif
 endif
 EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
-EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/com.oracle.jvmci.debug.DebugInitializationPropertyProvider
--- a/mx/mx_graal.py	Fri Jun 05 17:11:50 2015 +0200
+++ b/mx/mx_graal.py	Fri Jun 05 17:12:08 2015 +0200
@@ -90,16 +90,17 @@
 _untilVersion = None
 
 class JDKDeployedDist:
-    def __init__(self, name, isExtension=False, usesJVMCIClassLoader=False):
+    def __init__(self, name, isExtension=False, usesJVMCIClassLoader=False, partOfHotSpot=False):
         self.name = name
         self.isExtension = isExtension
         self.usesJVMCIClassLoader = usesJVMCIClassLoader
+        self.partOfHotSpot = partOfHotSpot # true when this distribution is delivered with HotSpot
 
 _jdkDeployedDists = [
     JDKDeployedDist('TRUFFLE'),
-    JDKDeployedDist('JVMCI_SERVICE'),
-    JDKDeployedDist('JVMCI_API', usesJVMCIClassLoader=True),
-    JDKDeployedDist('JVMCI_HOTSPOT', usesJVMCIClassLoader=True),
+    JDKDeployedDist('JVMCI_SERVICE', partOfHotSpot=True),
+    JDKDeployedDist('JVMCI_API', usesJVMCIClassLoader=True, partOfHotSpot=True),
+    JDKDeployedDist('JVMCI_HOTSPOT', usesJVMCIClassLoader=True, partOfHotSpot=True),
     JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True),
     JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True)
 ]
@@ -494,7 +495,7 @@
     if installJars:
         for jdkDist in _jdkDeployedDists:
             dist = mx.distribution(jdkDist.name)
-            if exists(dist.path):
+            if exists(dist.path) and jdkDist.partOfHotSpot:
                 _installDistInJdks(jdkDist)
 
     if vmToCheck is not None:
@@ -665,7 +666,6 @@
     """
     Installs the jar(s) for a given Distribution into all existing JVMCI JDKs
     """
-
     dist = mx.distribution(deployableDist.name)
     if dist.name == 'GRAAL':
         _patchGraalVersionConstant(dist)
@@ -838,6 +838,12 @@
 
     The global '--vm' and '--vmbuild' options select which VM type and build target to build."""
 
+    # Turn all jdk distributions into non HotSpot; this is only necessary as long we support building/exporting JVMCI with make and mx
+    if not ("-m" in args or "--use-make" in args):
+        for jdkDist in _jdkDeployedDists:
+            if jdkDist.partOfHotSpot:
+                jdkDist.partOfHotSpot = False
+
     # Override to fail quickly if extra arguments are given
     # at the end of the command line. This allows for a more
     # helpful error message.
@@ -856,6 +862,7 @@
     parser = AP()
     parser.add_argument('--export-dir', help='directory to which JVMCI and Graal jars and jvmci.options will be copied', metavar='<path>')
     parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
+    parser.add_argument('-m', '--use-make', action='store_true', help='Use the jvmci.make file to build and export JVMCI')
     opts2 = mx.build(['--source', '1.7'] + args, parser=parser)
     assert len(opts2.remainder) == 0
 
@@ -883,16 +890,18 @@
                 defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/' + basename(dist.path)
             if defLine not in defs:
                 mx.abort('Missing following line in ' + defsPath + '\n' + defLine)
-            shutil.copy(dist.path, opts2.export_dir)
+                shutil.copy(dist.path, opts2.export_dir)
+
         services, optionsFiles = _extractJVMCIFiles(jdkJars, jvmciJars, join(opts2.export_dir, 'services'), join(opts2.export_dir, 'options'))
-        for service in services:
-            defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/' + service
-            if defLine not in defs:
-                mx.abort('Missing following line in ' + defsPath + ' for service from ' + dist.name + '\n' + defLine)
-        for optionsFile in optionsFiles:
-            defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/' + optionsFile
-            if defLine not in defs:
-                mx.abort('Missing following line in ' + defsPath + ' for options from ' + dist.name + '\n' + defLine)
+        if not opts2.use_make:
+            for service in services:
+                defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_SERVICES_DIR)/' + service
+                if defLine not in defs:
+                    mx.abort('Missing following line in ' + defsPath + ' for service from ' + dist.name + '\n' + defLine)
+            for optionsFile in optionsFiles:
+                defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_JVMCI_OPTIONS_DIR)/' + optionsFile
+                if defLine not in defs:
+                    mx.abort('Missing following line in ' + defsPath + ' for options from ' + dist.name + '\n' + defLine)
         jvmciOptions = join(_graal_home, 'jvmci.options')
         if exists(jvmciOptions):
             shutil.copy(jvmciOptions, opts2.export_dir)
@@ -1019,6 +1028,7 @@
             setMakeVar('ARCH_DATA_MODEL', '64', env=env)
             setMakeVar('HOTSPOT_BUILD_JOBS', str(cpus), env=env)
             setMakeVar('ALT_BOOTDIR', mx.java().jdk, env=env)
+            setMakeVar("EXPORT_PATH", jdk)
 
             setMakeVar('MAKE_VERBOSE', 'y' if mx._opts.verbose else '')
             if vm.endswith('nojvmci'):
@@ -1044,7 +1054,8 @@
                         setMakeVar('STRIP_POLICY', 'no_strip')
             # This removes the need to unzip the *.diz files before debugging in gdb
             setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env)
-
+            if opts2.use_make:
+                setMakeVar('JVMCI_USE_MAKE', '1')
             # Clear this variable as having it set can cause very confusing build problems
             env.pop('CLASSPATH', None)
 
@@ -1055,8 +1066,8 @@
             envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]])
             if len(envPrefix):
                 mx.log('env ' + envPrefix + ' \\')
-
-            runCmd.append(build + buildSuffix)
+            makeTarget = "all_" + build + buildSuffix if opts2.use_make else build + buildSuffix
+            runCmd.append(makeTarget)
 
             if not mx._opts.verbose:
                 mx.log(' '.join(runCmd))
@@ -1093,6 +1104,9 @@
                         # Legacy support
                         f.write('-graal ALIASED_TO -jvmci\n')
 
+        for jdkDist in _jdkDeployedDists: # Install non HotSpot distribution
+            if not jdkDist.partOfHotSpot:
+                _installDistInJdks(jdkDist)
         if exists(timestampFile):
             os.utime(timestampFile, None)
         else:
@@ -2698,6 +2712,7 @@
         def _close(jdkDeployable):
             def _install(dist):
                 assert dist.name == jdkDeployable.name, dist.name + "!=" + jdkDeployable.name
-                _installDistInJdks(jdkDeployable)
+                if not jdkDist.partOfHotSpot:
+                    _installDistInJdks(jdkDeployable)
             return _install
         mx.distribution(jdkDist.name).add_update_listener(_close(jdkDist))
--- a/mx/mx_graal_makefile.py	Fri Jun 05 17:11:50 2015 +0200
+++ b/mx/mx_graal_makefile.py	Fri Jun 05 17:12:08 2015 +0200
@@ -51,8 +51,7 @@
     args = parser.parse_args(args)
 
     if args.selectedDists == None or len(args.selectedDists) == 0:
-        parser.print_help()
-        return
+        args.selectedDists = [d.name for d in mx_graal._jdkDeployedDists if d.partOfHotSpot]
     mf = Makefile()
     if do_build_makefile(mf, args.selectedDists):
         contents = mf.generate()
@@ -144,7 +143,7 @@
     if len(classPath) > 0: mf.add_definition("{depJarsVariable} = {jarDeps}".format(**props))
     if shouldExport: mf.add_definition("EXPORTED_FILES += $({name}_JAR)".format(**props))
     mf.add_rule("""$({name}_JAR): $({sourcesVariableName}) {annotationProcessors} {depJarsVariableAccess}
-\t$(eval TMP := $(shell mktemp -d))
+\t$(eval TMP := $(shell mktemp -d {name}_XXXXX))
 \t$(JAVAC) -d $(TMP) {cpAnnotationProcessors} {bootCp} {cpDeps} $({sourcesVariableName})
 \t{copyResources}
 \t$(call process_options,$(TMP),{shouldExport})
@@ -190,7 +189,7 @@
     $(eval services=$(1)/$(SERVICES_INF))
     $(eval options=$(1)/$(OPTIONS_INF))
     test -d $(services) || mkdir -p $(services)
-    test ! -d $(providers) || (cd $(providers) && for i in $$(ls $(providers)); do c=$$(cat $$i); echo $$i >> $(services)$$c; rm $$i; done)
+    test ! -d $(providers) || (cd $(providers) && for i in $$(ls); do c=$$(cat $$i); echo $$i >> $(abspath $(services))/$$c; rm $$i; done)
 
     # We're building all projects together with one javac call; thus we cannot determine, from which project the generated file is thus we hardcode it for now
     $(eval vmconfig=$(1)/hotspot/HotSpotVMConfig.inline.hpp)
@@ -199,8 +198,8 @@
 endef
 
 define extract =
-    $(eval TMP := $(shell mktemp -d))
-    mkdir -p $(2);
+    $(eval TMP := $(shell mktemp -d $(1)_XXXXX))
+    mkdir -p $(2)
     cd $(TMP) && $(JAR) xf $(abspath $(1)) && \
         ((test ! -d .$(SERVICES_INF) || cp -r .$(SERVICES_INF) $(abspath $(2))) &&  (test ! -d .$(OPTIONS_INF) || cp -r .$(OPTIONS_INF) $(abspath $(2))))
     rm -r $(TMP)
@@ -224,6 +223,7 @@
         if d.name in selectedDists:
             dists.update(d.get_dist_deps(True, True))
             projects.update(d.sorted_deps(includeLibs=False, transitive=True))
+
     for p in projects:
         deps = p.all_deps([], False, includeSelf=True, includeJreLibs=False, includeAnnotationProcessors=True)
         for d in deps:
@@ -231,11 +231,6 @@
                 apd = d.definedAnnotationProcessorsDist
                 ap.add(apd)
 
-    for d in mx_graal._jdkDeployedDists:
-        dist = mx.distribution(d.name)
-        if dist not in dists: # this sould go away
-            mf.add_definition("EXPORTED_FILES += $(MX_TARGET)/{}".format(os.path.relpath(dist.path, dist.suite.dir)))
-
     if len(dists) > 0:
         mf.add_definition(jdkBootClassPathVariableName + " = " + bootClassPath)
         bootClassPathVarAccess = "$(" + jdkBootClassPathVariableName + ")"
--- a/mx/suite.py	Fri Jun 05 17:11:50 2015 +0200
+++ b/mx/suite.py	Fri Jun 05 17:12:08 2015 +0200
@@ -284,74 +284,6 @@
       "workingSets" : "JVMCI",
     },
 
-    # ------------- JVMCI:Util -------------
-
-    "com.oracle.graal.asm" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : ["com.oracle.jvmci.code"],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Assembler",
-    },
-
-    "com.oracle.graal.asm.amd64" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : [
-        "com.oracle.graal.asm",
-        "com.oracle.jvmci.amd64",
-      ],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Assembler,AMD64",
-    },
-
-    "com.oracle.graal.asm.sparc" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : [
-        "com.oracle.graal.asm",
-        "com.oracle.jvmci.sparc",
-      ],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Assembler,SPARC",
-    },
-
-    "com.oracle.graal.bytecode" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Java",
-    },
-
-    "com.oracle.graal.asm.test" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : [
-        "com.oracle.graal.test",
-        "com.oracle.jvmci.runtime",
-      ],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Assembler,Test",
-    },
-
-    "com.oracle.graal.asm.amd64.test" : {
-      "subDir" : "graal",
-      "sourceDirs" : ["src"],
-      "dependencies" : [
-        "com.oracle.graal.asm.test",
-        "com.oracle.jvmci.common",
-        "com.oracle.graal.asm.amd64",
-      ],
-      "checkstyle" : "com.oracle.graal.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal,Assembler,AMD64,Test",
-    },
-
     # ------------- JVMCI:HotSpot -------------
 
     "com.oracle.jvmci.amd64" : {
@@ -473,6 +405,19 @@
 
     # ------------- Graal -------------
 
+    "com.oracle.graal.code" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.jvmci.service",
+        "com.oracle.jvmci.code",
+      ],
+      "annotationProcessors" : ["com.oracle.jvmci.service.processor"],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal",
+    },
+
     "com.oracle.graal.api.collections" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
@@ -650,6 +595,73 @@
       "workingSets" : "Graal,Graph,Test",
     },
 
+    "com.oracle.graal.asm" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : ["com.oracle.jvmci.code"],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Assembler",
+    },
+
+    "com.oracle.graal.asm.amd64" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.asm",
+        "com.oracle.jvmci.amd64",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Assembler,AMD64",
+    },
+
+    "com.oracle.graal.asm.sparc" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.asm",
+        "com.oracle.jvmci.sparc",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Assembler,SPARC",
+    },
+
+    "com.oracle.graal.bytecode" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Java",
+    },
+
+    "com.oracle.graal.asm.test" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.code",
+        "com.oracle.graal.test",
+        "com.oracle.jvmci.runtime",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Assembler,Test",
+    },
+
+    "com.oracle.graal.asm.amd64.test" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "com.oracle.graal.asm.test",
+        "com.oracle.jvmci.common",
+        "com.oracle.graal.asm.amd64",
+      ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Assembler,AMD64,Test",
+    },
+
     "com.oracle.graal.lir" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
@@ -1004,6 +1016,7 @@
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.graal.code",
         "com.oracle.graal.java",
         "com.oracle.graal.compiler",
       ],
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Fri Jun 05 17:12:08 2015 +0200
@@ -70,32 +70,9 @@
   // Capture info about frame layout.  Layout offsets are in jint
   // units because compiler frame slots are jints.
 #define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off
-#define DEF_YMM_HI_OFFS(regnum) ymm_hi ## regnum ## _off = ymm_off + (regnum)*16/BytesPerInt
   enum layout {
     fpu_state_off = frame::arg_reg_save_area_bytes/BytesPerInt, // fxsave save area
-#if defined(COMPILER2) || defined(JVMCI)
-    ymm_off       = fpu_state_off,            // offset in fxsave save area
-    DEF_YMM_HI_OFFS(0),
-    DEF_YMM_HI_OFFS(1),
-    DEF_YMM_HI_OFFS(2),
-    DEF_YMM_HI_OFFS(3),
-    DEF_YMM_HI_OFFS(4),
-    DEF_YMM_HI_OFFS(5),
-    DEF_YMM_HI_OFFS(6),
-    DEF_YMM_HI_OFFS(7),
-    DEF_YMM_HI_OFFS(8),
-    DEF_YMM_HI_OFFS(9),
-    DEF_YMM_HI_OFFS(10),
-    DEF_YMM_HI_OFFS(11),
-    DEF_YMM_HI_OFFS(12),
-    DEF_YMM_HI_OFFS(13),
-    DEF_YMM_HI_OFFS(14),
-    DEF_YMM_HI_OFFS(15),
-    ymm_hi_save_size = 16 * 16 / BytesPerInt,
-#else
-    ymm_hi_save_size = 0,
-#endif
-    xmm_off       = fpu_state_off + 160/BytesPerInt + ymm_hi_save_size,            // offset in fxsave save area
+    xmm_off       = fpu_state_off + 160/BytesPerInt,            // offset in fxsave save area
     DEF_XMM_OFFS(0),
     DEF_XMM_OFFS(1),
     DEF_XMM_OFFS(2),
@@ -112,7 +89,7 @@
     DEF_XMM_OFFS(13),
     DEF_XMM_OFFS(14),
     DEF_XMM_OFFS(15),
-    fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt) + ymm_hi_save_size,
+    fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
     fpu_stateH_end,
     r15_off, r15H_off,
     r14_off, r14H_off,
@@ -162,6 +139,21 @@
 };
 
 OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
+  int vect_words = 0;
+  int ymmhi_offset = -1;
+#if defined(COMPILER2) || defined(JVMCI)
+  if (save_vectors) {
+    assert(UseAVX > 0, "256bit vectors are supported only with AVX");
+    assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
+    // Save upper half of YMM registes
+    vect_words = 16 * 16 / wordSize;
+    ymmhi_offset = additional_frame_words;
+    additional_frame_words += vect_words;
+  }
+#else
+  assert(!save_vectors, "vectors are generated only by C2 and JVMCI");
+#endif
+
   // Always make the frame size 16-byte aligned
   int frame_size_in_bytes = round_to(additional_frame_words*wordSize +
                                      reg_save_size*BytesPerInt, 16);
@@ -182,32 +174,26 @@
   __ enter();          // rsp becomes 16-byte aligned here
   __ push_CPU_state(); // Push a multiple of 16 bytes
 
-#if defined(COMPILER2) || defined(JVMCI)
-  __ subptr(rsp, 256); // Save upper half of YMM registers
-  if (save_vectors) {
-    assert(UseAVX > 0, "256bit vectors are supported only with AVX");
-    assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
-    // Save upper half of YMM registers
-    __ vextractf128h(Address(rsp, ymm_hi0_off * BytesPerInt),  xmm0);
-    __ vextractf128h(Address(rsp, ymm_hi1_off * BytesPerInt),  xmm1);
-    __ vextractf128h(Address(rsp, ymm_hi2_off * BytesPerInt),  xmm2);
-    __ vextractf128h(Address(rsp, ymm_hi3_off * BytesPerInt),  xmm3);
-    __ vextractf128h(Address(rsp, ymm_hi4_off * BytesPerInt),  xmm4);
-    __ vextractf128h(Address(rsp, ymm_hi5_off * BytesPerInt),  xmm5);
-    __ vextractf128h(Address(rsp, ymm_hi6_off * BytesPerInt),  xmm6);
-    __ vextractf128h(Address(rsp, ymm_hi7_off * BytesPerInt),  xmm7);
-    __ vextractf128h(Address(rsp, ymm_hi8_off * BytesPerInt),  xmm8);
-    __ vextractf128h(Address(rsp, ymm_hi9_off * BytesPerInt),  xmm9);
-    __ vextractf128h(Address(rsp, ymm_hi10_off * BytesPerInt), xmm10);
-    __ vextractf128h(Address(rsp, ymm_hi11_off * BytesPerInt), xmm11);
-    __ vextractf128h(Address(rsp, ymm_hi12_off * BytesPerInt), xmm12);
-    __ vextractf128h(Address(rsp, ymm_hi13_off * BytesPerInt), xmm13);
-    __ vextractf128h(Address(rsp, ymm_hi14_off * BytesPerInt), xmm14);
-    __ vextractf128h(Address(rsp, ymm_hi15_off * BytesPerInt), xmm15);
+  if (vect_words > 0) {
+    assert(vect_words*wordSize == 256, "");
+    __ subptr(rsp, 256); // Save upper half of YMM registes
+    __ vextractf128h(Address(rsp,  0),xmm0);
+    __ vextractf128h(Address(rsp, 16),xmm1);
+    __ vextractf128h(Address(rsp, 32),xmm2);
+    __ vextractf128h(Address(rsp, 48),xmm3);
+    __ vextractf128h(Address(rsp, 64),xmm4);
+    __ vextractf128h(Address(rsp, 80),xmm5);
+    __ vextractf128h(Address(rsp, 96),xmm6);
+    __ vextractf128h(Address(rsp,112),xmm7);
+    __ vextractf128h(Address(rsp,128),xmm8);
+    __ vextractf128h(Address(rsp,144),xmm9);
+    __ vextractf128h(Address(rsp,160),xmm10);
+    __ vextractf128h(Address(rsp,176),xmm11);
+    __ vextractf128h(Address(rsp,192),xmm12);
+    __ vextractf128h(Address(rsp,208),xmm13);
+    __ vextractf128h(Address(rsp,224),xmm14);
+    __ vextractf128h(Address(rsp,240),xmm15);
   }
-#else
-  assert(!save_vectors, "vectors are generated only by C2 and JVMCI");
-#endif
   if (frame::arg_reg_save_area_bytes != 0) {
     // Allocate argument register save area
     __ subptr(rsp, frame::arg_reg_save_area_bytes);
@@ -222,6 +208,7 @@
   OopMap* map = new OopMap(frame_size_in_slots, 0);
 
 #define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_slots)
+#define YMMHI_STACK_OFFSET(x) VMRegImpl::stack2reg((x) + ymmhi_offset)
 
   map->set_callee_saved(STACK_OFFSET( rax_off ), rax->as_VMReg());
   map->set_callee_saved(STACK_OFFSET( rcx_off ), rcx->as_VMReg());
@@ -259,22 +246,23 @@
 
 #if defined(COMPILER2) || defined(JVMCI)
   if (save_vectors) {
-    map->set_callee_saved(STACK_OFFSET(ymm_hi0_off ), xmm0->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi1_off ), xmm1->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi2_off ), xmm2->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi3_off ), xmm3->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi4_off ), xmm4->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi5_off ), xmm5->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi6_off ), xmm6->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi7_off ), xmm7->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi8_off ), xmm8->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi9_off ), xmm9->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi10_off), xmm10->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi11_off), xmm11->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi12_off), xmm12->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi13_off), xmm13->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi14_off), xmm14->as_VMReg()->next()->next()->next()->next());
-    map->set_callee_saved(STACK_OFFSET(ymm_hi15_off), xmm15->as_VMReg()->next()->next()->next()->next());
+    assert(ymmhi_offset != -1, "save area must exist");
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm0_off ), xmm0->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm1_off ), xmm1->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm2_off ), xmm2->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm3_off ), xmm3->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm4_off ), xmm4->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm5_off ), xmm5->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm6_off ), xmm6->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm7_off ), xmm7->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm8_off ), xmm8->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm9_off ), xmm9->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm10_off), xmm10->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm11_off), xmm11->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm12_off), xmm12->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm13_off), xmm13->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm14_off), xmm14->as_VMReg()->next()->next()->next()->next());
+    map->set_callee_saved(YMMHI_STACK_OFFSET(xmm15_off), xmm15->as_VMReg()->next()->next()->next()->next());
   }
 #endif
 
@@ -326,24 +314,24 @@
     // Restore upper half of YMM registes.
     assert(UseAVX > 0, "256bit vectors are supported only with AVX");
     assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
-    __ vinsertf128h(xmm0,  Address(rsp, ymm_hi0_off * BytesPerInt));
-    __ vinsertf128h(xmm1,  Address(rsp, ymm_hi1_off * BytesPerInt));
-    __ vinsertf128h(xmm2,  Address(rsp, ymm_hi2_off * BytesPerInt));
-    __ vinsertf128h(xmm3,  Address(rsp, ymm_hi3_off * BytesPerInt));
-    __ vinsertf128h(xmm4,  Address(rsp, ymm_hi4_off * BytesPerInt));
-    __ vinsertf128h(xmm5,  Address(rsp, ymm_hi5_off * BytesPerInt));
-    __ vinsertf128h(xmm6,  Address(rsp, ymm_hi6_off * BytesPerInt));
-    __ vinsertf128h(xmm7,  Address(rsp, ymm_hi7_off * BytesPerInt));
-    __ vinsertf128h(xmm8,  Address(rsp, ymm_hi8_off * BytesPerInt));
-    __ vinsertf128h(xmm9,  Address(rsp, ymm_hi9_off * BytesPerInt));
-    __ vinsertf128h(xmm10, Address(rsp, ymm_hi10_off * BytesPerInt));
-    __ vinsertf128h(xmm11, Address(rsp, ymm_hi11_off * BytesPerInt));
-    __ vinsertf128h(xmm12, Address(rsp, ymm_hi12_off * BytesPerInt));
-    __ vinsertf128h(xmm13, Address(rsp, ymm_hi13_off * BytesPerInt));
-    __ vinsertf128h(xmm14, Address(rsp, ymm_hi14_off * BytesPerInt));
-    __ vinsertf128h(xmm15, Address(rsp, ymm_hi15_off * BytesPerInt));
+    __ vinsertf128h(xmm0, Address(rsp,  0));
+    __ vinsertf128h(xmm1, Address(rsp, 16));
+    __ vinsertf128h(xmm2, Address(rsp, 32));
+    __ vinsertf128h(xmm3, Address(rsp, 48));
+    __ vinsertf128h(xmm4, Address(rsp, 64));
+    __ vinsertf128h(xmm5, Address(rsp, 80));
+    __ vinsertf128h(xmm6, Address(rsp, 96));
+    __ vinsertf128h(xmm7, Address(rsp,112));
+    __ vinsertf128h(xmm8, Address(rsp,128));
+    __ vinsertf128h(xmm9, Address(rsp,144));
+    __ vinsertf128h(xmm10, Address(rsp,160));
+    __ vinsertf128h(xmm11, Address(rsp,176));
+    __ vinsertf128h(xmm12, Address(rsp,192));
+    __ vinsertf128h(xmm13, Address(rsp,208));
+    __ vinsertf128h(xmm14, Address(rsp,224));
+    __ vinsertf128h(xmm15, Address(rsp,240));
+    __ addptr(rsp, 256);
   }
-  __ addptr(rsp, 256);
 #else
   assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
 #endif
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Jun 05 17:12:08 2015 +0200
@@ -205,7 +205,6 @@
   JVMCI_ONLY(do_klass(HotSpotCompiledNmethod_klass,          com_oracle_jvmci_hotspot_HotSpotCompiledNmethod,              Jvmci)) \
   JVMCI_ONLY(do_klass(HotSpotForeignCallTarget_klass,        com_oracle_jvmci_hotspot_HotSpotForeignCallTarget,            Jvmci)) \
   JVMCI_ONLY(do_klass(HotSpotReferenceMap_klass,             com_oracle_jvmci_hotspot_HotSpotReferenceMap,                 Jvmci)) \
-  JVMCI_ONLY(do_klass(HotSpotOopMap_klass,                   com_oracle_jvmci_hotspot_HotSpotReferenceMap_HotSpotOopMap,   Jvmci)) \
   JVMCI_ONLY(do_klass(HotSpotInstalledCode_klass,            com_oracle_jvmci_hotspot_HotSpotInstalledCode,                Jvmci)) \
   JVMCI_ONLY(do_klass(HotSpotNmethod_klass,                  com_oracle_jvmci_hotspot_HotSpotNmethod,                      Jvmci)) \
   JVMCI_ONLY(do_klass(HotSpotResolvedJavaMethodImpl_klass,   com_oracle_jvmci_hotspot_HotSpotResolvedJavaMethodImpl,       Jvmci)) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Jun 05 17:12:08 2015 +0200
@@ -306,7 +306,6 @@
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotCompiledNmethod,          "com/oracle/jvmci/hotspot/HotSpotCompiledNmethod"))               \
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotForeignCallTarget,        "com/oracle/jvmci/hotspot/HotSpotForeignCallTarget"))             \
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotReferenceMap,             "com/oracle/jvmci/hotspot/HotSpotReferenceMap"))                  \
-  JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotReferenceMap_HotSpotOopMap, "com/oracle/jvmci/hotspot/HotSpotReferenceMap$HotSpotOopMap"))  \
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_CompilerToVMImpl,                "com/oracle/jvmci/hotspot/CompilerToVMImpl"))                     \
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotInstalledCode,            "com/oracle/jvmci/hotspot/HotSpotInstalledCode"))                 \
   JVMCI_ONLY(template(com_oracle_jvmci_hotspot_HotSpotNmethod,                  "com/oracle/jvmci/hotspot/HotSpotNmethod"))                       \
--- a/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Fri Jun 05 17:12:08 2015 +0200
@@ -69,83 +69,62 @@
   return asMethod(HotSpotResolvedJavaMethodImpl::metaspaceMethod(hotspot_method));
 }
 
-const int MapWordBits = 64;
-
-static int entry_value(typeArrayOop words, int i) {
-  jint words_idx = i / MapWordBits;
-  assert(words_idx >= 0 && words_idx < words->length(), "unexpected index");
-  jlong word = words->long_at(words_idx);
-  return (word >> (i % MapWordBits)) & 15LL;
-}
-
-static int fixedmap_size(oop bitset) {
-  typeArrayOop arr = HotSpotOopMap::words(bitset);
-  return arr->length() * MapWordBits;
-}
-
-static void set_vmreg_oops(OopMap* map, VMReg reg, typeArrayOop words, int idx) {
-  int value = entry_value(words, 4 * idx);
-  switch (value) {
-    case 10:
-      map->set_oop(reg);
-      break;
-    case 5:
-      map->set_narrowoop(reg);
-      map->set_narrowoop(reg->next());
-      break;
-    case 1:
-      map->set_narrowoop(reg);
-      break;
-    case 4:
-      map->set_narrowoop(reg->next());
-      break;
-    case 0:
-      break;
-    default:
-      assert(false, err_msg("unexpected bit pattern at %d = 0x%x", idx, value));
-      ShouldNotReachHere();
+// creates a HotSpot oop map out of the byte arrays provided by DebugInfo
+OopMap* CodeInstaller::create_oop_map(oop debug_info) {
+  oop reference_map = DebugInfo::referenceMap(debug_info);
+  if (HotSpotReferenceMap::maxRegisterSize(reference_map) > 16) {
+    _has_wide_vector = true;
   }
-}
-
-// creates a HotSpot oop map out of the byte arrays provided by DebugInfo
-static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) {
-  OopMap* map = new OopMap(total_frame_size, parameter_count);
-  oop reference_map = DebugInfo::referenceMap(debug_info);
-  oop register_map = HotSpotReferenceMap::registerRefMap(reference_map);
-  oop frame_map = HotSpotReferenceMap::frameRefMap(reference_map);
-  oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
-
-  if (register_map != NULL) {
-    typeArrayOop words = HotSpotOopMap::words(register_map);
-    int mapIdx = 0;
-    for (jint i = 0; i < RegisterImpl::number_of_registers; i++) {
-      set_vmreg_oops(map, as_Register(i)->as_VMReg(), words, mapIdx);
-      mapIdx++;
+  OopMap* map = new OopMap(_total_frame_size, _parameter_count);
+  objArrayOop objects = HotSpotReferenceMap::objects(reference_map);
+  typeArrayOop bytesPerArray = HotSpotReferenceMap::bytesPerElement(reference_map);
+  for (int i = 0; i < objects->length(); i++) {
+    oop value = objects->obj_at(i);
+    oop lirKind = AbstractValue::lirKind(value);
+    oop platformKind = LIRKind::platformKind(lirKind);
+    int bytesPerElement = bytesPerArray->int_at(i);
+    assert(bytesPerElement == 4 || bytesPerElement == 8, "wrong sizes");
+    jint referenceMask = LIRKind::referenceMask(lirKind);
+    assert(referenceMask != 0, "must be a reference type");
+    assert(referenceMask != -1, "must not be a derived reference type");
+    
+    VMReg vmReg;
+    if (value->is_a(RegisterValue::klass())) {
+      oop reg = RegisterValue::reg(value);
+      jint number = code_Register::number(reg);
+      vmReg = CodeInstaller::get_hotspot_reg(number);
+    } else if (value->is_a(StackSlot::klass())) {
+      jint offset = StackSlot::offset(value);
+#ifdef TARGET_ARCH_sparc
+      if(offset >= 0) {
+        offset += 128;
+      }
+#endif
+      if (StackSlot::addFrameSize(value)) {
+        offset += _total_frame_size;
+      }
+      assert(offset % 4 == 0, "must be aligned");
+      vmReg = VMRegImpl::stack2reg(offset / 4);
     }
-#ifdef TARGET_ARCH_x86
-    for (jint i = 0; i < XMMRegisterImpl::number_of_registers; i++) {
-      VMReg reg = as_XMMRegister(i)->as_VMReg();
-      for (jint j = 0; j < 4; j++) {
-        set_vmreg_oops(map, reg->next(2 * j), words, mapIdx++);
+      
+    int bit = 1;
+    while (referenceMask != 0) {
+      if (referenceMask & bit) {
+        if (bytesPerElement == 8) {
+          map->set_oop(vmReg);
+        } else {
+          map->set_narrowoop(vmReg);
+        }
+        referenceMask &= ~bit;
       }
+      vmReg = vmReg->next();
+      if (bytesPerElement == 8) {
+        vmReg = vmReg->next();
+      }
+      bit <<= 1;
     }
-#endif
-#ifdef TARGET_ARCH_sparc
-    for (jint i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
-      VMReg reg = as_FloatRegister(i)->as_VMReg();
-      set_vmreg_oops(map, reg, words, mapIdx++);
-    }
-#endif
   }
-
-  typeArrayOop words = HotSpotOopMap::words(frame_map);
-  int size = fixedmap_size(frame_map) / 4;
-  for (jint i = 0; i < size; i++) {
-    // HotSpot stack slots are 4 bytes
-    VMReg reg = VMRegImpl::stack2reg(i * VMRegImpl::slots_per_word);
-    set_vmreg_oops(map, reg, words, i);
-  }
-
+  oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
   if (callee_save_info != NULL) {
     objArrayOop registers = RegisterSaveLayout::registers(callee_save_info);
     typeArrayOop slots = RegisterSaveLayout::slots(callee_save_info);
@@ -261,7 +240,17 @@
       return value;
     }
   } else if (value->is_a(StackSlot::klass())) {
-      Location::Type locationType;
+    jint offset = StackSlot::offset(value);
+#ifdef TARGET_ARCH_sparc
+    if(offset >= 0) {
+      offset += 128;
+    }
+#endif
+    if (StackSlot::addFrameSize(value)) {
+      offset += _total_frame_size;
+    }
+
+    Location::Type locationType;
     if (type == T_LONG) {
       locationType = reference ? Location::oop : Location::lng;
     } else if (type == T_INT) {
@@ -278,15 +267,6 @@
       assert(type == T_OBJECT && reference, "unexpected type in stack slot");
       locationType = Location::oop;
     }
-    jint offset = StackSlot::offset(value);
-#ifdef TARGET_ARCH_sparc
-    if(offset >= 0) {
-      offset += 128;
-    }
-#endif
-    if (StackSlot::addFrameSize(value)) {
-      offset += _total_frame_size;
-    }
     ScopeValue* value = new LocationValue(Location::new_stk_loc(locationType, offset));
     if (type == T_DOUBLE || (type == T_LONG && !reference)) {
       second = value;
@@ -470,8 +450,10 @@
       // Make sure a valid compile_id is associated with every compile
       id = CompileBroker::assign_compile_id_unlocked(Thread::current(), method, entry_bci);
     }
-    result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-        JVMCICompiler::instance(), _debug_recorder, _dependencies, env, id, false, installed_code, compiled_code, speculation_log);
+    result = JVMCIEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer,
+                                       stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+                                       JVMCICompiler::instance(), _debug_recorder, _dependencies, env, id,
+                                       false, _has_wide_vector, installed_code, compiled_code, speculation_log);
     cb = nm;
   }
 
@@ -513,6 +495,8 @@
 #endif
 
   _next_call_type = INVOKE_INVALID;
+
+  _has_wide_vector = false;
 }
 
 int CodeInstaller::estimate_stub_entries() {
@@ -856,7 +840,7 @@
 
   // address instruction = _instructions->start() + pc_offset;
   // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start();
-  _debug_recorder->add_safepoint(pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info));
+  _debug_recorder->add_safepoint(pc_offset, create_oop_map(debug_info));
   record_scope(pc_offset, debug_info);
   _debug_recorder->end_safepoint(pc_offset);
 }
@@ -891,7 +875,7 @@
   jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
 
   if (debug_info != NULL) {
-    _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info));
+    _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(debug_info));
     record_scope(next_pc_offset, debug_info);
   }
 
--- a/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Fri Jun 05 17:12:08 2015 +0200
@@ -70,6 +70,8 @@
   jobject       _comments_handle;
 #endif
 
+  bool          _has_wide_vector;
+
   MarkId        _next_call_type;
   address       _invoke_mark_pc;
 
@@ -139,6 +141,8 @@
   void site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site);
   void site_Mark(CodeBuffer& buffer, jint pc_offset, oop site);
 
+  OopMap* create_oop_map(oop debug_info);
+
   void record_scope(jint pc_offset, oop debug_info);
   void record_scope(jint pc_offset, oop code_pos, GrowableArray<ScopeValue*>* objects);
   void record_object_value(ObjectValue* sv, oop value, GrowableArray<ScopeValue*>* objects);
--- a/src/share/vm/jvmci/jvmciEnv.cpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/jvmci/jvmciEnv.cpp	Fri Jun 05 17:12:08 2015 +0200
@@ -483,6 +483,7 @@
                                 JVMCIEnv* env,
                                 int compile_id,
                                 bool has_unsafe_access,
+                                bool has_wide_vector,
                                 Handle installed_code,
                                 Handle compiled_code,
                                 Handle speculation_log) {
@@ -546,12 +547,7 @@
         }
       } else {
         nm->set_has_unsafe_access(has_unsafe_access);
-#ifdef TARGET_ARCH_x86
-        // It might be preferable to set this only for methods which
-        // use vector instructions but we currently don't track this
-        // and it probably wouldn't make much difference.
-        nm->set_has_wide_vectors(MaxVectorSize > 16);
-#endif
+        nm->set_has_wide_vectors(has_wide_vector);
 
         // Record successful registration.
         // (Put nm into the task handle *before* publishing to the Java heap.)
--- a/src/share/vm/jvmci/jvmciEnv.hpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/jvmci/jvmciEnv.hpp	Fri Jun 05 17:12:08 2015 +0200
@@ -157,6 +157,7 @@
                        JVMCIEnv*                 env,
                        int                       compile_id,
                        bool                      has_unsafe_access,
+                       bool                      has_wide_vector,
                        Handle                    installed_code,
                        Handle                    compiled_code,
                        Handle                    speculation_log);
--- a/src/share/vm/jvmci/jvmciJavaAccess.hpp	Fri Jun 05 17:11:50 2015 +0200
+++ b/src/share/vm/jvmci/jvmciJavaAccess.hpp	Fri Jun 05 17:12:08 2015 +0200
@@ -157,16 +157,14 @@
     objArrayOop_field(DebugInfo, virtualObjectMapping, "[Lcom/oracle/jvmci/meta/Value;")                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotReferenceMap)                                                                                                                             \
-    oop_field(HotSpotReferenceMap, registerRefMap, "Lcom/oracle/jvmci/hotspot/HotSpotReferenceMap$HotSpotOopMap;")                                             \
-    oop_field(HotSpotReferenceMap, frameRefMap, "Lcom/oracle/jvmci/hotspot/HotSpotReferenceMap$HotSpotOopMap;")                                                \
+    objArrayOop_field(HotSpotReferenceMap, objects, "[Lcom/oracle/jvmci/meta/Value;")                                                                          \
+    typeArrayOop_field(HotSpotReferenceMap, bytesPerElement, "[I")                                                                                             \
+    int_field(HotSpotReferenceMap, maxRegisterSize)                                                                                                            \
   end_class                                                                                                                                                    \
   start_class(RegisterSaveLayout)                                                                                                                              \
     objArrayOop_field(RegisterSaveLayout, registers, "[Lcom/oracle/jvmci/code/Register;")                                                                      \
     typeArrayOop_field(RegisterSaveLayout, slots, "[I")                                                                                                        \
   end_class                                                                                                                                                    \
-  start_class(HotSpotOopMap)                                                                                                                                   \
-    typeArrayOop_field(HotSpotOopMap, words, "[J")                                                                                                             \
-  end_class                                                                                                                                                    \
   start_class(BytecodeFrame)                                                                                                                                   \
     objArrayOop_field(BytecodeFrame, values, "[Lcom/oracle/jvmci/meta/Value;")                                                                                 \
     int_field(BytecodeFrame, numLocals)                                                                                                                        \
@@ -223,15 +221,9 @@
   start_class(RegisterValue)                                                                                                                                   \
     oop_field(RegisterValue, reg, "Lcom/oracle/jvmci/code/Register;")                                                                                          \
   end_class                                                                                                                                                    \
-  start_class(RegisterCategory)                                                                                                                                \
-    oop_field(RegisterCategory, name, "Ljava/lang/String;")                                                                                                    \
-    int_field(RegisterCategory, referenceMapOffset)                                                                                                            \
-    int_field(RegisterCategory, referenceMapShift)                                                                                                             \
-  end_class                                                                                                                                                    \
   start_class(code_Register)                                                                                                                                   \
     int_field(code_Register, number)                                                                                                                           \
     int_field(code_Register, encoding)                                                                                                                         \
-    oop_field(code_Register, registerCategory, "Lcom/oracle/jvmci/code/Register$RegisterCategory;")                                                            \
   end_class                                                                                                                                                    \
   start_class(StackSlot)                                                                                                                                       \
     int_field(StackSlot, offset)                                                                                                                               \