changeset 8490:1567c6cc6561

Towards porting G1 WBs
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Wed, 20 Feb 2013 16:15:43 +0100
parents 92d21814cf7b
children 9cf5e381df05
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/WriteBarrierSnippets.java src/cpu/x86/vm/graalRuntime_x86.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp
diffstat 14 files changed, 434 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Wed Feb 20 16:15:43 2013 +0100
@@ -36,7 +36,8 @@
 import static com.oracle.graal.hotspot.nodes.ThreadIsInterruptedStubCall.*;
 import static com.oracle.graal.hotspot.nodes.VMErrorNode.*;
 import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*;
-import static com.oracle.graal.hotspot.nodes.WriteBarrierStubCall.*;
+import static com.oracle.graal.hotspot.nodes.WriteBarrierPreStubCall.*;
+import static com.oracle.graal.hotspot.nodes.WriteBarrierPostStubCall.*;
 import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.DecryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*;
 import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*;
@@ -88,11 +89,16 @@
                 /* arg0: object */ javaCallingConvention(Kind.Object,
                 /* arg1:   lock */                       word));
 
-       addRuntimeCall(G1_WB_SLOW, config.g1WBSlowStub,
-                        /*        temps */ null,
-                        /*          ret */ ret(Kind.Void),
-                        /* arg0: object */ javaCallingConvention(Kind.Object));
-       
+       addRuntimeCall(WBPRECALL, config.wbPreCallStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0: object */ javaCallingConvention(Kind.Object));
+
+       addRuntimeCall(WBPOSTCALL, config.wbPostCallStub,
+                /*        temps */ null,
+                /*          ret */ ret(Kind.Void),
+                /* arg0: object */ javaCallingConvention(Kind.Object));
+
         addRuntimeCall(MONITOREXIT, config.monitorExitStub,
                 /*        temps */ null,
                 /*          ret */ ret(Kind.Void),
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Feb 20 16:15:43 2013 +0100
@@ -213,6 +213,16 @@
     public boolean isPollingPageFar;
 
     /**
+     * G1 Collector Related Values.
+     */
+    public int g1CardQueueIndexOffset;
+    public int g1CardQueueBufferOffset;
+    public int logOfHRGrainBytes;
+    public int g1SATBQueueMarkingOffset;
+    public int g1SATBQueueIndexOffset;
+    public int g1SATBQueueBufferOffset;
+
+    /**
      * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
      */
     public int classMirrorOffset;
@@ -316,7 +326,8 @@
     public long handleDeoptStub;
     public long monitorEnterStub;
     public long monitorExitStub;
-    public long g1WBSlowStub;
+    public long wbPreCallStub;
+    public long wbPostCallStub;
     public long verifyOopStub;
     public long vmErrorStub;
     public long deoptimizeStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Feb 20 16:15:43 2013 +0100
@@ -609,9 +609,18 @@
             graph.replaceFixedWithFixed(storeField, memoryWrite);
             FixedWithNextNode last = memoryWrite;
             if (field.getKind() == Kind.Object && !memoryWrite.value().objectStamp().alwaysNull()) {
-                FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object()));
-                graph.addAfterFixed(memoryWrite, writeBarrier);
-                last = writeBarrier;
+                if (!config.useG1GC) {
+                    FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(memoryWrite.object()));
+                    graph.addAfterFixed(memoryWrite, writeBarrier);
+                    last = writeBarrier;
+                } else {
+                    WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(memoryWrite.object()));
+                    WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(memoryWrite.object()));
+                    graph.addBeforeFixed(memoryWrite, writeBarrierPre);
+                    graph.addAfterFixed(memoryWrite, writeBarrierPost);
+                    last = writeBarrierPost;
+
+                }
             }
             if (storeField.isVolatile()) {
                 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
@@ -627,12 +636,24 @@
                 ResolvedJavaType type = cas.object().objectStamp().type();
                 if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
                     // Use a field write barrier since it's not an array store
-                    FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(cas.object()));
-                    graph.addAfterFixed(cas, writeBarrier);
+                    if (!config.useG1GC) {
+                        FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(cas.object()));
+                        graph.addAfterFixed(cas, writeBarrier);
+                    } else {
+                        WriteBarrierPre writeBarrierPre = graph.add(new WriteBarrierPre(cas.object()));
+                        WriteBarrierPost writeBarrierPost = graph.add(new WriteBarrierPost(cas.object()));
+                        graph.addAfterFixed(cas, writeBarrierPre);
+                        graph.addAfterFixed(cas, writeBarrierPost);
+                    }
                 } else {
                     // This may be an array store so use an array write barrier
-                    LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false);
-                    graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location)));
+                    if (!config.useG1GC) {
+                        LocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, false);
+                        graph.addAfterFixed(cas, graph.add(new ArrayWriteBarrier(cas.object(), location)));
+                    } else {
+                        graph.addBeforeFixed(cas, graph.add(new WriteBarrierPre(cas.object())));
+                        graph.addAfterFixed(cas, graph.add(new WriteBarrierPost(cas.object())));
+                    }
                 }
             }
         } else if (n instanceof LoadIndexedNode) {
@@ -678,7 +699,12 @@
             graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
 
             if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) {
-                graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
+                if (!config.useG1GC) {
+                    graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
+                } else {
+                    graph.addBeforeFixed(memoryWrite, graph.add(new WriteBarrierPre(array)));
+                    graph.addAfterFixed(memoryWrite, graph.add(new WriteBarrierPost(array)));
+                }
             }
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
@@ -701,14 +727,23 @@
                 // WriteBarrier writeBarrier;
                 if (type != null && !type.isArray() && !MetaUtil.isJavaLangObject(type)) {
                     // Use a field write barrier since it's not an array store
-                    FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(object));
-                    graph.addAfterFixed(write, writeBarrier);
+                    if (!config.useG1GC) {
+                        FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(object));
+                        graph.addAfterFixed(write, writeBarrier);
+                    } else {
+                        graph.addBeforeFixed(write, graph.add(new WriteBarrierPre(object)));
+                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object)));
+                    }
                 } else {
                     // This may be an array store so use an array write barrier
-                    ArrayWriteBarrier writeBarrier = graph.add(new ArrayWriteBarrier(object, location));
-                    graph.addAfterFixed(write, writeBarrier);
+                    if (!config.useG1GC) {
+                        ArrayWriteBarrier writeBarrier = graph.add(new ArrayWriteBarrier(object, location));
+                        graph.addAfterFixed(write, writeBarrier);
+                    } else {
+                        graph.addBeforeFixed(write, graph.add(new WriteBarrierPre(object)));
+                        graph.addAfterFixed(write, graph.add(new WriteBarrierPost(object)));
+                    }
                 }
