# HG changeset patch # User twisti # Date 1374557209 25200 # Node ID e1fcdda228319cdef46b07cafe3f86372830af65 # Parent 22baf2a69f6d118ea8d06a695e8e2428b7155292 SPARC: can compile some stubs now but they don't work yet diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Jul 22 22:26:49 2013 -0700 @@ -395,7 +395,7 @@ } public void verify() { - assert (disp30 & DISP30_MASK) == 0; + assert isDisp30(disp30) : disp30; } } @@ -1316,15 +1316,41 @@ return x & ((1 << nbits) - 1); } - private static final int max13 = ((1 << 12) - 1); - private static final int min13 = -(1 << 12); - - public static boolean isSimm13(int src) { - return min13 <= src && src <= max13; + /** + * Minimum value for signed immediate ranges. + */ + public static long minSimm(long nbits) { + return -(1L << (nbits - 1)); + } + + /** + * Maximum value for signed immediate ranges. + */ + public static long maxSimm(long nbits) { + return (1L << (nbits - 1)) - 1; } - public static boolean isSimm13(long src) { - return NumUtil.isInt(src) && min13 <= src && src <= max13; + /** + * Test if imm is within signed immediate range for nbits. + */ + public static boolean isSimm(long imm, int nbits) { + return minSimm(nbits) <= imm && imm <= maxSimm(nbits); + } + + public static boolean isSimm13(int imm) { + return isSimm(imm, 13); + } + + public static boolean isSimm13(long imm) { + return NumUtil.isInt(imm) && isSimm(imm, 13); + } + + public static boolean isDisp30(long imm) { + return isSimm(imm, 30); + } + + public static boolean isWordDisp30(long imm) { + return isSimm(imm, 30 + 2); } public static final int hi22(int x) { diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java Mon Jul 22 22:26:49 2013 -0700 @@ -324,19 +324,24 @@ } } - public static class Setx { + /** + * This instruction is like sethi but for 64-bit values. + */ + public static class Sethix { + + private static final int INSTRUCTION_SIZE = 7; private long value; private Register dst; private boolean forceRelocatable; - public Setx(long value, Register dst, boolean forceRelocatable) { + public Sethix(long value, Register dst, boolean forceRelocatable) { this.value = value; this.dst = dst; this.forceRelocatable = forceRelocatable; } - public Setx(long value, Register dst) { + public Sethix(long value, Register dst) { this(value, dst, false); } @@ -344,28 +349,6 @@ int hi = (int) (value >> 32); int lo = (int) (value & ~0); -// if (isSimm13(lo) && value == lo) { -// new Or(g0, lo, dst).emit(masm); -// } else if (hi == 0) { -// new Sethi(lo, dst).emit(masm); // hardware version zero-extends to upper 32 -// if (lo10(lo) != 0) { -// new Or(dst, lo10(lo), dst).emit(masm); -// } -// } else if (hi == -1) { -// new Sethi(~lo, dst).emit(masm); // hardware version zero-extends to upper 32 -// new Xor(dst, ~lo10(~0), dst).emit(masm); -// new Add(dst, lo10(lo), dst).emit(masm); -// } else if (lo == 0) { -// if (isSimm13(hi)) { -// new Or(g0, hi, dst).emit(masm); -// } else { -// new Sethi(hi, dst).emit(masm); // hardware version zero-extends to upper 32 -// if (lo10(hi) != 0) { -// new Or(dst, lo10(hi), dst).emit(masm); -// } -// } -// new Sllx(dst, 32, dst).emit(masm); - // This is the same logic as MacroAssembler::internal_set. final int startPc = masm.codeBuffer.position(); @@ -402,10 +385,32 @@ } // Pad out the instruction sequence so it can be patched later. if (forceRelocatable) { - while (masm.codeBuffer.position() < (startPc + (7 * 4))) { + while (masm.codeBuffer.position() < (startPc + (INSTRUCTION_SIZE * 4))) { new Nop().emit(masm); } } + } + } + + public static class Setx { + + private long value; + private Register dst; + private boolean forceRelocatable; + + public Setx(long value, Register dst, boolean forceRelocatable) { + this.value = value; + this.dst = dst; + this.forceRelocatable = forceRelocatable; + } + + public Setx(long value, Register dst) { + this(value, dst, false); + } + + public void emit(SPARCMacroAssembler masm) { + new Sethix(value, dst, forceRelocatable).emit(masm); + int lo = (int) (value & ~0); if (lo10(lo) != 0 || forceRelocatable) { new Add(dst, lo10(lo), dst).emit(masm); } diff -r 22baf2a69f6d -r e1fcdda22831 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 Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Jul 22 22:26:49 2013 -0700 @@ -54,13 +54,11 @@ import com.oracle.graal.lir.sparc.SPARCControlFlow.SequentialSwitchOp; import com.oracle.graal.lir.sparc.SPARCControlFlow.SwitchRangesOp; import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadOp; import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; -import com.oracle.graal.lir.sparc.SPARCMove.StoreOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; @@ -94,6 +92,32 @@ } @Override + public boolean canStoreConstant(Constant c) { + // SPARC can only store integer null constants (via g0) + switch (c.getKind()) { + case Float: + case Double: + return false; + default: + return c.isNull(); + } + } + + @Override + public boolean canInlineConstant(Constant c) { + switch (c.getKind()) { + case Int: + return SPARCAssembler.isSimm13(c.asInt()) && !runtime.needsDataPatch(c); + case Long: + return SPARCAssembler.isSimm13(c.asLong()) && !runtime.needsDataPatch(c); + case Object: + return c.isNull(); + default: + return true; + } + } + + @Override public Variable emitMove(Value input) { Variable result = newVariable(input.getKind()); emitMove(result, input); @@ -117,6 +141,87 @@ } @Override + public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) { + AllocatableValue baseRegister; + long finalDisp = displacement; + if (isConstant(base)) { + if (asConstant(base).isNull()) { + baseRegister = Value.ILLEGAL; + } else if (asConstant(base).getKind() != Kind.Object) { + finalDisp += asConstant(base).asLong(); + baseRegister = Value.ILLEGAL; + } else { + baseRegister = load(base); + } + } else { + baseRegister = asAllocatable(base); + } + + AllocatableValue indexRegister; + if (!index.equals(Value.ILLEGAL) && scale != 0) { + if (isConstant(index)) { + finalDisp += asConstant(index).asLong() * scale; + indexRegister = Value.ILLEGAL; + } else { + if (scale != 1) { + Variable longIndex = newVariable(Kind.Long); + emitMove(longIndex, index); + indexRegister = emitMul(longIndex, Constant.forLong(scale)); + } else { + indexRegister = asAllocatable(index); + } + + // if (baseRegister.equals(Value.ILLEGAL)) { + // baseRegister = asAllocatable(indexRegister); + // } else { + // Variable newBase = newVariable(Kind.Long); + // emitMove(newBase, baseRegister); + // baseRegister = newBase; + // baseRegister = emitAdd(baseRegister, indexRegister); + // } + } + } else { + indexRegister = Value.ILLEGAL; + } + + int displacementInt; + + // If we don't have an index register we can use a displacement, otherwise load the + // displacement into a register and add it to the base. + if (indexRegister.equals(Value.ILLEGAL)) { + // TODO What if displacement if too big? + displacementInt = (int) finalDisp; + } else { + displacementInt = 0; + AllocatableValue displacementRegister = load(Constant.forLong(finalDisp)); + if (baseRegister.equals(Value.ILLEGAL)) { + baseRegister = displacementRegister; + } else { + Variable longBase = newVariable(Kind.Long); + emitMove(longBase, baseRegister); + baseRegister = emitAdd(longBase, displacementRegister); + } + } + + return new SPARCAddressValue(target().wordKind, baseRegister, indexRegister, displacementInt); + } + + protected SPARCAddressValue asAddressValue(Value address) { + if (address instanceof SPARCAddressValue) { + return (SPARCAddressValue) address; + } else { + return emitAddress(address, 0, Value.ILLEGAL, 0); + } + } + + @Override + public Value emitAddress(StackSlot address) { + Variable result = newVariable(target().wordKind); + append(new StackLoadAddressOp(result, address)); + return result; + } + + @Override protected boolean peephole(ValueNode valueNode) { // No peephole optimizations for now return false; @@ -267,7 +372,12 @@ @Override protected void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { - throw new InternalError("NYI"); + long maxOffset = linkage.getMaxCallTargetOffset(); + if (SPARCAssembler.isWordDisp30(maxOffset)) { + append(new SPARCCall.DirectNearForeignCallOp(linkage, result, arguments, temps, info)); + } else { + append(new SPARCCall.DirectFarForeignCallOp(this, linkage, result, arguments, temps, info)); + } } @Override @@ -354,121 +464,6 @@ } @Override - public boolean canInlineConstant(Constant c) { - switch (c.getKind()) { - case Int: - return SPARCAssembler.isSimm13(c.asInt()) && !runtime.needsDataPatch(c); - case Long: - return SPARCAssembler.isSimm13(c.asLong()) && !runtime.needsDataPatch(c); - case Object: - return c.isNull(); - default: - return true; - } - } - - @Override - public boolean canStoreConstant(Constant c) { - throw new InternalError("NYI"); - } - - @Override - public SPARCAddressValue emitAddress(Value base, long displacement, Value index, int scale) { - AllocatableValue baseRegister; - long finalDisp = displacement; - if (isConstant(base)) { - if (asConstant(base).isNull()) { - baseRegister = Value.ILLEGAL; - } else if (asConstant(base).getKind() != Kind.Object) { - finalDisp += asConstant(base).asLong(); - baseRegister = Value.ILLEGAL; - } else { - baseRegister = load(base); - } - } else { - baseRegister = asAllocatable(base); - } - - AllocatableValue indexRegister; - if (!index.equals(Value.ILLEGAL) && scale != 0) { - if (isConstant(index)) { - finalDisp += asConstant(index).asLong() * scale; - indexRegister = Value.ILLEGAL; - } else { - if (scale != 1) { - Variable longIndex = newVariable(Kind.Long); - emitMove(longIndex, index); - indexRegister = emitMul(longIndex, Constant.forLong(scale)); - } else { - indexRegister = asAllocatable(index); - } - -// if (baseRegister.equals(Value.ILLEGAL)) { -// baseRegister = asAllocatable(indexRegister); -// } else { -// Variable newBase = newVariable(Kind.Long); -// emitMove(newBase, baseRegister); -// baseRegister = newBase; -// baseRegister = emitAdd(baseRegister, indexRegister); -// } - } - } else { - indexRegister = Value.ILLEGAL; - } - - int displacementInt; - - // If we don't have an index register we can use a displacement, otherwise load the - // displacement into a register and add it to the base. - if (indexRegister.equals(Value.ILLEGAL)) { - // TODO What if displacement if too big? - displacementInt = (int) finalDisp; - } else { - displacementInt = 0; - AllocatableValue displacementRegister = load(Constant.forLong(finalDisp)); - if (baseRegister.equals(Value.ILLEGAL)) { - baseRegister = displacementRegister; - } else { - Variable longBase = newVariable(Kind.Long); - emitMove(longBase, baseRegister); - baseRegister = emitAdd(longBase, displacementRegister); - } - } - - return new SPARCAddressValue(target().wordKind, baseRegister, indexRegister, displacementInt); - } - - private SPARCAddressValue asAddress(Value address) { - if (address instanceof SPARCAddressValue) { - return (SPARCAddressValue) address; - } else { - return emitAddress(address, 0, Value.ILLEGAL, 0); - } - } - - @Override - public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) { - SPARCAddressValue loadAddress = asAddress(address); - Variable result = newVariable(kind); - append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null)); - return result; - } - - @Override - public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) { - SPARCAddressValue storeAddress = asAddress(address); - Variable input = load(inputVal); - append(new StoreOp(kind, storeAddress, input, deopting != null ? state(deopting) : null)); - } - - @Override - public Value emitAddress(StackSlot address) { - Variable result = newVariable(target().wordKind); - append(new StackLoadAddressOp(result, address)); - return result; - } - - @Override public Value emitNegate(Value input) { Variable result = newVariable(input.getKind()); switch (input.getKind()) { @@ -680,7 +675,7 @@ append(new Op2Stack(ISHL, result, a, loadNonConst(b))); break; case Long: - append(new Op1Stack(LSHL, result, loadNonConst(b))); + append(new Op2Stack(LSHL, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -696,7 +691,7 @@ append(new Op2Stack(ISHR, result, a, loadNonConst(b))); break; case Long: - append(new Op1Stack(LSHR, result, loadNonConst(b))); + append(new Op2Stack(LSHR, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Jul 22 22:26:49 2013 -0700 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.sparc; +import java.util.*; + import sun.misc.*; import com.oracle.graal.api.code.*; @@ -36,6 +38,7 @@ import com.oracle.graal.hotspot.stubs.Stub; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*; import static com.oracle.graal.sparc.SPARC.*; @@ -93,7 +96,7 @@ } } - class HotSpotFrameContext implements FrameContext { + public class HotSpotFrameContext implements FrameContext { final boolean isStub; @@ -138,6 +141,7 @@ public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen; FrameMap frameMap = gen.frameMap; + assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); AbstractAssembler masm = createAssembler(frameMap); @@ -150,6 +154,12 @@ tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } + if (stub != null) { + // SPARC stubs always enter a frame which saves the registers. + final Set definedRegisters = new HashSet<>(); + stub.initDestroyedRegisters(definedRegisters); + } + return tasm; } @@ -165,13 +175,15 @@ if (unverifiedStub != null) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); - CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false); + // We need to use JavaCall here because we haven't entered the frame yet. + CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false); Register inlineCacheKlass = g5; // see MacroAssembler::ic_call + Register scratch = g3; Register receiver = asRegister(cc.getArgument(0)); SPARCAddress src = new SPARCAddress(receiver, config.hubOffset); - new Ldx(src, g0).emit(masm); - new Cmp(inlineCacheKlass, g0).emit(masm); + new Ldx(src, scratch).emit(masm); + new Cmp(scratch, inlineCacheKlass).emit(masm); new Bpne(CC.Xcc, unverifiedStub).emit(masm); new Nop().emit(masm); // delay slot } @@ -186,10 +198,9 @@ HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext; if (frameContext != null && !frameContext.isStub) { tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); -// SPARCCall.directCall(tasm, asm, runtime().lookupForeignCall(EXCEPTION_HANDLER), null, false, -// null); + SPARCCall.directCall(tasm, masm, runtime().lookupForeignCall(EXCEPTION_HANDLER), null, false, null); tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); -// SPARCCall.directCall(tasm, asm, runtime().lookupForeignCall(DEOPT_HANDLER), null, false, null); + SPARCCall.directCall(tasm, masm, runtime().lookupForeignCall(DEOPT_HANDLER), null, false, null); } else { // No need to emit the stubs for entries back into the method since // it has no calls that can cause such "return" entries @@ -198,8 +209,8 @@ if (unverifiedStub != null) { masm.bind(unverifiedStub); -// SPARCCall.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER)); - // throw new InternalError("g0 must be scratch register"); + Register scratch = g3; + SPARCCall.indirectJmp(tasm, masm, scratch, runtime().lookupForeignCall(IC_MISS_HANDLER)); } } } diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Mon Jul 22 22:26:49 2013 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2013, 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 static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Removes the current frame and tail calls the uncommon trap routine. + */ +@Opcode("DEOPT_CALLER") +final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp { + + private final DeoptimizationAction action; + private final DeoptimizationReason reason; + + SPARCHotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) { + this.action = action; + this.reason = reason; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + leaveFrame(tasm); + +// SPARCHotSpotBackend backend = (SPARCHotSpotBackend) +// HotSpotGraalRuntime.graalRuntime().getBackend(); +// final boolean isStub = true; +// HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub); +// frameContext.enter(tasm); + + HotSpotGraalRuntime runtime = graalRuntime(); + Register thread = runtime.getRuntime().threadRegister(); + + Register scratch = g5; + new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm); + new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm); + + SPARCCall.indirectJmp(tasm, masm, scratch, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP)); + +// frameContext.leave(tasm); + } +} diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java Mon Jul 22 22:26:49 2013 -0700 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 2013, 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 com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Superclass for operations that leave a method's frame. + */ +abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction { + + protected void leaveFrame(TargetMethodAssembler tasm) { + if (tasm.frameContext != null) { + tasm.frameContext.leave(tasm); + } + } +} diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Jul 22 22:26:49 2013 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012, 2013, 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.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.sparc.SPARC.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +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.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Sets up the arguments for an exception handler in the callers frame, removes the current frame + * and jumps to the handler. + */ +@Opcode("JUMP_TO_EXCEPTION_HANDLER_IN_CALLER") +final class SPARCHotSpotJumpToExceptionHandlerInCallerOp extends SPARCHotSpotEpilogueOp { + + @Use(REG) AllocatableValue handlerInCallerPc; + @Use(REG) AllocatableValue exception; + @Use(REG) AllocatableValue exceptionPc; + + SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) { + this.handlerInCallerPc = handlerInCallerPc; + this.exception = exception; + this.exceptionPc = exceptionPc; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + leaveFrame(tasm); + + // Restore SP from L7 if the exception PC is a method handle call site. + Register thread = graalRuntime().getRuntime().threadRegister(); + int isMethodHandleReturnOffset = graalRuntime().getConfig().threadIsMethodHandleReturnOffset; + SPARCAddress dst = new SPARCAddress(thread, isMethodHandleReturnOffset); + new Lduw(dst, o7).emit(masm); + new Cmp(o7, o7).emit(masm); + new Movcc(ConditionFlag.NotZero, CC.Icc, l7, sp).emit(masm); + + new Jmpl(asRegister(handlerInCallerPc), 0, g0).emit(masm); + } +} diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Jul 22 22:26:49 2013 -0700 @@ -23,17 +23,21 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import java.lang.reflect.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.sparc.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; import com.oracle.graal.lir.sparc.SPARCMove.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -55,6 +59,32 @@ */ StackSlot deoptimizationRescueSlot; + @SuppressWarnings("hiding") + @Override + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap nodeOperands) { + assert runtime().config.basicLockSize == 8; + HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long); + return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); + } + + @Override + public StackSlot getLockSlot(int lockDepth) { + return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth); + } + + @Override + protected boolean needOnlyOopMaps() { + // Stubs only need oop maps + return graph.start() instanceof StubStartNode; + } + + Stub getStub() { + if (graph.start() instanceof StubStartNode) { + return ((StubStartNode) graph.start()).getStub(); + } + return null; + } + @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); @@ -62,8 +92,37 @@ } @Override + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + Kind kind = x.newValue().kind(); + assert kind == x.expectedValue().kind(); + + Variable address = load(operand(x.object())); + Value offset = operand(x.offset()); + Variable cmpValue = (Variable) loadNonConst(operand(x.expectedValue())); + Variable newValue = load(operand(x.newValue())); + + if (ValueUtil.isConstant(offset)) { + assert !runtime.needsDataPatch(asConstant(offset)); + Variable longAddress = newVariable(Kind.Long); + emitMove(longAddress, address); + address = emitAdd(longAddress, asConstant(offset)); + } else { + if (isLegal(offset)) { + address = emitAdd(address, offset); + } + } + + append(new CompareAndSwapOp(address, cmpValue, newValue)); + + Variable result = newVariable(x.kind()); + emitMove(result, newValue); + setResult(x, result); + } + + @Override public void emitTailcall(Value[] args, Value address) { - throw new InternalError("NYI"); +// append(new AMD64TailcallOp(args, address)); + throw GraalInternalError.unimplemented(); } @Override @@ -89,57 +148,120 @@ // emitMove(targetAddress, operand(callTarget.computedAddress())); // append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, // targetAddress, callState)); - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); + } + + @Override + public void emitUnwind(Value exception) { + ForeignCallLinkage linkage = getRuntime().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); + CallingConvention linkageCc = linkage.getCallingConvention(); + assert linkageCc.getArgumentCount() == 2; + RegisterValue exceptionParameter = (RegisterValue) linkageCc.getArgument(0); + emitMove(exceptionParameter, exception); + append(new SPARCHotSpotUnwindOp(exceptionParameter)); + throw GraalInternalError.unimplemented(); + } + + @Override + public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { +// append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting))); + throw GraalInternalError.unimplemented(); } @Override public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - throw new InternalError("NYI"); + append(new SPARCHotSpotDeoptimizeCallerOp(action, reason)); } @Override public void emitPatchReturnAddress(ValueNode address) { - throw new InternalError("NYI"); + append(new SPARCHotSpotPatchReturnAddressOp(load(operand(address)))); } @Override public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - throw new InternalError("NYI"); + Variable handler = load(operand(handlerInCallerPc)); + ForeignCallLinkage linkage = getRuntime().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); + CallingConvention linkageCc = linkage.getCallingConvention(); + assert linkageCc.getArgumentCount() == 2; + RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0); + RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1); + emitMove(exceptionFixed, operand(exception)); + emitMove(exceptionPcFixed, operand(exceptionPc)); + SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed); + append(op); + } + + private static boolean isCompressCandidate(DeoptimizingNode access) { + return access != null && ((HeapAccess) access).isCompressible(); + } + + @Override + public Variable emitLoad(Kind kind, Value address, DeoptimizingNode access) { + SPARCAddressValue loadAddress = asAddressValue(address); + Variable result = newVariable(kind); + assert access == null || access instanceof HeapAccess; + if (isCompressCandidate(access)) { + if (runtime().config.useCompressedOops && kind == Kind.Object) { +// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : +// null, runtime().config.narrowOopBase, runtime().config.narrowOopShift, +// runtime().config.logMinObjAlignment)); + throw GraalInternalError.unimplemented(); + } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) { +// append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : +// null, runtime().config.narrowKlassBase, runtime().config.narrowKlassShift, +// runtime().config.logKlassAlignment)); + throw GraalInternalError.unimplemented(); + } else { + append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null)); + } + } else { + append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null)); + } + return result; } @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().kind(); - assert kind == x.expectedValue().kind(); - - Variable address = load(operand(x.object())); - Value offset = operand(x.offset()); - Variable cmpValue = (Variable) loadNonConst(operand(x.expectedValue())); - Variable newValue = load(operand(x.newValue())); - - if (ValueUtil.isConstant(offset)) { - assert !runtime.needsDataPatch(asConstant(offset)); - address = emitAdd(address, asConstant(offset)); - } else { - if (isLegal(offset)) { - address = emitAdd(address, offset); + public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode access) { + SPARCAddressValue storeAddress = asAddressValue(address); + LIRFrameState state = access != null ? state(access) : null; + if (isConstant(inputVal)) { + Constant c = asConstant(inputVal); + if (canStoreConstant(c)) { + if (inputVal.getKind() == Kind.Object) { + append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access))); + } else if (inputVal.getKind() == Kind.Long) { + append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedKlassPointers && isCompressCandidate(access))); + } else { + append(new StoreConstantOp(kind, storeAddress, c, state, false)); + } + return; } } - - append(new CompareAndSwapOp(address, cmpValue, newValue)); - - Variable result = newVariable(x.kind()); - emitMove(result, newValue); - setResult(x, result); + Variable input = load(inputVal); + if (isCompressCandidate(access)) { + if (runtime().config.useCompressedOops && kind == Kind.Object) { +// if (input.getKind() == Kind.Object) { +// Variable scratch = newVariable(Kind.Long); +// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, +// runtime().config.narrowOopBase, runtime().config.narrowOopShift, +// runtime().config.logMinObjAlignment)); +// } else { +// // the input oop is already compressed +// append(new StoreOp(input.getKind(), storeAddress, input, state)); +// } + throw GraalInternalError.unimplemented(); + } else if (runtime().config.useCompressedKlassPointers && kind == Kind.Long) { +// Variable scratch = newVariable(Kind.Long); +// append(new StoreCompressedPointer(kind, storeAddress, input, scratch, state, +// runtime().config.narrowKlassBase, runtime().config.narrowKlassShift, +// runtime().config.logKlassAlignment)); + throw GraalInternalError.unimplemented(); + } else { + append(new StoreOp(kind, storeAddress, input, state)); + } + } else { + append(new StoreOp(kind, storeAddress, input, state)); + } } - - @Override - public StackSlot getLockSlot(int lockDepth) { - throw new InternalError("NYI"); - } - - public Stub getStub() { - throw new InternalError("NYI"); - } - } diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java Mon Jul 22 22:26:49 2013 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, 2013, 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 static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Patch the return address of the current frame. + */ +@Opcode("PATCH_RETURN") +final class SPARCHotSpotPatchReturnAddressOp extends SPARCLIRInstruction { + + @Use(REG) AllocatableValue address; + + SPARCHotSpotPatchReturnAddressOp(AllocatableValue address) { + this.address = address; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, 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 = tasm.frameMap.frameSize(); + // new Stx(asRegister(address), new SPARCAddress(sp, frameSize)); + new Ldx(new SPARCAddress(g0, g0), g0).emit(masm); + } +} diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Jul 22 22:26:49 2013 -0700 @@ -95,14 +95,16 @@ // @formatter:off if (reserveForHeapBase) { registers = new Register[] { - // TODO this is not complete + // TODO this is not complete + o0, o1, o2, o3, o4, o5, /*o6,*/ o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, /*i6,*/ i7, f0, f1, f2, f3, f4, f5, f6, f7 }; } else { registers = new Register[] { - // TODO this is not complete + // TODO this is not complete + o0, o1, o2, o3, o4, o5, /*o6,*/ o7, l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, /*i6,*/ i7, f0, f1, f2, f3, f4, f5, f6, f7 diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java Mon Jul 22 22:26:49 2013 -0700 @@ -76,7 +76,7 @@ @Override public Register stackPointerRegister() { - throw new InternalError("NYI: SPARC: Define stack pointer register."); + return sp; } @Override diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java Mon Jul 22 22:26:49 2013 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2013, 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 static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; + +/** + * Removes the current frame and jumps to the {@link UnwindExceptionToCallerStub}. + */ +@Opcode("UNWIND") +final class SPARCHotSpotUnwindOp extends SPARCHotSpotEpilogueOp { + + @Use({REG}) protected RegisterValue exception; + + SPARCHotSpotUnwindOp(RegisterValue exception) { + this.exception = exception; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + leaveFrame(tasm); + + ForeignCallLinkage linkage = tasm.runtime.lookupForeignCall(UNWIND_EXCEPTION_TO_CALLER); + CallingConvention cc = linkage.getCallingConvention(); + assert cc.getArgumentCount() == 2; + assert exception.equals(cc.getArgument(0)); + + // Get return address (is in o7 after leave). + Register returnAddress = asRegister(cc.getArgument(1)); + new Mov(o7, returnAddress).emit(masm); + + Register scratch = g5; + SPARCCall.indirectJmp(tasm, masm, scratch, linkage); + } +} diff -r 22baf2a69f6d -r e1fcdda22831 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 Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java Mon Jul 22 22:26:49 2013 -0700 @@ -264,10 +264,10 @@ new Add(asIntReg(src2), -(tasm.asIntConst(src1)), asIntReg(dst)).emit(masm); break; case IAND: - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); case IDIV: assert isSimm13(tasm.asIntConst(src1)); - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); // new Sdivx(masm, asIntReg(src1), asIntReg(src2), // asIntReg(dst)); case FSUB: @@ -311,6 +311,14 @@ assert isSimm13(tasm.asIntConst(src2)); new Xor(asIntReg(src1), tasm.asIntConst(src2), asIntReg(dst)).emit(masm); break; + case LADD: + assert isSimm13(tasm.asIntConst(src2)); + new Add(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); + break; + case LSUB: + assert isSimm13(tasm.asIntConst(src2)); + new Sub(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); + break; case LMUL: assert isSimm13(tasm.asIntConst(src2)); new Mulx(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); @@ -319,6 +327,10 @@ assert isSimm13(tasm.asIntConst(src2)); new Add(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); break; + case LSHL: + assert isSimm13(tasm.asIntConst(src2)); + new Sll(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); + break; case LUSHR: assert isSimm13(tasm.asIntConst(src2)); new Srl(asLongReg(src1), tasm.asIntConst(src2), asLongReg(dst)).emit(masm); @@ -365,7 +377,7 @@ new Sra(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm); break; case IREM: - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); case LADD: new Add(asLongReg(src1), asLongReg(src2), asLongReg(dst)).emit(masm); break; @@ -400,7 +412,7 @@ case LUDIV: case LUREM: case LREM: - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); case FADD: new Fadds(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm); break; @@ -414,7 +426,7 @@ new Fdivs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm); break; case FREM: - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); case DADD: new Faddd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)).emit(masm); break; @@ -428,7 +440,7 @@ new Fdivd(asDoubleReg(src1), asDoubleReg(src2), asDoubleReg(dst)).emit(masm); break; case DREM: - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); default: throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } @@ -507,7 +519,7 @@ rk = result.getKind(); xsk = x.getKind().getStackKind(); ysk = y.getKind().getStackKind(); - assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int : "opcode=" + opcode + ", rk=" + rk + ", xsk=" + xsk + ", ysk=" + ysk; + assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int; break; case LADD: case LSUB: @@ -517,13 +529,18 @@ case LAND: case LOR: case LXOR: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long; + break; case LSHL: case LSHR: case LUSHR: rk = result.getKind(); xk = x.getKind(); yk = y.getKind(); - assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long; + assert rk == Kind.Long && xk == Kind.Long && (yk == Kind.Int || yk == Kind.Long); break; case FADD: case FSUB: @@ -543,10 +560,10 @@ rk = result.getKind(); xk = x.getKind(); yk = y.getKind(); - assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double; + assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double : "opcode=" + opcode + ", result kind=" + rk + ", x kind=" + xk + ", y kind=" + yk; break; default: - throw new InternalError("NYI: " + opcode); + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } } diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java Mon Jul 22 22:26:49 2013 -0700 @@ -153,14 +153,13 @@ } int before = masm.codeBuffer.position(); if (scratch != null) { -// // offset might not fit a 32-bit immediate, generate an -// // indirect call with a 64-bit immediate -// masm.movq(scratch, 0L); -// masm.call(scratch); -// } else { -// masm.call(); + // offset might not fit a 30-bit displacement, generate an + // indirect call with a 64-bit immediate + new Sethix(0L, scratch, true).emit(masm); + new Jmpl(scratch, 0, r15).emit(masm); + } else { + new Call(0).emit(masm); } - new Call(0).emit(masm); int after = masm.codeBuffer.position(); tasm.recordDirectCall(before, after, callTarget, info); tasm.recordExceptionHandlers(after, info); @@ -168,14 +167,14 @@ new Nop().emit(masm); // delay slot } - public static void directJmp(TargetMethodAssembler tasm, SPARCMacroAssembler masm, InvokeTarget target) { + public static void indirectJmp(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget target) { int before = masm.codeBuffer.position(); -// masm.jmp(0, true); + new Sethix(0L, dst, true).emit(masm); + new Jmp(new SPARCAddress(dst, 0)).emit(masm); int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, target, null); + tasm.recordIndirectCall(before, after, target, null); // masm.ensureUniquePC(); new Nop().emit(masm); // delay slot - throw new InternalError("NYI"); } public static void indirectCall(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Mon Jul 22 22:26:49 2013 -0700 @@ -73,6 +73,9 @@ case GT: new Bpg(CC.Xcc, destination.label()).emit(masm); break; + case AT: + new Bpgu(CC.Xcc, destination.label()).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere(); } diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Mon Jul 22 22:26:49 2013 -0700 @@ -264,6 +264,51 @@ } } + public static class StoreConstantOp extends MemOp { + + protected final Constant input; + private final boolean compress; + + public StoreConstantOp(Kind kind, SPARCAddressValue address, Constant input, LIRFrameState state, boolean compress) { + super(kind, address, state); + this.input = input; + this.compress = compress; + if (input.isNonNull()) { + throw GraalInternalError.shouldNotReachHere("Can only store null constants to memory"); + } + } + + @Override + public void emitMemAccess(SPARCMacroAssembler masm) { + switch (kind) { + case Boolean: + case Byte: + new Stb(g0, address.toAddress()).emit(masm); + break; + case Char: + case Short: + new Sth(g0, address.toAddress()).emit(masm); + break; + case Int: + new Stw(g0, address.toAddress()).emit(masm); + break; + case Long: + case Object: + if (compress) { + new Stw(g0, address.toAddress()).emit(masm); + } else { + new Stx(g0, address.toAddress()).emit(masm); + } + break; + case Float: + case Double: + throw GraalInternalError.shouldNotReachHere("Cannot store float constants to memory"); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + public static void move(TargetMethodAssembler tasm, SPARCMacroAssembler masm, Value result, Value input) { if (isRegister(input)) { if (isRegister(result)) { @@ -314,9 +359,11 @@ new Stw(asRegister(input), dest).emit(masm); break; case Long: + case Object: + new Stx(asRegister(input), dest).emit(masm); + break; case Float: case Double: - case Object: default: throw GraalInternalError.shouldNotReachHere(); } @@ -342,21 +389,25 @@ case Int: if (tasm.runtime.needsDataPatch(input)) { tasm.recordDataReferenceInCode(input, 0, true); + new Setuw(input.asInt(), asRegister(result)).emit(masm); + } else { + if (input.isDefaultForKind()) { + new Clr(asRegister(result)).emit(masm); + } else { + new Setuw(input.asInt(), asRegister(result)).emit(masm); + } } - new Setuw(input.asInt(), asRegister(result)).emit(masm); break; case Long: { if (tasm.runtime.needsDataPatch(input)) { - new Nop().emit(masm); tasm.recordDataReferenceInCode(input, 0, true); new Setx(input.asLong(), asRegister(result), true).emit(masm); - new Nop().emit(masm); } else { - new Nop().emit(masm); - new Nop().emit(masm); - new Setx(input.asLong(), asRegister(result)).emit(masm); - new Nop().emit(masm); - new Nop().emit(masm); + if (input.isDefaultForKind()) { + new Clr(asRegister(result)).emit(masm); + } else { + new Setx(input.asLong(), asRegister(result)).emit(masm); + } } break; } diff -r 22baf2a69f6d -r e1fcdda22831 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Jul 22 21:43:31 2013 -0700 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Jul 22 22:26:49 2013 -0700 @@ -41,38 +41,38 @@ public static final RegisterCategory FPU = new RegisterCategory("FPU"); // General purpose registers - public static final Register r0 = new Register(0, 0, "r0", CPU); - public static final Register r1 = new Register(1, 1, "r1", CPU); - public static final Register r2 = new Register(2, 2, "r2", CPU); - public static final Register r3 = new Register(3, 3, "r3", CPU); - public static final Register r4 = new Register(4, 4, "r4", CPU); - public static final Register r5 = new Register(5, 5, "r5", CPU); - public static final Register r6 = new Register(6, 6, "r6", CPU); - public static final Register r7 = new Register(7, 7, "r7", CPU); - public static final Register r8 = new Register(8, 8, "r8", CPU); - public static final Register r9 = new Register(9, 9, "r9", CPU); - public static final Register r10 = new Register(10, 10, "r10", CPU); - public static final Register r11 = new Register(11, 11, "r11", CPU); - public static final Register r12 = new Register(12, 12, "r12", CPU); - public static final Register r13 = new Register(13, 13, "r13", CPU); - public static final Register r14 = new Register(14, 14, "r14", CPU); - public static final Register r15 = new Register(15, 15, "r15", CPU); - public static final Register r16 = new Register(16, 16, "r16", CPU); - public static final Register r17 = new Register(17, 17, "r17", CPU); - public static final Register r18 = new Register(18, 18, "r18", CPU); - public static final Register r19 = new Register(19, 19, "r19", CPU); - public static final Register r20 = new Register(20, 20, "r20", CPU); - public static final Register r21 = new Register(21, 21, "r21", CPU); - public static final Register r22 = new Register(22, 22, "r22", CPU); - public static final Register r23 = new Register(23, 23, "r23", CPU); - public static final Register r24 = new Register(24, 24, "r24", CPU); - public static final Register r25 = new Register(25, 25, "r25", CPU); - public static final Register r26 = new Register(26, 26, "r26", CPU); - public static final Register r27 = new Register(27, 27, "r27", CPU); - public static final Register r28 = new Register(28, 28, "r28", CPU); - public static final Register r29 = new Register(29, 29, "r29", CPU); - public static final Register r30 = new Register(30, 30, "r30", CPU); - public static final Register r31 = new Register(31, 31, "r31", CPU); + public static final Register r0 = new Register(0, 0, "g0", CPU); + public static final Register r1 = new Register(1, 1, "g1", CPU); + public static final Register r2 = new Register(2, 2, "g2", CPU); + public static final Register r3 = new Register(3, 3, "g3", CPU); + public static final Register r4 = new Register(4, 4, "g4", CPU); + public static final Register r5 = new Register(5, 5, "g5", CPU); + public static final Register r6 = new Register(6, 6, "g6", CPU); + public static final Register r7 = new Register(7, 7, "g7", CPU); + public static final Register r8 = new Register(8, 8, "o0", CPU); + public static final Register r9 = new Register(9, 9, "o1", CPU); + public static final Register r10 = new Register(10, 10, "o2", CPU); + public static final Register r11 = new Register(11, 11, "o3", CPU); + public static final Register r12 = new Register(12, 12, "o4", CPU); + public static final Register r13 = new Register(13, 13, "o5", CPU); + public static final Register r14 = new Register(14, 14, "o6", CPU); + public static final Register r15 = new Register(15, 15, "o7", CPU); + public static final Register r16 = new Register(16, 16, "l0", CPU); + public static final Register r17 = new Register(17, 17, "l1", CPU); + public static final Register r18 = new Register(18, 18, "l2", CPU); + public static final Register r19 = new Register(19, 19, "l3", CPU); + public static final Register r20 = new Register(20, 20, "l4", CPU); + public static final Register r21 = new Register(21, 21, "l5", CPU); + public static final Register r22 = new Register(22, 22, "l6", CPU); + public static final Register r23 = new Register(23, 23, "l7", CPU); + public static final Register r24 = new Register(24, 24, "i0", CPU); + public static final Register r25 = new Register(25, 25, "i1", CPU); + public static final Register r26 = new Register(26, 26, "i2", CPU); + public static final Register r27 = new Register(27, 27, "i3", CPU); + public static final Register r28 = new Register(28, 28, "i4", CPU); + public static final Register r29 = new Register(29, 29, "i5", CPU); + public static final Register r30 = new Register(30, 30, "i6", CPU); + public static final Register r31 = new Register(31, 31, "i7", CPU); public static final Register g0 = r0; public static final Register g1 = r1; diff -r 22baf2a69f6d -r e1fcdda22831 src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp --- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Mon Jul 22 21:43:31 2013 -0700 +++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Mon Jul 22 22:26:49 2013 -0700 @@ -29,8 +29,14 @@ #include "graal/graalJavaAccess.hpp" inline jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) { - assert(inst->is_call() || inst->is_jump(), "sanity"); - return pc_offset + NativeCall::instruction_size; + if (inst->is_call() || inst->is_jump()) { + return pc_offset + NativeCall::instruction_size; + } else if (inst->is_sethi()) { + return pc_offset + NativeFarCall::instruction_size; + } else { + fatal("unsupported type of instruction for call site"); + return 0; + } } inline void CodeInstaller::pd_site_DataPatch(int pc_offset, oop site) { @@ -107,7 +113,22 @@ } inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { - fatal("CodeInstaller::pd_relocate_ForeignCall - sparc unimp"); + address pc = (address) inst; + if (inst->is_call()) { + NativeCall* call = nativeCall_at(pc); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); + } else if (inst->is_sethi()) { + NativeFarCall* call = nativeFarCall_at(pc); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); + } else { + NativeJump* jump = nativeJump_at((address) (inst)); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate((address)inst, runtime_call_Relocation::spec()); + fatal("CodeInstaller::pd_relocate_ForeignCall - verify me!"); + } + TRACE_graal_3("relocating (foreign call) at %p", inst); } inline void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) { @@ -127,7 +148,6 @@ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); - /*, Assembler::call32_operand); */ break; } case MARK_INVOKESTATIC: { @@ -135,16 +155,13 @@ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); - /*, Assembler::call32_operand); */ break; } case MARK_INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); -// _instructions->relocate(call->instruction_address(), -// relocInfo::opt_virtual_call_type, Assembler::call32_operand); - fatal("NYI"); + _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); break; } default: diff -r 22baf2a69f6d -r e1fcdda22831 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 22 21:43:31 2013 -0700 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Jul 22 22:26:49 2013 -0700 @@ -734,12 +734,9 @@ if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) { assert(inst->is_jump(), "jump expected"); - CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target); assert(cb != NULL, "npe"); - CodeInstaller::pd_relocate_CodeBlob(cb, inst); - return; } @@ -755,7 +752,6 @@ if (foreign_call != NULL) { jlong foreign_call_destination = HotSpotForeignCallLinkage::address(foreign_call); - CodeInstaller::pd_relocate_ForeignCall(inst, foreign_call_destination); } else { // method != NULL assert(hotspot_method != NULL, "unexpected JavaMethod"); @@ -764,7 +760,9 @@ TRACE_graal_3("method call"); CodeInstaller::pd_relocate_JavaMethod(hotspot_method, pc_offset); } + _next_call_type = MARK_INVOKE_INVALID; + if (debug_info != NULL) { _debug_recorder->end_safepoint(next_pc_offset); }