changeset 16326:51f392557124

[SPARC] Improving implicit exception handling on sparc
author Stefan Anzinger <stefan.anzinger@gmail.com>
date Mon, 30 Jun 2014 08:50:26 +0200
parents e497100e1fbf
children 5f01f7c48d40
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCUncommonTrapStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConstant.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMField.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMFlag.java graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMType.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java src/cpu/sparc/vm/sharedRuntime_sparc.cpp test/whitelist_baseline.txt
diffstat 7 files changed, 193 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Jun 06 01:19:20 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Jun 30 08:50:26 2014 +0200
@@ -600,7 +600,7 @@
                 append(new BinaryRegReg(IDIV, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b)));
+                append(new BinaryRegReg(LDIV, result, a, loadNonConst(b), state));
                 break;
             case Float:
                 append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Fri Jun 06 01:19:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Jun 30 08:50:26 2014 +0200
@@ -62,7 +62,7 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
 
         link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
-        link(new SPARCDeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+        link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
 
         super.initialize(providers, config);
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Fri Jun 06 01:19:20 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Mon Jun 30 08:50:26 2014 +0200
@@ -24,10 +24,14 @@
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
@@ -48,8 +52,17 @@
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         // FIXME This is non-trivial. On SPARC we need to flush all register windows first before we
         // can patch the return address (see: frame::patch_pc).
-        // int frameSize = crb.frameMap.frameSize();
-        // new Stx(asRegister(address), new SPARCAddress(sp, frameSize));
-        new Ldx(new SPARCAddress(g0, 0x123), g0).emit(masm);
+        new Flushw().emit(masm);
+        int frameSize = crb.frameMap.frameSize();
+// new SPARCAssembler.Ldx(new SPARCAddress(o7, 1), g3).emit(masm);
+        // new Setx(8 * 15 - 1, g4, false).emit(masm);
+        new Mov(asLongReg(address), g4).emit(masm);
+        new Save(sp, -2000, sp).emit(masm);
+
+        new Sub(g4, 0, i7).emit(masm);
+        new Stx(i7, new SPARCAddress(fp, 8 * 15)).emit(masm);
+        new Restore(g0, g0, g0).emit(masm);
+        new Flushw().emit(masm);
+        // new Ldx(new SPARCAddress(g0, 0x123), g0).emit(masm);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCUncommonTrapStub.java	Mon Jun 30 08:50:26 2014 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.sparc.SPARC.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+final class SPARCUncommonTrapStub extends UncommonTrapStub {
+
+    private RegisterConfig registerConfig;
+
+    public SPARCUncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        // This is basically the maximum we can spare. All other G and O register are used.
+        Register[] allocatable = new Register[]{g1, g3, g4, g5, o0, o1, o2, o3, o4};
+        registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable);
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java	Fri Jun 06 01:19:20 2014 +0200
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java	Mon Jun 30 08:50:26 2014 +0200
@@ -49,4 +49,19 @@
         runTest("test", 11L, 0L);
     }
 
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 11L, 1000000000000L);
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        runTest("test", 1000000000000L, 11L);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        runTest("test", 1000000000000L, 0L);
+    }
+
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Fri Jun 06 01:19:20 2014 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Jun 30 08:50:26 2014 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.sparc.*;
 
 public enum SPARCArithmetic {
     // @formatter:off
@@ -123,17 +124,23 @@
         @Def({REG}) protected Value result;
         @Use({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
+        @State LIRFrameState state;
 
         public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y) {
+            this(opcode, result, x, y, null);
+        }
+
+        public BinaryRegReg(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
             this.opcode = opcode;
             this.result = result;
             this.x = x;
             this.y = y;
+            this.state = state;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            emit(crb, masm, opcode, result, x, y, null);
+            emit(crb, masm, opcode, result, x, y, state);
         }
 
         @Override
@@ -261,9 +268,9 @@
         }
     }
 
-    public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
+    public static void emit(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) {
         int exceptionOffset = -1;
-        if (isConstant(src1)) {
+        if (isConstant(src1) && !isConstant(src2)) {
             switch (opcode) {
                 case ISUB:
                     assert isSimm13(crb.asIntConst(src1));
@@ -276,6 +283,13 @@
                     throw GraalInternalError.unimplemented();
                     // new Sdivx(masm, asIntReg(src1), asIntReg(src2),
                     // asIntReg(dst));
+                case LDIV:
+                    int c = crb.asIntConst(src1);
+                    assert isSimm13(c);
+                    exceptionOffset = masm.position();
+                    new Sdivx(asLongReg(src2), c, asLongReg(dst)).emit(masm);
+                    new Mulx(asLongReg(src1), asLongReg(dst), asLongReg(dst)).emit(masm);
+                    break;
                 case FSUB:
                 case FDIV:
                 case DSUB:
@@ -339,7 +353,17 @@
                     new Mulx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LDIV:
-                    throw GraalInternalError.unimplemented();
+                    int c = crb.asIntConst(src2);
+                    exceptionOffset = masm.position();
+                    if (c == 0) { // Generate div by zero trap
+                        new Sdivx(SPARC.g0, 0, asLongReg(dst)).emit(masm);
+                    } else if (isConstant(src1)) { // Both are const, therefore just load the const
+                        new Setx(crb.asIntConst(src1) / c, asLongReg(dst), false).emit(masm);
+                    } else { // Otherwise try to divide
+                        assert isSimm13(crb.asLongConst(src2));
+                        new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(dst)).emit(masm);
+                    }
+                    break;
                 case LUDIV:
                     throw GraalInternalError.unimplemented();
                 case LAND:
@@ -421,6 +445,7 @@
                     new Mulx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LDIV:
+                    exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm);
                     break;
                 case LUDIV:
@@ -475,16 +500,42 @@
                     throw GraalInternalError.shouldNotReachHere();
             }
         }