-
             }
         } else if (n instanceof LoadHubNode) {
             LoadHubNode loadHub = (LoadHubNode) n;
@@ -744,6 +779,10 @@
             writeBarrierSnippets.lower((FieldWriteBarrier) n, tool);
         } else if (n instanceof ArrayWriteBarrier) {
             writeBarrierSnippets.lower((ArrayWriteBarrier) n, tool);
+        } else if (n instanceof WriteBarrierPre) {
+            writeBarrierSnippets.lower((WriteBarrierPre) n, tool);
+        } else if (n instanceof WriteBarrierPost) {
+            writeBarrierSnippets.lower((WriteBarrierPost) n, tool);
         } else if (n instanceof TLABAllocateNode) {
             newObjectSnippets.lower((TLABAllocateNode) n, tool);
         } else if (n instanceof InitializeObjectNode) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayWriteBarrier.java	Wed Feb 20 16:15:43 2013 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPost.java	Wed Feb 20 16:15:43 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+public final class WriteBarrierPost extends WriteBarrier implements Lowerable {
+
+    @Input private ValueNode object;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public WriteBarrierPost(ValueNode object) {
+        this.object = object;
+    }
+
+    public void lower(LoweringTool generator) {
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Wed Feb 20 16:15:43 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's {@code graal_monitorenter} stub.
+ */
+public class WriteBarrierPostStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private final ValueNode object;
+    public static final Descriptor WBPOSTCALL = new Descriptor("wbpostcall", true, void.class, Object.class);
+
+    public WriteBarrierPostStubCall(ValueNode object) {
+        super(StampFactory.forVoid());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPostStubCall.WBPOSTCALL);
+        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Object hub);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPre.java	Wed Feb 20 16:15:43 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+public final class WriteBarrierPre extends WriteBarrier implements Lowerable {
+
+    @Input private ValueNode object;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public WriteBarrierPre(ValueNode object) {
+        this.object = object;
+    }
+
+    public void lower(LoweringTool generator) {
+        generator.getRuntime().lower(this, generator);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Wed Feb 20 16:15:43 2013 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to HotSpot's {@code graal_monitorenter} stub.
+ */
+public class WriteBarrierPreStubCall extends FixedWithNextNode implements LIRGenLowerable {
+
+    @Input private final ValueNode object;
+    public static final Descriptor WBPRECALL = new Descriptor("wbprecall", true, void.class, Object.class);
+
+    public WriteBarrierPreStubCall(ValueNode object) {
+        super(StampFactory.forVoid());
+        this.object = object;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPreStubCall.WBPRECALL);
+        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+    }
+
+    @NodeIntrinsic
+    public static native void call(Object hub);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java	Wed Feb 20 16:15:43 2013 +0100
@@ -227,6 +227,36 @@
     }
 
     @Fold
+    public static int g1CardQueueIndexOffset() {
+        return config().g1CardQueueIndexOffset;
+    }
+
+    @Fold
+    public static int g1CardQueueBufferOffset() {
+        return config().g1CardQueueBufferOffset;
+    }
+
+    @Fold
+    public static int logOfHRGrainBytes() {
+        return config().logOfHRGrainBytes;
+    }
+
+    @Fold
+    public static int g1SATBQueueMarkingOffset() {
+        return config().g1SATBQueueMarkingOffset;
+    }
+
+    @Fold
+    public static int g1SATBQueueIndexOffset() {
+        return config().g1SATBQueueIndexOffset;
+    }
+
+    @Fold
+    public static int g1SATBQueueBufferOffset() {
+        return config().g1SATBQueueBufferOffset;
+    }
+
+    @Fold
     public static int superCheckOffsetOffset() {
         return config().superCheckOffsetOffset;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/WriteBarrierSnippets.java	Tue Feb 19 17:57:14 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/WriteBarrierSnippets.java	Wed Feb 20 16:15:43 2013 +0100
@@ -40,13 +40,72 @@
 public class WriteBarrierSnippets implements SnippetsInterface {
 
     @Snippet
-    public static void g1PreWriteBarrier(@Parameter("object") Object object) {
+    public static void g1PreWriteBarrier(@Parameter("object") Object object, @Parameter("previousValue") Word previousValue, @Parameter("load") boolean doLoad) {
+        Word thread = thread();
+        Pointer oop = Word.fromObject(object);
+        Word markingAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueMarkingOffset());
+        Word bufferAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueBufferOffset());
+        Word indexAddress = thread.add(HotSpotSnippetUtils.g1SATBQueueIndexOffset());
+        Word prevValue = previousValue;
 
+        Word marking = markingAddress.readWord(0);
+        if (marking.notEqual(Word.zero())) {
+            if (doLoad) {
+                prevValue = (Word) Word.fromObject(oop.readObject(0));
+            }
+
+            if (prevValue.notEqual(Word.zero())) {
+                if (indexAddress.readInt(0) != 0) {
+                    Word nextIndex = indexAddress.subtract(Word.signed(HotSpotSnippetUtils.wordSize()));
+                    Word nextIndexX = nextIndex;
+                    Word logAddress = bufferAddress.add(nextIndexX);
+                    logAddress.writeWord(0, prevValue);
+                    indexAddress.writeWord(0, nextIndex);
+                } else {
+                    WriteBarrierPostStubCall.call(object);
+                }
+            }
+        }
     }
 
     @Snippet
-    public static void g1PostWriteBarrier(@Parameter("object") Object object) {
+    public static void g1PostWriteBarrier(@Parameter("object") Object object, @Parameter("value") Word value) {
+        Word thread = thread();
+        Pointer oop = Word.fromObject(object);
+
+        Word bufferAddress = thread.add(HotSpotSnippetUtils.g1CardQueueBufferOffset());
+        Word indexAddress = thread.add(HotSpotSnippetUtils.g1CardQueueIndexOffset());
+
+        // Card Table
+        Word base = (Word) oop.unsignedShiftRight(cardTableShift());
+        long startAddress = cardTableStart();
+        int displacement = 0;
+        if (((int) startAddress) == startAddress) {
+            displacement = (int) startAddress;
+        } else {
+            base = base.add(Word.unsigned(cardTableStart()));
+        }
 
+        if (value != null) {
+            Word xorResult = (((Word) oop.xor(value)).unsignedShiftRight(HotSpotSnippetUtils.logOfHRGrainBytes()));
+            if (xorResult.notEqual(Word.zero())) {
+                if (value.notEqual(Word.zero())) {
+                    Word cardValue = base.readWord(displacement);
+                    if (cardValue.notEqual(Word.zero())) {
+                        base.writeWord(displacement, Word.zero()); // smash zero into card
+                        if (indexAddress.readInt(0) != 0) {
+                            Word nextIndex = indexAddress.subtract(Word.signed(HotSpotSnippetUtils.wordSize()));
+                            Word nextIndexX = nextIndex;
+                            Word logAddress = bufferAddress.add(nextIndexX);
+                            logAddress.writeWord(0, base.add(displacement));
+                            indexAddress.writeWord(0, nextIndex);
+                        } else {
+                            WriteBarrierPostStubCall.call(object);
+                        }
+                    }
+                }
+            }
+        }
     }
 
     private static void trace(boolean enabled, String format, WordBase value) {
@@ -68,7 +127,7 @@
             base = base.add(Word.unsigned(cardTableStart()));
         }
         base.writeWord(displacement, Word.zero());
-        WriteBarrierStubCall.call(object);
+        // WriteBarrierStubCall.call(object);
     }
 
     @Snippet
@@ -104,7 +163,7 @@
         }
 
         public void lower(ArrayWriteBarrier arrayWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = !useG1GC ? serialArrayWriteBarrier : serialArrayWriteBarrier;
+            ResolvedJavaMethod method = serialArrayWriteBarrier;
             Key key = new Key(method);
             Arguments arguments = new Arguments();
             arguments.add("object", arrayWriteBarrier.object());
@@ -113,12 +172,30 @@
         }
 
         public void lower(FieldWriteBarrier fieldWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) {
-            ResolvedJavaMethod method = !useG1GC ? serialFieldWriteBarrier : serialFieldWriteBarrier;
+            ResolvedJavaMethod method = serialFieldWriteBarrier;
             Key key = new Key(method);
             Arguments arguments = new Arguments();
             arguments.add("object", fieldWriteBarrier.object());
             SnippetTemplate template = cache.get(key, assumptions);
             template.instantiate(runtime, fieldWriteBarrier, DEFAULT_REPLACER, arguments);
         }
+
+        public void lower(WriteBarrierPre writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) {
+            ResolvedJavaMethod method = g1PreWriteBarrier;
+            Key key = new Key(method);
+            Arguments arguments = new Arguments();
+            arguments.add("object", writeBarrierPre.object());
+            SnippetTemplate template = cache.get(key, assumptions);
+            template.instantiate(runtime, writeBarrierPre, DEFAULT_REPLACER, arguments);
+        }
+
+        public void lower(WriteBarrierPost writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) {
+            ResolvedJavaMethod method = g1PostWriteBarrier;
+            Key key = new Key(method);
+            Arguments arguments = new Arguments();
+            arguments.add("object", writeBarrierPost.object());
+            SnippetTemplate template = cache.get(key, assumptions);
+            template.instantiate(runtime, writeBarrierPost, DEFAULT_REPLACER, arguments);
+        }
     }
 }
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp	Tue Feb 19 17:57:14 2013 +0100
+++ b/src/cpu/x86/vm/graalRuntime_x86.cpp	Wed Feb 20 16:15:43 2013 +0100
@@ -1191,25 +1191,43 @@
       }
       __ ret(0);
       break;
