Mercurial > hg > truffle
changeset 11838:16d0eb40d31c
Merge
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Mon, 30 Sep 2013 18:05:25 +0200 |
parents | 4187b229d2ec (diff) bd3441f941f9 (current diff) |
children | 0e2cceed1caf |
files | graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java |
diffstat | 45 files changed, 2133 insertions(+), 254 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Mon Sep 30 18:05:25 2013 +0200 @@ -399,9 +399,11 @@ } for (Method m : c.getDeclaredMethods()) { if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) { - Method overridden = vtable.methods.put(new NameAndSignature(m), m); - if (overridden != null) { - // println(m + " overrides " + overridden); + if (isAbstract(m.getModifiers())) { + // A subclass makes a concrete method in a superclass abstract + vtable.methods.remove(new NameAndSignature(m)); + } else { + vtable.methods.put(new NameAndSignature(m), m); } } } @@ -438,7 +440,13 @@ @Test public void resolveMethodTest() { for (Class c : classes) { - if (!c.isPrimitive() && !c.isInterface()) { + if (c.isInterface() || c.isPrimitive()) { + ResolvedJavaType type = runtime.lookupJavaType(c); + for (Method m : c.getDeclaredMethods()) { + ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m)); + assertEquals(m.toString(), null, impl); + } + } else { ResolvedJavaType type = runtime.lookupJavaType(c); VTable vtable = getVTable(c); for (Method impl : vtable.methods.values()) { @@ -449,6 +457,11 @@ checkResolveMethod(type, m, i); } } + for (Method m : c.getDeclaredMethods()) { + ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m)); + ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl; + assertEquals(type + " " + m.toString(), expected, impl); + } } } }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Mon Sep 30 18:05:25 2013 +0200 @@ -50,17 +50,21 @@ boolean isSynthetic(); /** - * Gets the constant value of this field for a given object, if available. + * Gets the constant value of this field. Note that a {@code static final} field may not be + * considered constant if its declaring class is not yet initialized or if it is a well known + * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}). * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. - * @return the constant value of this field or {@code null} if the constant value is not - * available + * @return the constant value of this field or {@code null} if this field is not considered + * constant by the runtime */ Constant readConstantValue(Constant receiver); /** - * Gets the current value of this field for a given object, if available. + * Gets the current value of this field for a given object, if available. There is no guarantee + * that the same value will be returned by this method for a field unless the field is + * considered to be {@link #readConstantValue(Constant)} by the runtime. * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static.
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Mon Sep 30 18:05:25 2013 +0200 @@ -205,10 +205,13 @@ /** * Resolves the method implementation for virtual dispatches on objects of this dynamic type. + * This resolution process only searches "up" the class hierarchy of this type. A broader search + * that also walks "down" the hierarchy is implemented by + * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. * * @param method the method to select the implementation of - * @return the method implementation that would be selected at runtime, or {@code null} if the - * runtime cannot resolve the method at this point in time. + * @return the concrete method that would be selected at runtime, or {@code null} if there is no + * concrete implementation of {@code method} in this type or any of its superclasses */ ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method);
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Sep 30 18:05:25 2013 +0200 @@ -747,7 +747,7 @@ emitOperandHelper(0, dst); } - private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { + public void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 6; long disp = jumpTarget - codeBuffer.position();
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Mon Sep 30 18:05:25 2013 +0200 @@ -288,7 +288,13 @@ } public String emitVariable(Variable v) { - return (" %r" + v.index); + String name = v.getName(); + + if (name == null) { + return (" %r" + v.index); + } else { + return name; + } } } @@ -757,6 +763,6 @@ @Override public PTXAddress getPlaceholder() { - throw GraalInternalError.unimplemented("PTXAddress.getPlaceholder()"); + return null; } }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java Mon Sep 30 18:05:25 2013 +0200 @@ -22,96 +22,59 @@ */ package com.oracle.graal.compiler.ptx.test; -import java.lang.reflect.Method; +import static com.oracle.graal.lir.ptx.ThreadDimension.*; -import org.junit.*; +import com.oracle.graal.lir.ptx.ParallelOver; +import com.oracle.graal.lir.ptx.Warp; + +import java.lang.reflect.Method; +import java.util.Arrays; +import org.junit.Test; public class ArrayPTXTest extends PTXTestBase { - @Ignore @Test public void testArray() { - int[] arrayI = { - 1, 2, 3, 4, 5 + int[] array1 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int[] array2 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int[] array3 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - Integer resI = (Integer) invoke(compile("testArray1I"), arrayI, 3); - printReport("testArray1I: " + resI); - // compile("testArray1J"); - // compile("testArray1B"); - // compile("testArray1S"); - // compile("testArray1C"); - // compile("testArray1F"); - // compile("testArray1D"); - // compile("testArray1L"); - // compile("testStoreArray1I"); - // compile("testStoreArray1J"); - // compile("testStoreArray1B"); - // compile("testStoreArray1S"); - // compile("testStoreArray1F"); - // compile("testStoreArray1D"); - } + + invoke(compile("testStoreArray1I"), array1, 2); + printReport("testStoreArray1I: " + Arrays.toString(array1)); - public static int testArray1I(int[] array, int i) { - return array[i]; - } + invoke(compile("testStoreArrayWarp0"), array2, 2); + printReport("testStoreArrayWarp0: " + Arrays.toString(array2)); - public static long testArray1J(long[] array, int i) { - return array[i]; - } + invoke(compile("testStoreArrayWarp1I"), array3, 2); + printReport("testStoreArrayWarp1I: " + Arrays.toString(array3)); - public static byte testArray1B(byte[] array, int i) { - return array[i]; - } - - public static short testArray1S(short[] array, int i) { - return array[i]; } - public static char testArray1C(char[] array, int i) { - return array[i]; - } - - public static float testArray1F(float[] array, int i) { - return array[i]; - } - - public static double testArray1D(double[] array, int i) { - return array[i]; - } - - public static Object testArray1L(Object[] array, int i) { - return array[i]; - } - - public static void testStoreArray1I(int[] array, int i, int val) { - array[i] = val; + public static void testStoreArray1I(int[] array, int i) { + array[i] = 42; } - public static void testStoreArray1B(byte[] array, int i, byte val) { - array[i] = val; - } - - public static void testStoreArray1S(short[] array, int i, short val) { - array[i] = val; + public static void testStoreArrayWarp0(int[] array, + @Warp(dimension = X) int i) { + array[i] = 42; } - public static void testStoreArray1J(long[] array, int i, long val) { - array[i] = val; + public static void testStoreArrayWarp1I(@ParallelOver(dimension = X) int[] array, + @Warp(dimension = X) int i) { + array[i] = 42; } - public static void testStoreArray1F(float[] array, int i, float val) { - array[i] = val; - } - - public static void testStoreArray1D(double[] array, int i, double val) { - array[i] = val; - } public static void printReport(String message) { // CheckStyle: stop system..print check System.out.println(message); // CheckStyle: resume system..print check - } public static void main(String[] args) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Mon Sep 30 18:05:25 2013 +0200 @@ -32,11 +32,13 @@ import com.oracle.graal.compiler.ptx.PTXBackend; import com.oracle.graal.compiler.test.GraalCompilerTest; import com.oracle.graal.debug.Debug; +import com.oracle.graal.hotspot.meta.HotSpotNmethod; import com.oracle.graal.hotspot.meta.HotSpotRuntime; import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod; import com.oracle.graal.hotspot.ptx.PTXHotSpotRuntime; import com.oracle.graal.java.GraphBuilderConfiguration; import com.oracle.graal.java.GraphBuilderPhase; +import com.oracle.graal.lir.ptx.ParallelOver; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.GraalCodeCacheProvider; import com.oracle.graal.phases.OptimisticOptimizations; @@ -44,6 +46,8 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.ptx.PTX; + +import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; public abstract class PTXTestBase extends GraalCompilerTest { @@ -102,8 +106,42 @@ boolean isStatic = Modifier.isStatic(compiledMethod.getModifiers()); Object[] executeArgs = argsWithReceiver((isStatic ? null : this), args); HotSpotRuntime hsr = (HotSpotRuntime) runtime; - InstalledCode installedCode = hsr.addExternalMethod(sg.method(), result, sg); - Object r = installedCode.executeVarargs(executeArgs); + InstalledCode installedCode = hsr.addExternalMethod(compiledMethod, result, sg); + Annotation[][] params = compiledMethod.getParameterAnnotations(); + + int dimensionX = 1; + int dimensionY = 1; + int dimensionZ = 1; + + for (int p = 0; p < params.length; p++) { + Annotation[] annos = params[p]; + if (annos != null) { + for (int a = 0; a < annos.length; a++) { + Annotation aa = annos[a]; + if (args[p] instanceof int[] && aa.annotationType().equals(ParallelOver.class)) { + int[] iarray = (int[]) args[p]; + ParallelOver threadBlockDimension = (ParallelOver) aa; + switch (threadBlockDimension.dimension()) { + case X: + dimensionX = iarray.length; + break; + case Y: + dimensionY = iarray.length; + break; + case Z: + dimensionZ = iarray.length; + break; + } + } + } + } + } + Object r; + if (dimensionX != 1 || dimensionY != 1 || dimensionZ != 1) { + r = ((HotSpotNmethod) installedCode).executeParallel(dimensionX, dimensionY, dimensionZ, executeArgs); + } else { + r = installedCode.executeVarargs(executeArgs); + } return r; } catch (Throwable th) { th.printStackTrace();
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Sep 30 18:05:25 2013 +0200 @@ -62,6 +62,9 @@ import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.java.*; +import java.lang.annotation.*; + + /** * This class implements the PTX specific portion of the LIR generator. */ @@ -120,7 +123,9 @@ if (isRegister(value)) { return asRegister(value).asValue(value.getKind().getStackKind()); } else if (isStackSlot(value)) { - return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); + return StackSlot.get(value.getKind().getStackKind(), + asStackSlot(value).getRawOffset(), + asStackSlot(value).getRawAddFrameSize()); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -132,22 +137,62 @@ public void emitPrologue() { // Need to emit .param directives based on incoming arguments and return value CallingConvention incomingArguments = cc; - int argCount = incomingArguments.getArgumentCount(); - // Additional argument for return value. - Variable[] params = new Variable[argCount + 1]; - for (int i = 0; i < argCount; i++) { - params[i] = (Variable) incomingArguments.getArgument(i); + Object returnObject = incomingArguments.getReturn(); + AllocatableValue[] params; + int argCount; + + if (returnObject == Value.ILLEGAL) { + params = incomingArguments.getArguments(); + } else { + argCount = incomingArguments.getArgumentCount(); + params = new Variable[argCount + 1]; + for (int i = 0; i < argCount; i++) { + params[i] = incomingArguments.getArgument(i); + } + params[argCount] = (Variable) returnObject; } - // Add the return value as the last parameter. - params[argCount] = (Variable) incomingArguments.getReturn(); append(new PTXParameterOp(params)); for (LocalNode local : graph.getNodes(LocalNode.class)) { Value param = params[local.index()]; - setResult(local, emitLoadParam(param.getKind(), param, null)); + Annotation[] annos = graph.method().getParameterAnnotations()[local.index()]; + Warp warpAnnotation = null; + + if (annos != null) { + for (int a = 0; a < annos.length; a++) { + if (annos[a].annotationType().equals(Warp.class)) { + warpAnnotation = (Warp) annos[a]; + } + } + } + if (warpAnnotation != null) { + setResult(local, emitWarpParam(param.getKind(), warpAnnotation)); + } else { + setResult(local, emitLoadParam(param.getKind(), param, null)); + } } } + public Variable emitWarpParam(Kind kind, Warp annotation) { + Variable result = newVariable(kind); + Variable tid = newVariable(Kind.Char); + + switch (annotation.dimension()) { + case X: + tid.setName("%tid.x"); + break; + case Y: + tid.setName("%tid.y"); + break; + case Z: + tid.setName("%tid.y"); + break; + } + emitMove(result, tid); + + return result; + } + @Override public Variable emitMove(Value input) { Variable result = newVariable(input.getKind()); @@ -168,39 +213,47 @@ public PTXAddressValue 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) { + } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) { finalDisp += asConstant(base).asLong(); baseRegister = Value.ILLEGAL; } else { baseRegister = load(base); } + } else if (base.equals(Value.ILLEGAL)) { + baseRegister = Value.ILLEGAL; } else { baseRegister = asAllocatable(base); } - @SuppressWarnings("unused") - Value indexRegister; - if (!index.equals(Value.ILLEGAL) && scale != 0) { + if (!index.equals(Value.ILLEGAL)) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; - indexRegister = Value.ILLEGAL; } else { + Value convertedIndex; + Value indexRegister; + + convertedIndex = emitConvert(Op.I2L, index); if (scale != 1) { - Variable longIndex = emitConvert(Op.I2L, index); if (CodeUtil.isPowerOf2(scale)) { - indexRegister = emitShl(longIndex, Constant.forLong(CodeUtil.log2(scale))); + indexRegister = emitShl(convertedIndex, Constant.forInt(CodeUtil.log2(scale))); } else { - indexRegister = emitMul(longIndex, Constant.forLong(scale)); + indexRegister = emitMul(convertedIndex, Constant.forInt(scale)); } } else { - indexRegister = asAllocatable(index); + indexRegister = convertedIndex; + } + if (baseRegister.equals(Value.ILLEGAL)) { + baseRegister = asAllocatable(indexRegister); + } else { + Variable longBaseRegister = newVariable(Kind.Long); + emitMove(longBaseRegister, baseRegister); + baseRegister = emitAdd(longBaseRegister, indexRegister); } } - } else { - indexRegister = Value.ILLEGAL; } return new PTXAddressValue(target().wordKind, baseRegister, finalDisp); @@ -287,6 +340,7 @@ throw GraalInternalError.unimplemented("PTXLIRGenerator.emitConditionalMove()"); } + @Override public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { throw new InternalError("NYI"); @@ -504,7 +558,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(); @@ -520,7 +574,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();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Sep 30 18:05:25 2013 +0200 @@ -447,7 +447,7 @@ @Test public void testLoop4() { SchedulePhase schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL); - assertReadWithinStartBlock(schedule, true); + assertReadWithinStartBlock(schedule, false); assertReadWithinReturnBlock(schedule, false); }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Sep 30 18:05:25 2013 +0200 @@ -236,11 +236,10 @@ FrameMap frameMap = tasm.frameMap; RegisterConfig regConfig = frameMap.registerConfig; HotSpotVMConfig config = runtime().config; - Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label(); + Label verifiedStub = new Label(); // Emit the prefix - - if (unverifiedStub != null) { + if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false); Register inlineCacheKlass = rax; // see definition of IC_Klass in @@ -257,11 +256,12 @@ } else { asm.cmpq(inlineCacheKlass, src); } - asm.jcc(ConditionFlag.NotEqual, unverifiedStub); + AMD64Call.directConditionalJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER), ConditionFlag.NotEqual); } asm.align(config.codeEntryAlignment); tasm.recordMark(Marks.MARK_OSR_ENTRY); + asm.bind(verifiedStub); tasm.recordMark(Marks.MARK_VERIFIED_ENTRY); // Emit code for the LIR @@ -278,10 +278,5 @@ // it has no calls that can cause such "return" entries assert !frameMap.accessesCallerFrame() : lirGen.getGraph(); } - - if (unverifiedStub != null) { - asm.bind(unverifiedStub); - AMD64Call.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER)); - } } }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Mon Sep 30 18:05:25 2013 +0200 @@ -60,30 +60,42 @@ } @Test - public void testAESEncryptSubstitution() throws Exception { + public void testEncryptSubstitution() throws Exception { byte[] seed = {0x4, 0x7, 0x1, 0x1}; SecureRandom random = new SecureRandom(seed); KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES"); + KeyGenerator desKeyGen = KeyGenerator.getInstance("DESede"); aesKeyGen.init(128, random); + desKeyGen.init(168, random); SecretKey aesKey = aesKeyGen.generateKey(); + SecretKey desKey = desKeyGen.generateKey(); byte[] input = readClassfile16(getClass()); - ByteArrayOutputStream expected = new ByteArrayOutputStream(); - expected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); - expected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); + ByteArrayOutputStream aesExpected = new ByteArrayOutputStream(); + aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); + aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); if (compiledAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); - Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray()); } + ByteArrayOutputStream desExpected = new ByteArrayOutputStream(); + desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input)); + desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input)); + if (compiledAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); - Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray()); + + actual.reset(); + actual.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input)); + actual.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input)); + Assert.assertArrayEquals(desExpected.toByteArray(), actual.toByteArray()); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Sep 30 18:05:25 2013 +0200 @@ -128,8 +128,7 @@ CompilationStatistics stats = CompilationStatistics.create(method, entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI); final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); if (printCompilation) { - TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), - entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ")); + TTY.println(getMethodDescription() + "..."); } if (HotSpotPrintCompilation.getValue()) { printCompilation(); @@ -161,7 +160,10 @@ }); } finally { filter.remove(); - if (printCompilation) { + final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + if (printAfterCompilation) { + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); + } else if (printCompilation) { TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); } } @@ -193,6 +195,11 @@ } } + private String getMethodDescription() { + return String.format("%-6d Graal %-70s %-45s %-50s %s", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature().getMethodDescriptor(), + entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "); + } + /** * Print a HotSpot-style compilation message to the console. */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Mon Sep 30 18:05:25 2013 +0200 @@ -55,4 +55,7 @@ long generateKernel(byte[] code, String name) throws InvalidInstalledCodeException; Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + + Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, + Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Mon Sep 30 18:05:25 2013 +0200 @@ -39,4 +39,7 @@ public native boolean deviceDetach(); public native Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + + public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, + Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon Sep 30 18:05:25 2013 +0200 @@ -123,6 +123,15 @@ return true; } + public Object executeParallel(int dimX, int dimY, int dimZ, Object... args) throws InvalidInstalledCodeException { + assert checkArgs(args); + + assert isExternal(); // for now + + return graalRuntime().getCompilerToGPU().executeParallelMethodVarargs(dimX, dimY, dimZ, args, this); + + } + @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Sep 30 18:05:25 2013 +0200 @@ -169,6 +169,12 @@ private static final String SystemClassName = "Ljava/lang/System;"; + /** + * {@inheritDoc} + * <p> + * The {@code value} field in {@link OptionValue} is considered constant if the type of + * {@code receiver} is (assignable to) {@link StableOptionValue}. + */ @Override public Constant readConstantValue(Constant receiver) { assert !AOTCompilation.getValue() || isCalledForSnippets() : receiver; @@ -198,6 +204,7 @@ } else { Class<?> clazz = object.getClass(); if (StableOptionValue.class.isAssignableFrom(clazz)) { + assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this; StableOptionValue<?> option = (StableOptionValue<?>) object; return Constant.forObject(option.getValue()); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Sep 30 18:05:25 2013 +0200 @@ -345,7 +345,11 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - return (ResolvedJavaMethod) graalRuntime().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); + ResolvedJavaMethod res = (ResolvedJavaMethod) graalRuntime().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); + if (res == null || isAbstract(res.getModifiers())) { + return null; + } + return res; } @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Sep 30 18:05:25 2013 +0200 @@ -49,6 +49,7 @@ import static com.oracle.graal.hotspot.stubs.StubUtil.*; import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; +import static com.oracle.graal.nodes.java.ArrayLengthNode.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.Log.*; @@ -994,10 +995,15 @@ private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { StructuredGraph g = n.graph(); ValueNode array = n.array(); - Stamp stamp = StampFactory.positiveInt(); - ReadNode arrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, g), stamp, BarrierType.NONE, false)); - g.addBeforeFixed(n, arrayLength); - tool.createNullCheckGuard(arrayLength, array); + ValueNode arrayLength = readArrayLength(array, tool.getRuntime()); + if (arrayLength == null) { + Stamp stamp = StampFactory.positiveInt(); + ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, g), stamp, BarrierType.NONE, false)); + g.addBeforeFixed(n, readArrayLength); + tool.createNullCheckGuard(readArrayLength, array); + arrayLength = readArrayLength; + } + return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Mon Sep 30 18:05:25 2013 +0200 @@ -56,9 +56,12 @@ Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false); - Pointer memory = Word.fromObject(result); for (int offset = instanceHeaderSize(); offset < instanceSize; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values + * to be copied atomically, but here they are copied as two 4-byte word values. + */ + ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); } return result; @@ -73,9 +76,12 @@ Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false); - Pointer memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values + * to be copied atomically, but here they are copied as two 4-byte word values. + */ + ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); } return result; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Mon Sep 30 18:05:25 2013 +0200 @@ -192,6 +192,11 @@ } } else { for (long i = 0; i < byteLength; i += VECTOR_SIZE) { + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double + * values to be copied atomically, but not long values. For example, on Intel 32-bit + * this code is not atomic as long as the vector kind remains Kind.Long. + */ Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND); UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND); } @@ -225,22 +230,22 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); - Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize); - Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize); - Word destStart = destOffset; - long sizeInBytes = ((long) length) << log2ElementSize; - Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); + Unsigned srcOffset = Word.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned destOffset = Word.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned destStart = destOffset; + Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize); + Unsigned destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); - int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE); - Word destNonVectorEnd = destStart.add(nonVectorBytes); + Unsigned nonVectorBytes = sizeInBytes.unsignedRemainder(Word.unsigned(VECTOR_SIZE)); + Unsigned destNonVectorEnd = destStart.add(nonVectorBytes); while (destOffset.belowThan(destNonVectorEnd)) { - destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION); + ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, ANY_LOCATION), ANY_LOCATION); destOffset = destOffset.add(1); srcOffset = srcOffset.add(1); } while (destOffset.belowThan(destEnd)) { - destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION); + ObjectAccess.writeWord(dest, destOffset, ObjectAccess.readWord(src, srcOffset, ANY_LOCATION), ANY_LOCATION); destOffset = destOffset.add(wordSize()); srcOffset = srcOffset.add(wordSize()); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Sep 30 18:05:25 2013 +0200 @@ -49,18 +49,16 @@ public class WriteBarrierSnippets implements Snippets { private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; - private static final SnippetCounter serialFieldWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialFieldWriteBarrier", "Number of Serial Field Write Barriers"); - private static final SnippetCounter serialArrayWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialArrayWriteBarrier", "Number of Serial Array Write Barriers"); - private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrierCounter", - "Number of attempted G1 Post Write Barriers"); - private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrierCounter", "Number of G1 attempted Pre Write Barriers"); - private static final SnippetCounter g1AttemptedRefFieldBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedRefFieldBarrierCounter", - "Number of G1 attempted Ref Field Read Barriers"); - private static final SnippetCounter g1EffectivePostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePostWriteBarrierCounter", - "Number of effective G1 Post Write Barriers"); - private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrierCounter", "Number of G1 effective Pre Write Barriers"); - private static final SnippetCounter g1EffectiveRefFieldBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveRefFieldBarrierCounter", - "Number of G1 effective Ref Field Read Barriers"); + private static final SnippetCounter serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); + private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of G1 attempted Pre Write Barriers"); + private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of G1 effective Pre Write Barriers"); + private static final SnippetCounter g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of G1 executed Pre Write Barriers"); + private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); + private static final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the XOR test)"); + private static final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the NULL test)"); + private static final SnippetCounter g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); public static final LocationIdentity GC_CARD_LOCATION = new NamedLocationIdentity("GC-Card"); public static final LocationIdentity GC_LOG_LOCATION = new NamedLocationIdentity("GC-Log"); @@ -76,11 +74,10 @@ Pointer oop; if (usePrecise) { oop = Word.fromArray(fixedObject, location); - serialArrayWriteBarrierCounter.inc(); } else { oop = Word.fromObject(fixedObject); - serialFieldWriteBarrierCounter.inc(); } + serialWriteBarrierCounter.inc(); Word base = (Word) oop.unsignedShiftRight(cardTableShift()); long startAddress = cardTableStart(); int displacement = 0; @@ -136,8 +133,9 @@ log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); } + g1AttemptedPreWriteBarrierCounter.inc(); // If the concurrent marker is enabled, the barrier is issued. - if (probability(NOT_LIKELY_PROBABILITY, markingValue != (byte) 0)) { + if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. // The load is always issued except the cases of CAS and referent field. if (probability(LIKELY_PROBABILITY, doLoad)) { @@ -146,17 +144,11 @@ log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); verifyOop(previousOop.toObject()); } - g1AttemptedPreWriteBarrierCounter.inc(); - } else { - g1AttemptedRefFieldBarrierCounter.inc(); } + g1EffectivePreWriteBarrierCounter.inc(); // If the previous value is null the barrier should not be issued. if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { - if (doLoad) { - g1EffectivePreWriteBarrierCounter.inc(); - } else { - g1EffectiveRefFieldBarrierCounter.inc(); - } + g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { @@ -217,15 +209,20 @@ Word cardAddress = cardBase.add(displacement); g1AttemptedPostWriteBarrierCounter.inc(); - if (probability(LIKELY_PROBABILITY, xorResult.notEqual(0))) { + if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) { + g1EffectiveAfterXORPostWriteBarrierCounter.inc(); + // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0); + g1EffectiveAfterNullPostWriteBarrierCounter.inc(); + // If the card is already dirty, (hence already enqueued) skip the insertion. - if (probability(LIKELY_PROBABILITY, cardByte != (byte) 0)) { - g1EffectivePostWriteBarrierCounter.inc(); + if (probability(NOT_FREQUENT_PROBABILITY, cardByte != (byte) 0)) { log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); + g1ExecutedPostWriteBarrierCounter.inc(); + // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopyGeneric.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, 2012, 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.jtt.optimize; + +import com.oracle.graal.jtt.*; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopyGeneric extends JTTTest { + + public Object[] arraysFrom; + public Object[] arraysTo; + + public void init() { + arraysFrom = new Object[]{new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + new long[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new float[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + arraysTo = new Object[]{new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + new long[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new float[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + } + + public Object test() { + init(); + + for (int i = 0; i < arraysFrom.length; i++) { + Object from = arraysFrom[i]; + Object to = arraysTo[i]; + System.arraycopy(from, 1, to, 2, 2); + System.arraycopy(from, 8, to, 7, 2); + } + return arraysTo; + } + + @Test + public void run0() throws Throwable { + runTest("test"); + } +}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Mon Sep 30 18:05:25 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.spi.*; @@ -182,6 +183,14 @@ masm.ensureUniquePC(); } + public static void directConditionalJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget target, ConditionFlag cond) { + int before = masm.codeBuffer.position(); + masm.jcc(cond, 0, true); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, target, null); + masm.ensureUniquePC(); + } + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); masm.call(dst);
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Mon Sep 30 18:05:25 2013 +0200 @@ -75,7 +75,7 @@ case D2I: case D2L: case D2F: - break; // cvt handles the move + break; // cvt handles the move default: PTXMove.move(tasm, masm, result, x); } @@ -422,11 +422,73 @@ } private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) { - if (((opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) - || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) - || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) - || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)) == false) { - throw GraalInternalError.shouldNotReachHere("opcode: " + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind()); + Kind rk; + Kind xk; + Kind yk; + Kind xsk; + Kind ysk; + + switch (opcode) { + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case IAND: + case IOR: + case IXOR: + case ISHL: + case ISHR: + case IUSHR: + rk = result.getKind(); + xsk = x.getKind().getStackKind(); + ysk = y.getKind().getStackKind(); + assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int; + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + 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.Int || yk == Kind.Long); + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Float && xk == Kind.Float && yk == Kind.Float; + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double : + "opcode=" + opcode + ", result kind=" + rk + ", x kind=" + xk + ", y kind=" + yk; + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ParallelOver.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 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.lir.ptx; + +import static com.oracle.graal.lir.ptx.ThreadDimension.*; + +import java.lang.annotation.*; +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface ParallelOver { + + String value() default ""; + + ThreadDimension dimension() default X; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ThreadDimension.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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.lir.ptx; + +public enum ThreadDimension { +X, +Y, +Z +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/Warp.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 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.lir.ptx; + +import static com.oracle.graal.lir.ptx.ThreadDimension.*; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface Warp { + + String value() default ""; + + ThreadDimension dimension() default X; +} +
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Mon Sep 30 18:05:25 2013 +0200 @@ -38,6 +38,8 @@ */ public final int index; + private String name; + /** * Creates a new variable. * @@ -50,9 +52,21 @@ this.index = index; } + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + @Override public String toString() { - return "v" + index + getKindSuffix(); + if (name != null) { + return name; + } else { + return "v" + index + getKindSuffix(); + } } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Mon Sep 30 18:05:25 2013 +0200 @@ -45,23 +45,36 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (array() instanceof ArrayLengthProvider) { - ValueNode length = ((ArrayLengthProvider) array()).length(); + ValueNode length = readArrayLength(array(), tool.runtime()); + if (length != null) { + return length; + } + return this; + } + + /** + * Gets the length of an array if possible. + * + * @param array an array + * @return a node representing the length of {@code array} or null if it is not available + */ + public static ValueNode readArrayLength(ValueNode array, MetaAccessProvider runtime) { + if (array instanceof ArrayLengthProvider) { + ValueNode length = ((ArrayLengthProvider) array).length(); if (length != null) { return length; } } - MetaAccessProvider runtime = tool.runtime(); - if (runtime != null && array().isConstant() && !array().isNullConstant()) { - Constant constantValue = array().asConstant(); + if (runtime != null && array.isConstant() && !array.isNullConstant()) { + Constant constantValue = array.asConstant(); if (constantValue != null && constantValue.isNonNull()) { Integer constantLength = runtime.lookupArrayLength(constantValue); if (constantLength != null) { - return ConstantNode.forInt(constantLength, graph()); + return ConstantNode.forInt(constantLength, array.graph()); } } } - return this; + return null; } @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Mon Sep 30 18:05:25 2013 +0200 @@ -30,6 +30,10 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; +/** + * A phase suite that applies {@linkplain CanonicalizerPhase canonicalization} to a graph after all + * phases in the suite have been applied if any of the phases changed the graph. + */ public class IncrementalCanonicalizerPhase<C extends PhaseContext> extends PhaseSuite<C> { private final CanonicalizerPhase canonicalizer; @@ -58,6 +62,8 @@ graph.stopTrackingInputChange(); graph.stopTrackingUsagesDroppedZero(); - canonicalizer.applyIncremental(graph, context, changedNodes, newNodesMark, false); + if (graph.getMark() != newNodesMark || !changedNodes.isEmpty()) { + canonicalizer.applyIncremental(graph, context, changedNodes, newNodesMark, false); + } } }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Sep 30 18:05:25 2013 +0200 @@ -167,6 +167,8 @@ @Option(help = "") public static final OptionValue<Boolean> PrintCompilation = new OptionValue<>(false); @Option(help = "") + public static final OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false); + @Option(help = "") public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false); @Option(help = "") public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Mon Sep 30 18:05:25 2013 +0200 @@ -26,6 +26,9 @@ import com.oracle.graal.nodes.*; +/** + * A compiler phase that can apply an ordered collection of phases to a graph. + */ public class PhaseSuite<C> extends BasePhase<C> { private final List<BasePhase<? super C>> phases;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,390 @@ +/* + * Copyright (c) 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.replacements.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.word.*; + +/** + * Tests for the {@link Pointer} read and write operations. + */ +public class ObjectAccessTest extends GraalCompilerTest implements Snippets { + + private static final LocationIdentity ID = new NamedLocationIdentity("ID"); + private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; + private final TargetDescription target; + private final ReplacementsImpl installer; + + public ObjectAccessTest() { + target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); + installer = new ReplacementsImpl(runtime, new Assumptions(false), target); + } + + private static final ThreadLocal<SnippetInliningPolicy> inliningPolicy = new ThreadLocal<>(); + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + } + + @Test + public void testRead1() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void testRead2() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void testRead3() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); + } + } + + @Test + public void testWrite1() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void testWrite2() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void testWrite3() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); + } + } + + private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { + ReadNode read = (ReadNode) graph.start().next(); + Assert.assertEquals(kind.getStackKind(), read.kind()); + Assert.assertEquals(graph.getLocal(0), read.object()); + + IndexedLocationNode location = (IndexedLocationNode) read.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.getLocationIdentity()); + Assert.assertEquals(1, location.getIndexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.getIndex(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.getIndex()); + } + + ReturnNode ret = (ReturnNode) read.next(); + Assert.assertEquals(read, ret.result()); + } + + private static void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { + WriteNode write = (WriteNode) graph.start().next(); + Assert.assertEquals(graph.getLocal(2), write.value()); + Assert.assertEquals(graph.getLocal(0), write.object()); + Assert.assertEquals(Kind.Void, write.kind()); + Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + + IndexedLocationNode location = (IndexedLocationNode) write.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.getLocationIdentity()); + Assert.assertEquals(1, location.getIndexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.getIndex(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.getIndex()); + } + + ReturnNode ret = (ReturnNode) write.next(); + Assert.assertEquals(null, ret.result()); + } + + @Snippet + public static byte readByte1(Object o, int offset) { + return ObjectAccess.readByte(o, offset, ID); + } + + @Snippet + public static byte readByte2(Object o, int offset) { + return ObjectAccess.readByte(o, Word.signed(offset), ID); + } + + @Snippet + public static byte readByte3(Object o, int offset) { + return ObjectAccess.readByte(o, offset); + } + + @Snippet + public static void writeByte1(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, offset, value, ID); + } + + @Snippet + public static void writeByte2(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeByte3(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, offset, value); + } + + @Snippet + public static char readChar1(Object o, int offset) { + return ObjectAccess.readChar(o, offset, ID); + } + + @Snippet + public static char readChar2(Object o, int offset) { + return ObjectAccess.readChar(o, Word.signed(offset), ID); + } + + @Snippet + public static char readChar3(Object o, int offset) { + return ObjectAccess.readChar(o, offset); + } + + @Snippet + public static void writeChar1(Object o, int offset, char value) { + ObjectAccess.writeChar(o, offset, value, ID); + } + + @Snippet + public static void writeChar2(Object o, int offset, char value) { + ObjectAccess.writeChar(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeChar3(Object o, int offset, char value) { + ObjectAccess.writeChar(o, offset, value); + } + + @Snippet + public static short readShort1(Object o, int offset) { + return ObjectAccess.readShort(o, offset, ID); + } + + @Snippet + public static short readShort2(Object o, int offset) { + return ObjectAccess.readShort(o, Word.signed(offset), ID); + } + + @Snippet + public static short readShort3(Object o, int offset) { + return ObjectAccess.readShort(o, offset); + } + + @Snippet + public static void writeShort1(Object o, int offset, short value) { + ObjectAccess.writeShort(o, offset, value, ID); + } + + @Snippet + public static void writeShort2(Object o, int offset, short value) { + ObjectAccess.writeShort(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeShort3(Object o, int offset, short value) { + ObjectAccess.writeShort(o, offset, value); + } + + @Snippet + public static int readInt1(Object o, int offset) { + return ObjectAccess.readInt(o, offset, ID); + } + + @Snippet + public static int readInt2(Object o, int offset) { + return ObjectAccess.readInt(o, Word.signed(offset), ID); + } + + @Snippet + public static int readInt3(Object o, int offset) { + return ObjectAccess.readInt(o, offset); + } + + @Snippet + public static void writeInt1(Object o, int offset, int value) { + ObjectAccess.writeInt(o, offset, value, ID); + } + + @Snippet + public static void writeInt2(Object o, int offset, int value) { + ObjectAccess.writeInt(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeInt3(Object o, int offset, int value) { + ObjectAccess.writeInt(o, offset, value); + } + + @Snippet + public static long readLong1(Object o, int offset) { + return ObjectAccess.readLong(o, offset, ID); + } + + @Snippet + public static long readLong2(Object o, int offset) { + return ObjectAccess.readLong(o, Word.signed(offset), ID); + } + + @Snippet + public static long readLong3(Object o, int offset) { + return ObjectAccess.readLong(o, offset); + } + + @Snippet + public static void writeLong1(Object o, int offset, long value) { + ObjectAccess.writeLong(o, offset, value, ID); + } + + @Snippet + public static void writeLong2(Object o, int offset, long value) { + ObjectAccess.writeLong(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeLong3(Object o, int offset, long value) { + ObjectAccess.writeLong(o, offset, value); + } + + @Snippet + public static float readFloat1(Object o, int offset) { + return ObjectAccess.readFloat(o, offset, ID); + } + + @Snippet + public static float readFloat2(Object o, int offset) { + return ObjectAccess.readFloat(o, Word.signed(offset), ID); + } + + @Snippet + public static float readFloat3(Object o, int offset) { + return ObjectAccess.readFloat(o, offset); + } + + @Snippet + public static void writeFloat1(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, offset, value, ID); + } + + @Snippet + public static void writeFloat2(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeFloat3(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, offset, value); + } + + @Snippet + public static double readDouble1(Object o, int offset) { + return ObjectAccess.readDouble(o, offset, ID); + } + + @Snippet + public static double readDouble2(Object o, int offset) { + return ObjectAccess.readDouble(o, Word.signed(offset), ID); + } + + @Snippet + public static double readDouble3(Object o, int offset) { + return ObjectAccess.readDouble(o, offset); + } + + @Snippet + public static void writeDouble1(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, offset, value, ID); + } + + @Snippet + public static void writeDouble2(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeDouble3(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, offset, value); + } + + @Snippet + public static Object readObject1(Object o, int offset) { + return ObjectAccess.readObject(o, offset, ID); + } + + @Snippet + public static Object readObject2(Object o, int offset) { + return ObjectAccess.readObject(o, Word.signed(offset), ID); + } + + @Snippet + public static Object readObject3(Object o, int offset) { + return ObjectAccess.readObject(o, offset); + } + + @Snippet + public static void writeObject1(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, offset, value, ID); + } + + @Snippet + public static void writeObject2(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeObject3(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, offset, value); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.java Mon Sep 30 18:05:25 2013 +0200 @@ -0,0 +1,936 @@ +/* + * Copyright (c) 2013, 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.word; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.word.Word.Opcode; +import com.oracle.graal.word.Word.Operation; + +/** + * Low-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for + * {@link Pointer}, these methods access the raw memory without any null checks, read- or write + * barriers. + */ +public final class ObjectAccess { + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, WordBase offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, WordBase offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, WordBase offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, WordBase offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, WordBase offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, WordBase offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, WordBase offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, WordBase offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, WordBase offset, Object val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, int offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, int offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, int offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, int offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, int offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, int offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, int offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, int offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, int offset, Object val, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, int offset); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, WordBase offset, byte val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, WordBase offset, char val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, WordBase offset, short val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, WordBase offset, int val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, WordBase offset, long val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, WordBase offset, float val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, WordBase offset, double val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, WordBase offset, WordBase val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * <p> + * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, WordBase offset, Object val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, int offset, byte val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, int offset, char val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, int offset, short val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, int offset, int val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, int offset, long val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, int offset, float val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, int offset, double val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, int offset, WordBase val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, int offset, Object val); +}
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Sep 30 18:05:25 2013 +0200 @@ -50,6 +50,7 @@ protected final MetaAccessProvider metaAccess; protected final ResolvedJavaType wordBaseType; protected final ResolvedJavaType wordImplType; + protected final ResolvedJavaType objectAccessType; protected final Kind wordKind; public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) { @@ -57,6 +58,7 @@ this.wordKind = wordKind; this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); this.wordImplType = metaAccess.lookupJavaType(Word.class); + this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class); } @Override @@ -191,8 +193,11 @@ */ protected void rewriteInvoke(StructuredGraph graph, MethodCallTargetNode callTargetNode) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); - if (!wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass())) { - /* Not a method defined on WordBase or a subclass / subinterface, so nothing to rewrite. */ + if (!wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass()) && !objectAccessType.equals(targetMethod.getDeclaringClass())) { + /* + * Not a method defined on WordBase or a subclass / subinterface, and not on + * ObjectAccess, so nothing to rewrite. + */ return; } @@ -252,7 +257,7 @@ case WRITE: case INITIALIZE: { assert arguments.size() == 3 || arguments.size() == 4; - Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass())); + Kind writeKind = asKind(targetMethod.getSignature().getParameterType(Modifier.isStatic(targetMethod.getModifiers()) ? 2 : 1, targetMethod.getDeclaringClass())); LocationNode location; if (arguments.size() == 3) { location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Thu Sep 26 17:33:04 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Sep 30 18:05:25 2013 +0200 @@ -102,6 +102,7 @@ * * @return the assigned source code section */ + @CompilerDirectives.SlowPath public final SourceSection getEncapsulatingSourceSection() { if (sourceSection == null && getParent() != null) { return getParent().getEncapsulatingSourceSection();
--- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Mon Sep 30 18:05:25 2013 +0200 @@ -50,6 +50,9 @@ // the inlined vtable stub contains a "call register" instruction assert(method != NULL, "only valid for virtual calls"); return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset()); + } else if (inst->is_cond_jump()) { + address pc = (address) (inst); + return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc); } else { fatal("unsupported type of instruction for call site"); return 0; @@ -145,21 +148,30 @@ } inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { + address pc = (address) inst; if (inst->is_call()) { // NOTE: for call without a mov, the offset must fit a 32-bit immediate // see also CompilerToVM.getMaxCallTargetOffset() - NativeCall* call = nativeCall_at((address) (inst)); + NativeCall* call = nativeCall_at(pc); call->set_destination((address) foreign_call_destination); _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); } else if (inst->is_mov_literal64()) { - NativeMovConstReg* mov = nativeMovConstReg_at((address) (inst)); + NativeMovConstReg* mov = nativeMovConstReg_at(pc); mov->set_data((intptr_t) foreign_call_destination); _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); - } else { - NativeJump* jump = nativeJump_at((address) (inst)); + } else if (inst->is_jump()) { + NativeJump* jump = nativeJump_at(pc); jump->set_jump_destination((address) foreign_call_destination); - _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); + _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); + } else if (inst->is_cond_jump()) { + address old_dest = nativeGeneralJump_at(pc)->jump_destination(); + address disp = Assembler::locate_operand(pc, Assembler::call32_operand); + *(jint*) disp += ((address) foreign_call_destination) - old_dest; + _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand); + } else { + fatal("unsupported relocation for foreign call"); } + TRACE_graal_3("relocating (foreign call) at %p", inst); }
--- a/src/gpu/ptx/vm/gpu_ptx.cpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/gpu/ptx/vm/gpu_ptx.cpp Mon Sep 30 18:05:25 2013 +0200 @@ -228,15 +228,20 @@ } bool gpu::Ptx::execute_kernel(address kernel, PTXKernelArguments &ptxka, JavaValue &ret) { + return gpu::Ptx::execute_warp(1, 1, 1, kernel, ptxka, ret); +} + +bool gpu::Ptx::execute_warp(int dimX, int dimY, int dimZ, + address kernel, PTXKernelArguments &ptxka, JavaValue &ret) { // grid dimensionality unsigned int gridX = 1; unsigned int gridY = 1; unsigned int gridZ = 1; // thread dimensionality - unsigned int blockX = 1; - unsigned int blockY = 1; - unsigned int blockZ = 1; + unsigned int blockX = dimX; + unsigned int blockY = dimY; + unsigned int blockZ = dimZ; struct CUfunc_st* cu_function = (struct CUfunc_st*) kernel; @@ -264,7 +269,7 @@ } if (TraceGPUInteraction) { - tty->print_cr("[CUDA] Success: Kernel Launch"); + tty->print_cr("[CUDA] Success: Kernel Launch: X: %d Y: %d Z: %d", blockX, blockY, blockZ); } status = _cuda_cu_ctx_synchronize(); @@ -282,7 +287,7 @@ // Get the result. TODO: Move this code to get_return_oop() BasicType return_type = ptxka.get_ret_type(); switch (return_type) { - case T_INT : + case T_INT: { int return_val; status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_INT_BYTE_SIZE); @@ -293,7 +298,7 @@ ret.set_jint(return_val); } break; - case T_LONG : + case T_LONG: { long return_val; status = gpu::Ptx::_cuda_cu_memcpy_dtoh(&return_val, ptxka._return_value_ptr, T_LONG_BYTE_SIZE); @@ -304,10 +309,14 @@ ret.set_jlong(return_val); } break; + case T_VOID: + break; default: - tty->print_cr("[CUDA] TODO *** Unhandled return type"); + tty->print_cr("[CUDA] TODO *** Unhandled return type: %d", return_type); } + // handle post-invocation object and array arguemtn + ptxka.reiterate(); // Free device memory allocated for result status = gpu::Ptx::_cuda_cu_memfree(ptxka._return_value_ptr);
--- a/src/gpu/ptx/vm/gpu_ptx.hpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/gpu/ptx/vm/gpu_ptx.hpp Mon Sep 30 18:05:25 2013 +0200 @@ -74,6 +74,7 @@ static bool probe_linkage(); static bool initialize_gpu(); static void * generate_kernel(unsigned char *code, int code_len, const char *name); + static bool execute_warp(int dimX, int dimY, int dimZ, address kernel, PTXKernelArguments & ka, JavaValue &ret); static bool execute_kernel(address kernel, PTXKernelArguments & ka, JavaValue &ret); public: #if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
--- a/src/gpu/ptx/vm/ptxKernelArguments.cpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/gpu/ptx/vm/ptxKernelArguments.cpp Mon Sep 30 18:05:25 2013 +0200 @@ -32,12 +32,18 @@ // Get next java argument oop PTXKernelArguments::next_arg(BasicType expectedType) { assert(_index < _args->length(), "out of bounds"); - oop arg=((objArrayOop) (_args))->obj_at(_index++); - assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); + + oop arg = ((objArrayOop) (_args))->obj_at(_index++); + assert(expectedType == T_OBJECT || + java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); + return arg; } -void PTXKernelArguments::do_int() { +void PTXKernelArguments::do_int() { + if (is_after_invocation()) { + return; + } // If the parameter is a return value, if (is_return_type()) { // Allocate device memory for T_INT return value pointer on device. Size in bytes @@ -50,8 +56,7 @@ // Push _return_value_ptr to _kernelBuffer *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; _bufferOffset += sizeof(_return_value_ptr); - } - else { + } else { // Get the next java argument and its value which should be a T_INT oop arg = next_arg(T_INT); // Copy the java argument value to kernelArgBuffer @@ -67,7 +72,10 @@ return; } -void PTXKernelArguments::do_long() { +void PTXKernelArguments::do_long() { + if (is_after_invocation()) { + return; + } // If the parameter is a return value, if (is_return_type()) { // Allocate device memory for T_LONG return value pointer on device. Size in bytes @@ -80,8 +88,7 @@ // Push _return_value_ptr to _kernelBuffer *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; _bufferOffset += sizeof(_return_value_ptr); - } - else { + } else { // Get the next java argument and its value which should be a T_LONG oop arg = next_arg(T_LONG); // Copy the java argument value to kernelArgBuffer @@ -97,34 +104,81 @@ return; } -void PTXKernelArguments::do_byte() { - // If the parameter is a return value, - if (is_return_type()) { - // Allocate device memory for T_BYTE return value pointer on device. Size in bytes - int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BYTE_SIZE); +void PTXKernelArguments::do_byte() { + if (is_after_invocation()) { + return; + } + // If the parameter is a return value, + if (is_return_type()) { + // Allocate device memory for T_BYTE return value pointer on device. Size in bytes + int status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, T_BYTE_SIZE); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; + return; + } + // Push _return_value_ptr to _kernelBuffer + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; + _bufferOffset += sizeof(_return_value_ptr); + } else { + // Get the next java argument and its value which should be a T_BYTE + oop arg = next_arg(T_BYTE); + // Copy the java argument value to kernelArgBuffer + jvalue val; + if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) { + tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); + _success = false; + return; + } + *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b; + _bufferOffset += sizeof(val.b); + } + return; +} + +void PTXKernelArguments::do_array(int begin, int end) { + gpu::Ptx::CUdeviceptr _array_ptr; + int status; + + // Get the next java argument and its value which should be a T_ARRAY + oop arg = next_arg(T_OBJECT); + int array_size = arg->size() * HeapWordSize; + + if (is_after_invocation()) { + _array_ptr = *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]); + status = gpu::Ptx::_cuda_cu_memcpy_dtoh(arg, _array_ptr, array_size); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to copy array argument to host", status); + _success = false; + return; + } else { + // tty->print_cr("device: %x host: %x size: %d", _array_ptr, arg, array_size); + } + return; + } + // Allocate device memory for T_ARRAY return value pointer on device. Size in bytes + status = gpu::Ptx::_cuda_cu_memalloc(&_return_value_ptr, array_size); if (status != GRAAL_CUDA_SUCCESS) { - tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); - _success = false; - return; + tty->print_cr("[CUDA] *** Error (%d) Failed to allocate memory for return value pointer on device", status); + _success = false; + return; + } + status = gpu::Ptx::_cuda_cu_memcpy_htod(_return_value_ptr, arg, array_size); + if (status != GRAAL_CUDA_SUCCESS) { + tty->print_cr("[CUDA] *** Error (%d) Failed to copy array to device argument", status); + _success = false; + return; + } else { + // tty->print_cr("host: %x device: %x size: %d", arg, _return_value_ptr, array_size); } // Push _return_value_ptr to _kernelBuffer *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = _return_value_ptr; _bufferOffset += sizeof(_return_value_ptr); - } - else { - // Get the next java argument and its value which should be a T_BYTE - oop arg = next_arg(T_BYTE); - // Copy the java argument value to kernelArgBuffer - jvalue val; - if (java_lang_boxing_object::get_value(arg, &val) != T_BYTE) { - tty->print_cr("[CUDA] *** Error: Unexpected argument type; expecting T_BYTE"); - _success = false; - return; - } - *((gpu::Ptx::CUdeviceptr*) &_kernelArgBuffer[_bufferOffset]) = val.b; - _bufferOffset += sizeof(val.b); - } - return; + return; +} + +void PTXKernelArguments::do_void() { + return; } // TODO implement other do_*
--- a/src/gpu/ptx/vm/ptxKernelArguments.hpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/gpu/ptx/vm/ptxKernelArguments.hpp Mon Sep 30 18:05:25 2013 +0200 @@ -31,6 +31,7 @@ #define T_BYTE_SIZE 1 #define T_INT_BYTE_SIZE 4 #define T_LONG_BYTE_SIZE 8 +#define T_ARRAY_BYTE_SIZE 8 class PTXKernelArguments : public SignatureIterator { public: @@ -46,6 +47,8 @@ int _index; // Flag to indicate successful creation of kernel argument buffer bool _success; + + bool _afterInvoocation; // Get next java argument oop next_arg(BasicType expectedType); @@ -74,6 +77,17 @@ return _bufferOffset; } + void reiterate() { + _afterInvoocation = true; + _bufferOffset = 0; + _index = 0; + iterate(); + } + + inline bool is_after_invocation() { + return _afterInvoocation; + } + // Get the return oop value oop get_return_oop(); @@ -86,44 +100,40 @@ void do_byte(); void do_int(); void do_long(); + void do_array(int begin, int end); + void do_void(); inline void do_bool() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_bool:NYI"); } inline void do_char() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_char:NYI"); } inline void do_short() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_short:NYI"); } inline void do_float() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_float:NYI"); } inline void do_double() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_double:NYI"); } inline void do_object() { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_object:NYI"); } + inline void do_object(int begin, int end) { /* TODO : To be implemented */ - guarantee(false, "NYI"); + guarantee(false, "do_object(II):NYI"); } - inline void do_array(int begin, int end) { - /* TODO : To be implemented */ - guarantee(false, "NYI"); - } - inline void do_void() { - /* TODO : To be implemented */ - guarantee(false, "NYI"); - } + }; #endif // KERNEL_ARGUMENTS_HPP
--- a/src/share/vm/graal/graalCodeInstaller.cpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Sep 30 18:05:25 2013 +0200 @@ -727,7 +727,7 @@ oop debug_info = CompilationResult_Call::debugInfo(site); - assert((hotspot_method ? 1 : 0) + (foreign_call ? 1 : 0) == 1, "Call site needs exactly one type"); + assert(!!hotspot_method ^ !!foreign_call, "Call site needs exactly one type"); NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
--- a/src/share/vm/graal/graalCompilerToGPU.cpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToGPU.cpp Mon Sep 30 18:05:25 2013 +0200 @@ -103,6 +103,45 @@ C2V_END +C2V_VMENTRY(jobject, executeParallelMethodVarargs, (JNIEnv *env, + jobject, + jint dimX, jint dimY, jint dimZ, + jobject args, jobject hotspotInstalledCode)) + ResourceMark rm; + HandleMark hm; + + if (gpu::is_available() == false || gpu::has_gpu_linkage() == false && gpu::is_initialized()) { + tty->print_cr("executeExternalMethodVarargs - not available / no linkage / not initialized"); + return NULL; + } + jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); + nmethod* nm = (nmethod*) (address) nmethodValue; + methodHandle mh = nm->method(); + Symbol* signature = mh->signature(); + + // start value is the kernel + jlong startValue = HotSpotInstalledCode::codeStart(hotspotInstalledCode); + + PTXKernelArguments ptxka(signature, (arrayOop) JNIHandles::resolve(args), mh->is_static()); + JavaValue result(ptxka.get_ret_type()); +if (!gpu::execute_warp(dimX, dimY, dimZ, (address)startValue, ptxka, result)) { + return NULL; + } + + if (ptxka.get_ret_type() == T_VOID) { + return NULL; + } else if (ptxka.get_ret_type() == T_OBJECT || ptxka.get_ret_type() == T_ARRAY) { + return JNIHandles::make_local((oop) result.get_jobject()); + } else { + oop o = java_lang_boxing_object::create(ptxka.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); + if (TraceGPUInteraction) { + tty->print_cr("GPU execution returned %d", result.get_jint()); + } + return JNIHandles::make_local(o); + } + +C2V_END + C2V_VMENTRY(jboolean, deviceInit, (JNIEnv *env, jobject)) if (gpu::is_available() == false || gpu::has_gpu_linkage() == false) { tty->print_cr("deviceInit - not available / no linkage"); @@ -157,10 +196,11 @@ #define GPUSPACE_METHOD "J" JNINativeMethod CompilerToGPU_methods[] = { - {CC"generateKernel", CC"([B" STRING ")"GPUSPACE_METHOD, FN_PTR(generateKernel)}, - {CC"deviceInit", CC"()Z", FN_PTR(deviceInit)}, - {CC"deviceDetach", CC"()Z", FN_PTR(deviceDetach)}, - {CC"executeExternalMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeExternalMethodVarargs)}, + {CC"generateKernel", CC"([B" STRING ")"GPUSPACE_METHOD, FN_PTR(generateKernel)}, + {CC"deviceInit", CC"()Z", FN_PTR(deviceInit)}, + {CC"deviceDetach", CC"()Z", FN_PTR(deviceDetach)}, + {CC"executeExternalMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeExternalMethodVarargs)}, + {CC"executeParallelMethodVarargs", CC"(III["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeParallelMethodVarargs)}, }; int CompilerToGPU_methods_count() {
--- a/src/share/vm/runtime/gpu.cpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/share/vm/runtime/gpu.cpp Mon Sep 30 18:05:25 2013 +0200 @@ -61,12 +61,23 @@ } bool gpu::execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue& ret) { - if (gpu::has_gpu_linkage()) { - if (gpu::get_target_il_type() == gpu::PTX) { - return (gpu::Ptx::execute_kernel(kernel, ptxka, ret)); + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::execute_kernel(kernel, ptxka, ret)); + } + // Add kernel execution functionality of other GPUs here } - // Add kernel execution functionality of other GPUs here - } - return false; + return false; } +bool gpu::execute_warp(int dimX, int dimY, int dimZ, + address kernel, PTXKernelArguments & ptxka, JavaValue& ret) { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::execute_warp(dimX, dimY, dimZ, kernel, ptxka, ret)); + } + // Add kernel execution functionality of other GPUs here + } + return false; +} +
--- a/src/share/vm/runtime/gpu.hpp Thu Sep 26 17:33:04 2013 +0200 +++ b/src/share/vm/runtime/gpu.hpp Mon Sep 30 18:05:25 2013 +0200 @@ -46,6 +46,9 @@ static void * generate_kernel(unsigned char *code, int code_len, const char *name); + static bool execute_warp(int dimX, int dimY, int dimZ, + address kernel, PTXKernelArguments & ptxka, JavaValue & ret); + static bool execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue & ret); static void set_available(bool value) {