-
         if (info != null) {
             assert exceptionOffset != -1;
             crb.recordImplicitException(exceptionOffset, info);
         }
     }
 
-    public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info) {
+    public static void emit(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCArithmetic opcode, Value dst, Value src1, Value src2, Value scratch1, Value scratch2, LIRFrameState info) {
         int exceptionOffset = -1;
-        if (isConstant(src1)) {
+        if (isConstant(src1) && isConstant(src2)) {
+            switch (opcode) {
+                case IREM: {
+                    int a = crb.asIntConst(src1);
+                    int b = crb.asIntConst(src2);
+                    if (b == 0) {
+                        exceptionOffset = masm.position();
+                        new Sdivx(SPARC.g0, 0, asIntReg(dst)).emit(masm);
+                    } else {
+                        new Setx(a % b, asIntReg(dst), false).emit(masm);
+                    }
+                }
+                    break;
+                case LREM: {
+                    long a = crb.asLongConst(src1);
+                    long b = crb.asLongConst(src2);
+                    if (b == 0) {
+                        exceptionOffset = masm.position();
+                        new Sdivx(SPARC.g0, 0, asLongReg(dst)).emit(masm);
+                    } else {
+                        new Setx(a % b, asLongReg(dst), false).emit(masm);
+                    }
+                }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere("not implemented");
+            }
+        } else if (isConstant(src1)) {
             switch (opcode) {
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -494,12 +545,14 @@
                 case IREM:
                     assert isSimm13(crb.asIntConst(src2));
                     new Sra(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
+                    exceptionOffset = masm.position();
                     new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
                     new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm);
                     new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
                     break;
                 case LREM:
                     assert isSimm13(crb.asIntConst(src2));
+                    exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm);
                     new Mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)).emit(masm);
                     new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
@@ -512,14 +565,14 @@
         } else {
             switch (opcode) {
                 case LREM:
+                    exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
-                    exceptionOffset = masm.position();
                     new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch2)).emit(masm);
                     new Sub(asLongReg(src1), asLongReg(scratch2), asLongReg(dst)).emit(masm);
                     break;
                 case IREM:
+                    exceptionOffset = masm.position();
                     new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    exceptionOffset = masm.position();
                     new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch2)).emit(masm);
                     new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
                     break;
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Fri Jun 06 01:19:20 2014 +0200
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Jun 30 08:50:26 2014 +0200
@@ -43,6 +43,9 @@
 #include "compiler/compileBroker.hpp"
 #include "shark/sharkCompiler.hpp"
 #endif
+#ifdef GRAAL
+#include "graal/graalJavaAccess.hpp"
+#endif
 
 #define __ masm->
 
@@ -3496,6 +3499,46 @@
   __ ba(cont);
   __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
 
+
+#ifdef GRAAL
+  masm->block_comment("BEGIN GRAAL");
+  int implicit_exception_uncommon_trap_offset = __ offset() - start;
+  //__ pushptr(Address(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset())));
+  __ ld_ptr(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()), O7);
+  //__ add(G0, 0x321, O7);
+  __ add(O7, -8, O7);
+  //__ st_ptr(I7, SP, I7->sp_offset_in_saved_window()*wordSize + STACK_BIAS);
+  // Save everything in sight.
+  masm->block_comment("save_live_regs");
+  (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
+  masm->block_comment("/save_live_regs");
+  //__ ld_ptr(G2_thread, in_bytes(JavaThread::graal_implicit_exception_pc_offset()), O7);
+  // fetch_unroll_info needs to call last_java_frame()
+  masm->block_comment("set_last_java_frame");
+  __ set_last_Java_frame(SP, NULL);
+  masm->block_comment("/set_last_java_frame");
+
+  //__ movl(c_rarg1, Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())));
+  __ ld(G2_thread, in_bytes(ThreadShadow::pending_deoptimization_offset()), O1);
+  //__ movl(Address(r15_thread, in_bytes(ThreadShadow::pending_deoptimization_offset())), -1);
+  __ sub(G0, 1, L1);
+  __ st_ptr(L1, G2_thread, in_bytes(ThreadShadow::pending_deoptimization_offset()));
+
+  __ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
+  __ mov(G2_thread, O0);
+  __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
+  __ delayed()->nop();
+  oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
+  __ get_thread();
+  __ add(O7, 8, O7);
+  __ reset_last_Java_frame();
+
+  Label after_fetch_unroll_info_call;
+  __ ba(after_fetch_unroll_info_call);
+  __ delayed()->nop(); // Delay slot
+  masm->block_comment("END GRAAL");
+#endif // GRAAL
+
   int exception_offset = __ offset() - start;
 
   // restore G2, the trampoline destroyed it
@@ -3573,6 +3616,9 @@
 
   __ reset_last_Java_frame();
 
+#ifdef GRAAL
+  __ bind(after_fetch_unroll_info_call);
+#endif
   // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
   // so this move will survive
 
@@ -3581,7 +3627,6 @@
   __ mov(O0, O2UnrollBlock->after_save());
 
   RegisterSaver::restore_result_registers(masm);
-
   Label noException;
   __ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException);
 
@@ -3638,6 +3683,9 @@
   masm->flush();
   _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words);
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#ifdef GRAAL
+  _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+#endif
 }
 
 #ifdef COMPILER2