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