changeset 21255:ccddbb1409d2

[SPARC] Implement Narrow OOPS
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Wed, 06 May 2015 17:13:50 +0200
parents 7a49a2763a7a
children 0927730ed87f
files graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp src/share/vm/runtime/arguments.cpp
diffstat 5 files changed, 303 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed May 06 17:10:58 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed May 06 17:13:50 2015 +0200
@@ -49,6 +49,7 @@
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
+import com.oracle.graal.sparc.*;
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
@@ -214,6 +215,17 @@
     }
 
     @Override
+    public boolean canInlineConstant(JavaConstant c) {
+        if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
+            return true;
+        } else if (c instanceof HotSpotObjectConstant) {
+            return ((HotSpotObjectConstant) c).isCompressed();
+        } else {
+            return super.canInlineConstant(c);
+        }
+    }
+
+    @Override
     public void emitStore(LIRKind kind, Value address, Value inputVal, LIRFrameState state) {
         SPARCAddressValue storeAddress = asAddressValue(address);
         if (isConstant(inputVal)) {
@@ -243,15 +255,85 @@
     }
 
     @Override
+    protected SPARCLIRInstruction createMove(AllocatableValue dst, Value src) {
+        if (src instanceof JavaConstant) {
+            return new SPARCHotSpotMove.HotSpotLoadConstantOp(dst, (JavaConstant) src);
+        } else {
+            return super.createMove(dst, src);
+        }
+    }
+
+    @Override
+    public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
+                    double trueDestinationProbability) {
+        Value localX = x;
+        Value localY = y;
+        if (localX instanceof HotSpotObjectConstant) {
+            localX = load(localX);
+        }
+        if (localY instanceof HotSpotObjectConstant) {
+            localY = load(localY);
+        }
+        super.emitCompareBranch(cmpKind, localX, localY, cond, unorderedIsTrue, trueDestination, falseDestination, trueDestinationProbability);
+    }
+
+    @Override
+    protected boolean emitCompare(PlatformKind cmpKind, Value a, Value b) {
+        Value localA = a;
+        Value localB = b;
+        if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(localA)) {
+            localA = SPARC.g0.asValue(LIRKind.value(Kind.Int));
+        } else if (localA instanceof HotSpotObjectConstant) {
+            localA = load(localA);
+        }
+        if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(localB)) {
+            localB = SPARC.g0.asValue(LIRKind.value(Kind.Int));
+        } else if (localB instanceof HotSpotObjectConstant) {
+            localB = load(localB);
+        }
+        return super.emitCompare(cmpKind, localA, localB);
+    }
+
+    @Override
     public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
-        // TODO
-        throw GraalInternalError.unimplemented();
+        LIRKind inputKind = pointer.getLIRKind();
+        assert inputKind.getPlatformKind() == Kind.Long || inputKind.getPlatformKind() == Kind.Object;
+        if (inputKind.isReference(0)) {
+            // oop
+            Variable result = newVariable(LIRKind.reference(Kind.Int));
+            append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+            return result;
+        } else {
+            // metaspace pointer
+            Variable result = newVariable(LIRKind.value(Kind.Int));
+            AllocatableValue base = Value.ILLEGAL;
+            if (encoding.base != 0) {
+                base = emitMove(JavaConstant.forLong(encoding.base));
+            }
+            append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+            return result;
+        }
     }
 
     @Override
     public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