-    }
-    case graal_g1_wb_slow_id: {
-          Register obj = j_rarg0;
-          {
-            GraalStubFrame f(sasm, "graal_g1_wb_slow", dont_gc_arguments);
-            OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
+   }
+   case graal_wb_pre_call_id: {
+      Register obj = j_rarg0;
+      {
+        GraalStubFrame f(sasm, "graal_wb_pre_call", dont_gc_arguments);
+        OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
+
+        // note: really a leaf routine but must setup last java sp
+        //       => use call_RT for now (speed can be improved by
+        //       doing last java sp setup manually)
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_wb_pre_call), obj);
 
-            // note: really a leaf routine but must setup last java sp
-            //       => use call_RT for now (speed can be improved by
-            //       doing last java sp setup manually)
-            int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_g1_wb_slow), obj);
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, map);
+        restore_live_registers(sasm, save_fpu_registers);
+      }
+      __ ret(0);
+      break;
+   }
+   case graal_wb_post_call_id: {
+      Register obj = j_rarg0;
+      {
+        GraalStubFrame f(sasm, "graal_wb_post_call", dont_gc_arguments);
+        OopMap* map = save_live_registers(sasm, 2, save_fpu_registers);
 
-            oop_maps = new OopMapSet();
-            oop_maps->add_gc_map(call_offset, map);
-            restore_live_registers(sasm, save_fpu_registers);
-          }
-          __ ret(0);
-          break;
-        }
+        // note: really a leaf routine but must setup last java sp
+        //       => use call_RT for now (speed can be improved by
+        //       doing last java sp setup manually)
+        int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_wb_post_call), obj);
+
+        oop_maps = new OopMapSet();
+        oop_maps->add_gc_map(call_offset, map);
+        restore_live_registers(sasm, save_fpu_registers);
+      }
+      __ ret(0);
+      break;
+   }
    case graal_identity_hash_code_id: {
       Register obj = j_rarg0; // Incoming
       __ set_info("identity_hash_code", dont_gc_arguments);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Tue Feb 19 17:57:14 2013 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Feb 20 16:15:43 2013 +0100
@@ -38,6 +38,7 @@
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalVMToCompiler.hpp"
 #include "graal/graalVmIds.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
 
 
 Method* getMethodFromHotSpotMethod(oop hotspot_method) {
@@ -720,7 +721,8 @@
   set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack()));
   set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id)));
   set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id)));
