# HG changeset patch # User Christos Kotselidis # Date 1373653140 -7200 # Node ID 88992c295d475b5a62af46f0c2e46dad8646f34a # Parent 060f9ed42e2f54d893f8566d9b448b9ad6831855# Parent 2a4ad6ab345eb59c4b6296246caf1ad3d8704c74 Merge diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Jul 12 20:19:00 2013 +0200 @@ -236,7 +236,15 @@ Register receiver = asRegister(cc.getArgument(0)); AMD64Address src = new AMD64Address(receiver, config.hubOffset); - asm.cmpq(inlineCacheKlass, src); + AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen; + HotSpotRuntime hr = ((HotSpotRuntime) gen.getRuntime()); + if (hr.config.useCompressedKlassPointers) { + Register register = r10; + AMD64Move.decodeKlassPointer(asm, register, src, hr.config.narrowKlassBase, hr.config.narrowKlassShift, hr.config.logKlassAlignment); + asm.cmpq(inlineCacheKlass, register); + } else { + asm.cmpq(inlineCacheKlass, src); + } asm.jcc(ConditionFlag.NotEqual, unverifiedStub); } diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Jul 12 20:19:00 2013 +0200 @@ -413,9 +413,16 @@ AMD64AddressValue loadAddress = asAddressValue(address); Variable result = newVariable(kind); assert access == null || access instanceof HeapAccess; - if (runtime().config.useCompressedOops && isCompressCandidate(access)) { - append(new LoadCompressedPointer(kind, result, loadAddress, access != null ? state(access) : null, runtime().config.narrowOopBase, runtime().config.narrowOopShift, - runtime().config.logMinObjAlignment)); + 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)); + } 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)); + } else { + append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null)); + } } else { append(new LoadOp(kind, result, loadAddress, access != null ? state(access) : null)); } @@ -429,17 +436,26 @@ if (isConstant(inputVal)) { Constant c = asConstant(inputVal); if (canStoreConstant(c)) { - append(new StoreConstantOp(kind, storeAddress, c, state, runtime().config.useCompressedOops && isCompressCandidate(access))); + 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; } } Variable input = load(inputVal); - if (runtime().config.useCompressedOops && isCompressCandidate(access)) { - if (input.getKind() == Kind.Object) { + if (isCompressCandidate(access)) { + if (runtime().config.useCompressedOops && kind == 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 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)); } else { - append(new StoreOp(input.getKind(), storeAddress, input, state)); + append(new StoreOp(kind, storeAddress, input, state)); } } else { append(new StoreOp(kind, storeAddress, input, state)); diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Fri Jul 12 20:19:00 2013 +0200 @@ -287,6 +287,103 @@ return "Test".equals(c1); } + @SuppressWarnings("unchecked") + public static Object[] unmodListTestByte(Object c1, @SuppressWarnings("unused") Object c2, @SuppressWarnings("unused") Object c3) { + List queue = (ArrayList) c1; + Byte[] result = Collections.unmodifiableCollection(queue).toArray(new Byte[queue.size()]); + return result; + } + + @Test + public void test13() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("unmodListTestByte"); + List list = new ArrayList<>(); + Byte[] array = (Byte[]) installedBenchmarkCode.execute(list, null, null); + Assert.assertTrue(list.size() == array.length); + } + + @Test + public void test14() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTest"); + StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + Assert.assertTrue(buffer.length() == 28); + String a = new String("TestTestTestTestTestTestTest"); + installedBenchmarkCode.execute(buffer, a.toCharArray(), null); + Assert.assertTrue(buffer.length() == 56); + Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest")); + } + + public static void stringBufferTest(Object c1, Object c2, @SuppressWarnings("unused") Object c3) { + StringBuffer source = (StringBuffer) c1; + char[] add = (char[]) c2; + for (int i = 0; i < add.length; i++) { + source.append(add[i]); + } + } + + @Test + public void test15() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferTestIn"); + installedBenchmarkCode.execute(null, null, null); + } + + @SuppressWarnings("unused") + public static void stringBufferTestIn(Object c1, Object c2, Object c3) { + StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + Assert.assertTrue(buffer.length() == 28); + String a = new String("TestTestTestTestTestTestTest"); + char[] add = a.toCharArray(); + for (int i = 0; i < add.length; i++) { + buffer.append(add[i]); + } + Assert.assertTrue(buffer.length() == 56); + Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest")); + } + + @Test + public void test16() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBufferArrayCopy"); + installedBenchmarkCode.execute(null, null, null); + } + + @SuppressWarnings("unused") + public static void stringBufferArrayCopy(Object c1, Object c2, Object c3) { + StringBuffer buffer = new StringBuffer("TestTestTestTestTestTestTest"); + Assert.assertTrue(buffer.length() == 28); + String a = new String("TestTestTestTestTestTestTest"); + char[] dst = new char[buffer.length() * 2]; + System.arraycopy(buffer.toString().toCharArray(), 0, dst, 0, buffer.length()); + System.arraycopy(a.toCharArray(), 0, dst, buffer.length(), buffer.length()); + Assert.assertTrue(dst.length == 56); + Assert.assertTrue(new String(dst).equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest")); + } + + @Test + public void test17() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringFormat"); + installedBenchmarkCode.execute(null, null, null); + } + + @SuppressWarnings("unused") + public static void stringFormat(Object c1, Object c2, Object c3) { + String.format("Hello %d", 0); + String.format("Hello %d", -11); + String.format("Hello %d", -2147483648); + } + + @Test + public void test18() throws Exception { + HotSpotInstalledCode installedBenchmarkCode = getInstalledCode("stringBuilder"); + StringBuilder b = (StringBuilder) installedBenchmarkCode.execute(null, null, null); + Assert.assertTrue(b.capacity() == 16); + Assert.assertTrue(b.length() == 0); + } + + @SuppressWarnings("unused") + public static Object stringBuilder(Object c1, Object c2, Object c3) { + return new StringBuilder(); + } + static class Container { public Object a = new Object(); @@ -352,5 +449,4 @@ } } - } diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Jul 12 20:19:00 2013 +0200 @@ -649,6 +649,10 @@ ResolvedJavaMethod method = loadMethodNode.getMethod(); ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method); graph.replaceFixed(loadMethodNode, metaspaceMethod); + } else if (n instanceof StoreHubNode) { + StoreHubNode storeHub = (StoreHubNode) n; + WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue()); + graph.replaceFixed(storeHub, hub); } else if (n instanceof FixedGuardNode) { FixedGuardNode node = (FixedGuardNode) n; GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated()); @@ -836,7 +840,13 @@ private ReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); - return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, false)); + return graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()), WriteBarrierType.NONE, config.useCompressedKlassPointers)); + } + + private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) { + LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph); + assert !object.isConstant() || object.asConstant().isNull(); + return graph.add(new WriteNode(object, value, location, WriteBarrierType.NONE, config.useCompressedKlassPointers)); } public static long referentOffset() { diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Fri Jul 12 20:19:00 2013 +0200 @@ -277,7 +277,7 @@ public static void initializeObjectHeader(Word memory, Word markWord, Word hub) { memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION); - memory.writeWord(hubOffset(), hub, HUB_LOCATION); + StoreHubNode.write(memory.toObject(), hub); } @Fold @@ -473,6 +473,7 @@ } public static Word loadWordFromObject(Object object, int offset) { + assert offset != hubOffset() : "Use loadHubIntrinsic instead"; return loadWordFromObjectIntrinsic(object, 0, offset, getWordKind()); } @@ -488,7 +489,10 @@ @SuppressWarnings("unused") @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true) static Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word) { - return Word.box(unsafeReadWord(object, hubOffset())); + if (wordKind() == Kind.Int) { + return Word.box((int) unsafeReadKlassPointer(object)); + } + return Word.box(unsafeReadKlassPointer(object)); } @Fold diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Fri Jul 12 20:19:00 2013 +0200 @@ -213,7 +213,7 @@ fatal("oop not in heap: %p", oop.rawValue()); } - Word klass = oop.readWord(hubOffset()); + Word klass = loadHub(object); if (klass.equal(Word.zero())) { fatal("klass for oop %p is null", oop.rawValue()); } diff -r 2a4ad6ab345e -r 88992c295d47 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Jul 12 19:09:52 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Jul 12 20:19:00 2013 +0200 @@ -129,14 +129,18 @@ this.base = base; this.shift = shift; this.alignment = alignment; - assert kind == Kind.Object; + assert kind == Kind.Object || kind == Kind.Long; } @Override public void emitMemAccess(AMD64MacroAssembler masm) { Register resRegister = asRegister(result); masm.movl(resRegister, address.toAddress()); - decodePointer(masm, resRegister, base, shift, alignment); + if (kind == Kind.Object) { + decodePointer(masm, resRegister, base, shift, alignment); + } else { + decodeKlassPointer(masm, resRegister, base, shift, alignment); + } } } @@ -203,13 +207,17 @@ this.address = address; this.state = state; this.input = input; - assert kind == Kind.Object; + assert kind == Kind.Object || kind == Kind.Long; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { masm.movq(asRegister(scratch), asRegister(input)); - encodePointer(masm, asRegister(scratch), base, shift, alignment); + if (kind == Kind.Object) { + encodePointer(masm, asRegister(scratch), base, shift, alignment); + } else { + encodeKlassPointer(masm, asRegister(scratch), base, shift, alignment); + } if (state != null) { tasm.recordImplicitException(masm.codeBuffer.position(), state); } @@ -286,7 +294,11 @@ break; case Long: if (NumUtil.isInt(input.asLong())) { - masm.movslq(address.toAddress(), (int) input.asLong()); + if (compress) { + masm.movl(address.toAddress(), (int) input.asLong()); + } else { + masm.movslq(address.toAddress(), (int) input.asLong()); + } } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); } @@ -691,4 +703,30 @@ } } + private static void encodeKlassPointer(AMD64MacroAssembler masm, Register scratchRegister, long base, int shift, int alignment) { + if (base != 0) { + masm.subq(scratchRegister, AMD64.r12); + } + if (shift != 0) { + assert alignment == shift : "Encode algorithm is wrong"; + masm.shrq(scratchRegister, alignment); + } + } + + private static void decodeKlassPointer(AMD64MacroAssembler masm, Register resRegister, long base, int shift, int alignment) { + if (shift != 0) { + assert alignment == shift : "Decode algorighm is wrong"; + masm.shlq(resRegister, alignment); + if (base != 0) { + masm.addq(resRegister, AMD64.r12); + } + } else { + assert base == 0 : "Sanity"; + } + } + + public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, AMD64Address address, long narrowKlassBase, int narrowKlassShift, int logKlassAlignment) { + masm.movl(register, address); + decodeKlassPointer(masm, register, narrowKlassBase, narrowKlassShift, logKlassAlignment); + } }