-        // TODO
-        throw GraalInternalError.unimplemented();
+        LIRKind inputKind = pointer.getLIRKind();
+        assert inputKind.getPlatformKind() == Kind.Int;
+        if (inputKind.isReference(0)) {
+            // oop
+            Variable result = newVariable(LIRKind.reference(Kind.Object));
+            append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+            return result;
+        } else {
+            // metaspace pointer
+            Variable result = newVariable(LIRKind.value(Kind.Long));
+            AllocatableValue base = Value.ILLEGAL;
+            if (encoding.base != 0) {
+                base = emitMove(JavaConstant.forLong(encoding.base));
+            }
+            append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+            return result;
+        }
     }
 
     /**
@@ -360,8 +442,16 @@
 
     public void emitNullCheck(Value address, LIRFrameState state) {
         PlatformKind kind = address.getLIRKind().getPlatformKind();
-        assert kind == Kind.Object || kind == Kind.Long : address + " - " + kind + " not an object!";
-        append(new NullCheckOp(load(address), state));
+        if (address.getLIRKind().getPlatformKind() == Kind.Int) {
+            CompressEncoding encoding = config.getOopEncoding();
+            Value uncompressed;
+            uncompressed = emitUncompress(address, encoding, false);
+
+            append(new NullCheckOp(load(uncompressed), state));
+        } else {
+            assert kind == Kind.Object || kind == Kind.Long : address + " - " + kind + " not an object!";
+            append(new NullCheckOp(load(address), state));
+        }
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java	Wed May 06 17:13:50 2015 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.sparc;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Annul;
+import com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCAssembler.RCondition;
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.sparc.*;
+
+public class SPARCHotSpotMove {
+
+    public static final class HotSpotLoadConstantOp extends SPARCLIRInstruction implements MoveOp {
+        public static final LIRInstructionClass<HotSpotLoadConstantOp> TYPE = LIRInstructionClass.create(HotSpotLoadConstantOp.class);
+
+        @Def({REG}) private AllocatableValue result;
+        private final JavaConstant input;
+
+        public HotSpotLoadConstantOp(AllocatableValue result, JavaConstant input) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            assert isRegister(result);
+            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(input)) {
+                masm.mov(0, asRegister(result));
+            } else if (input instanceof HotSpotObjectConstant) {
+                boolean compressed = ((HotSpotObjectConstant) input).isCompressed();
+                if (crb.target.inlineObjects) {
+                    crb.recordInlineDataInCode(input);
+                    if (compressed) {
+                        masm.sethi(0xDEADDEAD >>> 10, asRegister(result));
+                        masm.add(asRegister(result), 0xAD & 0x3F, asRegister(result));
+                    } else {
+                        new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(result), true).emit(masm);
+                    }
+                } else {
+                    GraalInternalError.unimplemented();
+                }
+            } else if (input instanceof HotSpotMetaspaceConstant) {
+                assert input.getKind() == Kind.Int || input.getKind() == Kind.Long;
+                boolean compressed = input.getKind() == Kind.Int;
+                boolean isImmutable = GraalOptions.ImmutableCode.getValue();
+                boolean generatePIC = GraalOptions.GeneratePIC.getValue();
+                crb.recordInlineDataInCode(input);
+                if (compressed) {
+                    if (isImmutable && generatePIC) {
+                        GraalInternalError.unimplemented();
+                    } else {
+                        new SPARCMacroAssembler.Setx(input.asInt(), asRegister(result), true).emit(masm);
+                    }
+                } else {
+                    if (isImmutable && generatePIC) {
+                        GraalInternalError.unimplemented();
+                    } else {
+                        new SPARCMacroAssembler.Setx(input.asLong(), asRegister(result), true).emit(masm);
+                    }
+                }
+            } else {
+                SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
+            }
+        }
+
+        public Value getInput() {
+            return input;
+        }
+
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    public static final class CompressPointer extends SPARCLIRInstruction {
+        public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
+
+        private final CompressEncoding encoding;
+        private final boolean nonNull;
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue input;
+        @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
+
+        public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+            this.baseRegister = baseRegister;
+            this.encoding = encoding;
+            this.nonNull = nonNull;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
+
+            Register resReg = asRegister(result);
+            if (encoding.base != 0) {
+                Register baseReg = asRegister(baseRegister);
+                if (!nonNull) {
+                    masm.cmp(resReg, baseReg);
+                    masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg);
+                }
+                masm.sub(resReg, baseReg, resReg);
+            }
+
+            if (encoding.shift != 0) {
+                masm.srlx(resReg, encoding.shift, resReg);
+            }
+        }
+    }
+
+    public static final class UncompressPointer extends SPARCLIRInstruction {
+        public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
+
+        private final CompressEncoding encoding;
+        private final boolean nonNull;
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue input;
+        @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
+
+        public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+            this.baseRegister = baseRegister;
+            this.encoding = encoding;
+            this.nonNull = nonNull;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
+
+            Register resReg = asRegister(result);
+            if (encoding.shift != 0) {
+                masm.sllx(resReg, 32, resReg);
+                masm.srlx(resReg, 32 - encoding.shift, resReg);
+            }
+
+            if (encoding.base != 0) {
+                if (nonNull) {
+                    masm.add(resReg, asRegister(baseRegister), resReg);
+                } else {
+                    masm.cmp(resReg, resReg);
+
+                    Label done = new Label();
+                    masm.bpr(RCondition.Rc_nz, Annul.ANNUL, done, BranchPredict.PREDICT_TAKEN, resReg);
+                    masm.add(asRegister(baseRegister), resReg, resReg);
+                    masm.bind(done);
+                }
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed May 06 17:10:58 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Wed May 06 17:13:50 2015 +0200
@@ -65,7 +65,9 @@
     protected BytecodeFrame computeFrameForState(FrameState state) {
         if (isPlaceholderBci(state.bci) && state.bci != BytecodeFrame.BEFORE_BCI) {
             // This is really a hard error since an incorrect state could crash hotspot
-            throw GraalInternalError.shouldNotReachHere("Invalid state " + BytecodeFrame.getPlaceholderBciName(state.bci) + " " + state);
+            throw new BailoutException(true, "Invalid state " + BytecodeFrame.getPlaceholderBciName(state.bci) + " " + state);
+// throw GraalInternalError.shouldNotReachHere("Invalid state " +
+// BytecodeFrame.getPlaceholderBciName(state.bci) + " " + state);
         }
         return super.computeFrameForState(state);
     }
--- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Wed May 06 17:10:58 2015 +0200
+++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.cpp	Wed May 06 17:13:50 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,13 @@
   Handle obj = HotSpotObjectConstantImpl::object(constant);
   jobject value = JNIHandles::make_local(obj());
   if (HotSpotObjectConstantImpl::compressed(constant)) {
-    fatal("unimplemented: narrow oop relocation");
+#ifdef _LP64
+    int oop_index = _oop_recorder->find_index(value);
+    RelocationHolder rspec = oop_Relocation::spec(oop_index);
+    _instructions->relocate(pc, rspec, 1);
+#else
+    fatal("compressed oop on 32bit");
+#endif
   } else {
     NativeMovConstReg* move = nativeMovConstReg_at(pc);
     move->set_data((intptr_t) value);
--- a/src/share/vm/runtime/arguments.cpp	Wed May 06 17:10:58 2015 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Wed May 06 17:13:50 2015 +0200
@@ -1502,9 +1502,9 @@
   // to use UseCompressedOops is InitialHeapSize.
   size_t max_heap_size = MAX2(MaxHeapSize, InitialHeapSize);
   // Set default on graal with sparc to not use compressed oops as long they are not implemented
-#if defined(GRAAL) && defined(TARGET_ARCH_sparc)
+/*#if defined(GRAAL) && defined(TARGET_ARCH_sparc)
   FLAG_SET_DEFAULT(UseCompressedOops, false);
-#else // if !(GRAAL && SOLARIS)
+#else // if !(GRAAL && SOLARIS)*/
   if (max_heap_size <= max_heap_for_compressed_oops()) {
 #if !defined(COMPILER1) || defined(TIERED)
     if (FLAG_IS_DEFAULT(UseCompressedOops)) {
@@ -1529,7 +1529,7 @@
   }
 #endif // _LP64
 #endif // ZERO
-#endif // !(GRAAL && SOLARIS)
+//#endif // !(GRAAL && SOLARIS)
 }