-  set_long("g1WBSlowStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_g1_wb_slow_id)));
+  set_long("wbPreCallStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_wb_pre_call_id)));
+  set_long("wbPostCallStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_wb_post_call_id)));
   set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id)));
   set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id)));
   set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap()));
@@ -764,7 +766,13 @@
   set_int("deoptActionReinterpret", Deoptimization::Action_reinterpret);
   set_int("deoptActionMakeNotEntrant", Deoptimization::Action_make_not_entrant);
   set_int("deoptActionMakeNotCompilable", Deoptimization::Action_make_not_compilable);
+  set_int("g1CardQueueIndexOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()));
+  set_int("g1CardQueueBufferOffset", in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()));
+  set_int("logOfHRGrainBytes", HeapRegion::LogOfHRGrainBytes);
 
+  set_int("g1SATBQueueMarkingOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()));
+  set_int("g1SATBQueueIndexOffset", in_bytes(JavaThread::satb_mark_queue_offset() +  PtrQueue::byte_offset_of_index()));
+  set_int("g1SATBQueueBufferOffset", in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()));
 
   BarrierSet* bs = Universe::heap()->barrier_set();
   switch (bs->kind()) {
--- a/src/share/vm/graal/graalRuntime.cpp	Tue Feb 19 17:57:14 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Feb 20 16:15:43 2013 +0100
@@ -483,8 +483,12 @@
   }
 JRT_END
 
