diff graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java @ 9885:ed86945795d5

Add Compressed Oops support in LIR
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Tue, 04 Jun 2013 18:06:57 +0200
parents cbf274a92e5b
children 9d0031cf5df9
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Jun 04 17:14:51 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Jun 04 18:06:57 2013 +0200
@@ -45,9 +45,18 @@
 import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.StandardOp.PlaceholderOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapCompressedOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadCompressedOop;
+import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreCompressedOop;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
+import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -391,4 +400,78 @@
             op.savedRbp = savedRbp;
         }
     }
+
+    private static boolean isCompressCandidate(DeoptimizingNode access) {
+        return access != null && ((HeapAccess) access).compress();
+    }
+
+    @Override
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) {
+        AMD64AddressValue loadAddress = asAddressValue(address);
+        Variable result = newVariable(kind);
+        assert access != null || access instanceof HeapAccess;
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new LoadCompressedOop(kind, result, scratch, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift,
+                            runtime().config.logMinObjAlignment));
+        } else {
+            append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null));
+        }
+        return result;
+    }
+
+    @Override
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) {
+        AMD64AddressValue storeAddress = asAddressValue(address);
+        LIRFrameState state = access != null ? state(access) : null;
+        if (isConstant(inputVal)) {
+            Constant c = asConstant(inputVal);
+            if (canStoreConstant(c)) {
+                append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access)));
+                return;
+            }
+        }
+        Variable input = load(inputVal);
+        if (runtime().config.useCompressedOops && isCompressCandidate(access)) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new StoreCompressedOop(kind, storeAddress, input, scratch, state, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new StoreOp(kind, storeAddress, input, state));
+        }
+    }
+
+    @Override
+    public void visitCompareAndSwap(CompareAndSwapNode node) {
+        Kind kind = node.newValue().kind();
+        assert kind == node.expected().kind();
+
+        Value expected = loadNonConst(operand(node.expected()));
+        Variable newValue = load(operand(node.newValue()));
+
+        AMD64AddressValue address;
+        int displacement = node.displacement();
+        Value index = operand(node.offset());
+        if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) {
+            assert !runtime.needsDataPatch(asConstant(index));
+            displacement += (int) asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, load(operand(node.object())), displacement);
+        } else {
+            address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement);
+        }
+
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expected);
+        if (runtime().config.useCompressedOops && node.compress()) {
+            assert kind == Kind.Object;
+            Variable scratch = newVariable(Kind.Long);
+            append(new CompareAndSwapCompressedOp(raxRes, address, raxRes, newValue, scratch, runtime().config.narrowOopBase, runtime().config.narrowOopShift, runtime().config.logMinObjAlignment));
+        } else {
+            append(new CompareAndSwapOp(raxRes, address, raxRes, newValue));
+        }
+        Variable result = newVariable(node.kind());
+        append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
+        setResult(node, result);
+    }
 }