# HG changeset patch # User Stefan Anzinger # Date 1404111026 -7200 # Node ID 51f39255712497a8faf9616d400fd6d9c99ce4e9 # Parent e497100e1fbff6aff4a0dc26413dd9d95bb7d938 [SPARC] Improving implicit exception handling on sparc diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/UnsafeAccess.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/AbstractObjectStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IllegalStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ObjectStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampProvider.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/VoidStamp.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- 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))); diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java --- 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); } diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java --- 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); } } diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCUncommonTrapStub.java --- /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; + } + +} diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMConstant.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMField.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMFlag.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.hotspotvmconfig/src/com/oracle/graal/hotspotvmconfig/HotSpotVMType.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/except/BC_ldiv2.java --- 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); + } + } diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java --- 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; diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningPhase.java diff -r e497100e1fbf -r 51f392557124 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java diff -r e497100e1fbf -r 51f392557124 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- 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 diff -r e497100e1fbf -r 51f392557124 test/whitelist_baseline.txt