-JRT_LEAF(void, GraalRuntime::graal_g1_wb_slow(JavaThread* thread, oopDesc* obj))
-    tty->print_cr("HELLO WRITE BARRIER");
+JRT_LEAF(void, GraalRuntime::graal_wb_pre_call(JavaThread* thread, oopDesc* obj))
+    tty->print_cr("HELLO PRE WRITE BARRIER");
+JRT_END
+
+JRT_LEAF(void, GraalRuntime::graal_wb_post_call(JavaThread* thread, oopDesc* obj))
+    tty->print_cr("HELLO POST WRITE BARRIER");
 JRT_END
 
 JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock))
--- a/src/share/vm/graal/graalRuntime.hpp	Tue Feb 19 17:57:14 2013 +0100
+++ b/src/share/vm/graal/graalRuntime.hpp	Wed Feb 20 16:15:43 2013 +0100
@@ -103,7 +103,8 @@
   stub(graal_log_primitive)           \
   stub(graal_identity_hash_code)      \
   stub(graal_thread_is_interrupted)   \
-  stub(graal_g1_wb_slow)              \
+  stub(graal_wb_pre_call)             \
+  stub(graal_wb_post_call)             \
   last_entry(number_of_ids)
 
 #define DECLARE_STUB_ID(x)       x ## _id ,
@@ -141,7 +142,8 @@
 
   static address exception_handler_for_pc(JavaThread* thread);
 
-  static void graal_g1_wb_slow(JavaThread* thread, oopDesc* obj);
+  static void graal_wb_pre_call(JavaThread* thread, oopDesc* obj);
+  static void graal_wb_post_call(JavaThread* thread, oopDesc* obj);
   static void graal_create_null_exception(JavaThread* thread);
   static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index);
   static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);