From bed60175eca1056ae792f796ca1154ec8bb8033c Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 9 Jul 2018 14:33:10 +0200 Subject: [PATCH 01/12] Add missing specializations. Bugfix for frameslot reading. --- .../truffle/llvm/nodes/op/LLVMLogicNode.java | 31 +++++++++++++++++++ .../truffle/llvm/nodes/vars/LLVMReadNode.java | 23 ++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java index ad8f6f864..5df6ae1cb 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java @@ -29,11 +29,15 @@ */ package com.oracle.truffle.llvm.nodes.op; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeChildren; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; +import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; +import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; import com.oracle.truffle.llvm.runtime.vector.LLVMI16Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI1Vector; @@ -288,6 +292,33 @@ protected long ashr(long left, long right) { return left >>> right; } + @Specialization + protected long ashr(LLVMNativePointer left, long right) { + return ashr(left.asNative(), right); + } + + @Specialization + protected long ashr(long left, LLVMNativePointer right) { + return ashr(left, right.asNative()); + } + + @Specialization + protected long ashr(LLVMNativePointer left, LLVMNativePointer right) { + return ashr(left.asNative(), right.asNative()); + } + + @Specialization + protected long ashr(LLVMManagedPointer left, long right, + @Cached("createToNativeWithTarget()") LLVMToNativeNode toNative) { + return ashr(toNative.executeWithTarget(left), right); + } + + @Specialization + protected long ashr(LLVMManagedPointer left, LLVMNativePointer right, + @Cached("createToNativeWithTarget()") LLVMToNativeNode toNative) { + return ashr(toNative.executeWithTarget(left), right.asNative()); + } + @Specialization protected byte ashr(byte left, byte right) { return (byte) ((left & LLVMExpressionNode.I8_MASK) >>> right); diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/vars/LLVMReadNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/vars/LLVMReadNode.java index a559dc440..acda1a7fb 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/vars/LLVMReadNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/vars/LLVMReadNode.java @@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.FrameUtil; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; @@ -81,19 +82,23 @@ protected int readI32(VirtualFrame frame) { } public abstract static class LLVMI64ReadNode extends LLVMReadNode { - - protected final boolean isLongSlot() { - return getSlot().getKind() == FrameSlotKind.Long; + @Specialization(rewriteOn = FrameSlotTypeException.class) + protected long readI64(VirtualFrame frame) throws FrameSlotTypeException { + return frame.getLong(getSlot()); } - @Specialization(guards = "isLongSlot()") - protected long readI64(VirtualFrame frame) { - return FrameUtil.getLongSafe(frame, getSlot()); + @Specialization(rewriteOn = FrameSlotTypeException.class) + protected Object readObject(VirtualFrame frame) throws FrameSlotTypeException { + return frame.getObject(getSlot()); } - @Specialization(guards = "!isLongSlot()") - protected Object readI64Object(VirtualFrame frame) { - return FrameUtil.getObjectSafe(frame, getSlot()); + @Specialization + protected Object readGeneric(VirtualFrame frame) { + if (getSlot().getKind() == FrameSlotKind.Long) { + return FrameUtil.getLongSafe(frame, getSlot()); + } else { + return FrameUtil.getObjectSafe(frame, getSlot()); + } } } From 0db81e6d9b49ccad76e454268437f69739bd751c Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 9 Jul 2018 11:49:23 +0200 Subject: [PATCH 02/12] Initialize AT_RANDOM. --- .../src/crt0.c | 11 +++--- .../truffle/llvm/runtime/LLVMContext.java | 34 +++++++++++++++---- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.libraries.bitcode/src/crt0.c b/projects/com.oracle.truffle.llvm.libraries.bitcode/src/crt0.c index ff2ee3bcc..ec7ff8f9c 100644 --- a/projects/com.oracle.truffle.llvm.libraries.bitcode/src/crt0.c +++ b/projects/com.oracle.truffle.llvm.libraries.bitcode/src/crt0.c @@ -37,6 +37,7 @@ #else #define AT_NULL 0 #define AT_PLATFORM 15 +#define AT_RANDOM 25 #define AT_EXECFN 31 typedef struct { uint64_t a_type; @@ -76,10 +77,10 @@ void __sulong_init_libc(char **envp, char *pn) { // nothing to do } -void __sulong_init_context(void **argv_java_byte_arrays, void **envp_java_byte_arrays) { +void __sulong_init_context(void **argv_java_byte_arrays, void **envp_java_byte_arrays, void **random_java_byte_array) { int argc = polyglot_get_array_size(argv_java_byte_arrays); int envc = polyglot_get_array_size(envp_java_byte_arrays); - int auxc = 3; + int auxc = 4; size_t total_argument_size = sizeof(void *) + (argc + 1) * sizeof(char *) + (envc + 1) * sizeof(char *) + auxc * sizeof(Elf64_auxv_t); long *p = __sulong_start_arguments = malloc(total_argument_size); @@ -98,8 +99,10 @@ void __sulong_init_context(void **argv_java_byte_arrays, void **envp_java_byte_a aux[0].a_un.a_val = (uint64_t)argv[0]; aux[1].a_type = AT_PLATFORM; aux[1].a_un.a_val = (uint64_t) "x86_64"; - aux[2].a_type = AT_NULL; - aux[2].a_un.a_val = 0; + aux[2].a_type = AT_RANDOM; + aux[2].a_un.a_val = (uint64_t)__sulong_byte_array_to_native(random_java_byte_array); + aux[3].a_type = AT_NULL; + aux[3].a_un.a_val = 0; __sulong_init_libc(envp, argv[0]); } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java index 7768459cf..fa2d3a4eb 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMContext.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -213,7 +214,7 @@ public void initialize() { LLVMFunctionDescriptor initContextDescriptor = globalScope.getFunction("@__sulong_init_context"); RootCallTarget initContextFunction = initContextDescriptor.getLLVMIRFunction(); try (StackPointer stackPointer = threadingStack.getStack().newFrame()) { - Object[] args = new Object[]{stackPointer, toTruffleObjects(getApplicationArguments()), toTruffleObjects(getEnvironmentVariables())}; + Object[] args = new Object[]{stackPointer, getApplicationArguments(), getEnvironmentVariables(), getRandomValues()}; initContextFunction.call(args); } } @@ -227,7 +228,7 @@ public void setDefaultLibrariesLoaded() { defaultLibrariesLoaded = true; } - private String[] getApplicationArguments() { + private LLVMManagedPointer getApplicationArguments() { int mainArgsCount = mainArguments == null ? 0 : mainArguments.length; String[] result = new String[mainArgsCount + 1]; // we don't have an application path at this point in time. it will be overwritten when @@ -236,19 +237,38 @@ private String[] getApplicationArguments() { for (int i = 1; i < result.length; i++) { result[i] = mainArguments[i - 1].toString(); } - return result; + return toTruffleObjects(result); + } + + private LLVMManagedPointer getEnvironmentVariables() { + String[] result = environment.entrySet().stream().map((e) -> e.getKey() + "=" + e.getValue()).toArray(String[]::new); + return toTruffleObjects(result); + } + + private LLVMManagedPointer getRandomValues() { + byte[] result = new byte[16]; + random().nextBytes(result); + return toManagedPointer(toTruffleObject(result)); } - private String[] getEnvironmentVariables() { - return environment.entrySet().stream().map((e) -> e.getKey() + "=" + e.getValue()).toArray(String[]::new); + private static Random random() { + return new Random(); } private LLVMManagedPointer toTruffleObjects(String[] values) { TruffleObject[] result = new TruffleObject[values.length]; for (int i = 0; i < values.length; i++) { - result[i] = (TruffleObject) env.asGuestValue(values[i].getBytes()); + result[i] = toTruffleObject(values[i].getBytes()); } - return LLVMManagedPointer.create(LLVMTypedForeignObject.createUnknown((TruffleObject) env.asGuestValue(result))); + return toManagedPointer(toTruffleObject(result)); + } + + private TruffleObject toTruffleObject(Object value) { + return (TruffleObject) env.asGuestValue(value); + } + + private static LLVMManagedPointer toManagedPointer(TruffleObject value) { + return LLVMManagedPointer.create(LLVMTypedForeignObject.createUnknown(value)); } public void dispose(LLVMMemory memory) { From 0d3669204fb756cfef6a00977411a630d9a9cebb Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 10 Jul 2018 16:12:54 +0200 Subject: [PATCH 03/12] Globals bugfixes. --- .../src/com/oracle/truffle/llvm/Runner.java | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java index c4eddcfdf..b87f2f9ce 100644 --- a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java +++ b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Runner.java @@ -377,58 +377,85 @@ private CallTarget parse(Source source, ByteBuffer bytes, ExternalLibrary librar private void allocateGlobals(List parserResults) { for (LLVMParserResult res : parserResults) { - ArrayList globals = new ArrayList<>(); - for (GlobalVariable symbol : res.getDefinedGlobals()) { - LLVMGlobal global = res.getRuntime().getFileScope().getGlobalVariable(symbol.getName()); - globals.add(global); - } - allocateGlobals(globals); + allocateGlobals(res); } } - private void allocateGlobals(ArrayList globals) { + private void allocateGlobals(LLVMParserResult res) { DataLayout dataLayout = context.getDataSpecConverter(); - // divide into pointer and non-pointer globals - ArrayList nonPointerTypes = new ArrayList<>(); - for (LLVMGlobal global : globals) { - Type type = global.getPointeeType(); - if (!isSpecialGlobalSlot(type)) { - // allocate at least one byte per global (to make the pointers unique) - if (type.getSize(dataLayout) == 0) { - nonPointerTypes.add(PrimitiveType.getIntegerType(8)); - } - nonPointerTypes.add(type); - } - } - - StructureType structType = new StructureType("globals_struct", false, nonPointerTypes.toArray(new Type[0])); + // allocate all non-pointer types as one struct + ArrayList nonPointerTypes = getNonPointerTypes(res, dataLayout); + StructureType structType = new StructureType("globals_struct", true, nonPointerTypes.toArray(new Type[0])); LLVMAllocateStructNode allocationNode = nodeFactory.createAllocateStruct(context, structType); LLVMPointer nonPointerStore = allocationNode.executeWithTarget(); + LLVMScope fileScope = res.getRuntime().getFileScope(); HashMap reverseMap = new HashMap<>(); int nonPointerOffset = 0; - for (LLVMGlobal global : globals) { - Type type = global.getPointeeType(); + for (GlobalVariable global : res.getDefinedGlobals()) { + Type type = global.getType().getPointeeType(); LLVMPointer ref; - if (isSpecialGlobalSlot(global.getPointeeType())) { + if (isSpecialGlobalSlot(global.getType().getPointeeType())) { ref = LLVMManagedPointer.create(new LLVMGlobalContainer()); } else { // allocate at least one byte per global (to make the pointers unique) if (type.getSize(dataLayout) == 0) { type = PrimitiveType.getIntegerType(8); } - nonPointerOffset += Type.getPadding(nonPointerOffset, type, dataLayout); + int alignment = getAlignment(dataLayout, global, type); + nonPointerOffset += Type.getPadding(nonPointerOffset, alignment); ref = nonPointerStore.increment(nonPointerOffset); nonPointerOffset += type.getSize(dataLayout); } - global.setTarget(ref); - reverseMap.put(ref, global); + + LLVMGlobal descriptor = fileScope.getGlobalVariable(global.getName()); + if (!descriptor.isInitialized()) { + // because of our symbol overriding support, it can happen that the global was + // already bound before to a different target location + descriptor.setTarget(ref); + reverseMap.put(ref, descriptor); + } } context.registerGlobals(nonPointerStore, reverseMap); } + private static ArrayList getNonPointerTypes(LLVMParserResult res, DataLayout dataLayout) { + ArrayList result = new ArrayList<>(); + int nonPointerOffset = 0; + for (GlobalVariable global : res.getDefinedGlobals()) { + Type type = global.getType().getPointeeType(); + if (!isSpecialGlobalSlot(type)) { + // allocate at least one byte per global (to make the pointers unique) + if (type.getSize(dataLayout) == 0) { + type = PrimitiveType.getIntegerType(8); + } + int alignment = getAlignment(dataLayout, global, type); + int padding = Type.getPadding(nonPointerOffset, alignment); + addPaddingTypes(result, padding); + nonPointerOffset += padding; + result.add(type); + nonPointerOffset += type.getSize(dataLayout); + } + } + return result; + } + + private static void addPaddingTypes(ArrayList result, int padding) { + assert padding >= 0; + int remaining = padding; + while (remaining > 0) { + int size = Math.min(Long.BYTES, Integer.highestOneBit(remaining)); + result.add(PrimitiveType.getIntegerType(size * Byte.SIZE)); + remaining -= size; + } + } + + private static int getAlignment(DataLayout dataLayout, GlobalVariable global, Type type) { + return global.getAlign() > 0 ? 1 << (global.getAlign() - 1) : type.getAlignment(dataLayout); + } + private static boolean isSpecialGlobalSlot(Type type) { // globals of pointer type can potentially contain a TruffleObject return type instanceof PointerType; From 64d6c32321bedde1dce59771030341013bf3bb6b Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 10 Jul 2018 18:33:35 +0200 Subject: [PATCH 04/12] Refactorings. --- .../nodes/func/LLVMLookupDispatchNode.java | 2 +- .../memory/load/LLVMAbstractLoadNode.java | 2 +- .../load/LLVMDerefHandleGetReceiverNode.java | 12 +- .../memory/store/LLVMStoreNodeCommon.java | 2 +- .../llvm/runtime/memory/LLVMMemory.java | 841 +++------------- .../llvm/runtime/memory/LLVMNativeMemory.java | 923 ++++++++++++++++++ .../truffle/llvm/BasicConfiguration.java | 3 +- 7 files changed, 1045 insertions(+), 740 deletions(-) create mode 100644 projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMNativeMemory.java diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLookupDispatchNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLookupDispatchNode.java index bbcec126a..bcee7d03c 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLookupDispatchNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLookupDispatchNode.java @@ -213,7 +213,7 @@ protected boolean isAutoDerefHandle(LLVMNativePointer addr) { protected LLVMDerefHandleGetReceiverNode getDerefHandleGetReceiverNode() { if (derefHandleGetReceiverNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create(LLVMMemory.getDerefHandleObjectMask())); + derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create()); } return derefHandleGetReceiverNode; } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMAbstractLoadNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMAbstractLoadNode.java index 2b757082c..d933f0631 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMAbstractLoadNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMAbstractLoadNode.java @@ -44,7 +44,7 @@ abstract class LLVMAbstractLoadNode extends LLVMLoadNode { protected LLVMDerefHandleGetReceiverNode getDerefHandleGetReceiverNode() { if (derefHandleGetReceiverNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create(LLVMMemory.getDerefHandleObjectMask())); + derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create()); } return derefHandleGetReceiverNode; } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMDerefHandleGetReceiverNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMDerefHandleGetReceiverNode.java index 307f592b4..4c87afcb6 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMDerefHandleGetReceiverNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/load/LLVMDerefHandleGetReceiverNode.java @@ -34,19 +34,15 @@ import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.llvm.runtime.LLVMContext; +import com.oracle.truffle.llvm.runtime.memory.LLVMNativeMemory; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; public class LLVMDerefHandleGetReceiverNode extends LLVMNode { - protected final long mask; @CompilationFinal private ContextReference context; - protected LLVMDerefHandleGetReceiverNode(long mask) { - this.mask = mask; - } - protected LLVMContext getContext() { if (context == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -56,14 +52,14 @@ protected LLVMContext getContext() { } public LLVMManagedPointer execute(LLVMNativePointer addr) { + long mask = LLVMNativeMemory.getDerefHandleObjectMask(); LLVMNativePointer objectBaseAddr = LLVMNativePointer.create(addr.asNative() & ~mask); TruffleObject receiver = getContext().getManagedObjectForHandle(objectBaseAddr); LLVMManagedPointer pointerToForeign = LLVMManagedPointer.create(receiver); return pointerToForeign.increment(addr.asNative() & mask); } - public static LLVMDerefHandleGetReceiverNode create(long bitmask) { - return new LLVMDerefHandleGetReceiverNode(bitmask); + public static LLVMDerefHandleGetReceiverNode create() { + return new LLVMDerefHandleGetReceiverNode(); } - } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/store/LLVMStoreNodeCommon.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/store/LLVMStoreNodeCommon.java index c757b2638..9ef8151ea 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/store/LLVMStoreNodeCommon.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/store/LLVMStoreNodeCommon.java @@ -58,7 +58,7 @@ public LLVMSourceLocation getSourceLocation() { protected LLVMDerefHandleGetReceiverNode getDerefHandleGetReceiverNode() { if (derefHandleGetReceiverNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create(LLVMMemory.getDerefHandleObjectMask())); + derefHandleGetReceiverNode = insert(LLVMDerefHandleGetReceiverNode.create()); } return derefHandleGetReceiverNode; } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMMemory.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMMemory.java index a8bff6a5e..6f6eb8948 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMMemory.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMMemory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. + * Copyright (c) 2018, Oracle and/or its affiliates. * * All rights reserved. * @@ -29,32 +29,15 @@ */ package com.oracle.truffle.llvm.runtime.memory; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.ADDRESS_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.DOUBLE_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.FLOAT_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I16_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I1_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I32_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I64_SIZE_IN_BYTES; -import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I8_SIZE_IN_BYTES; - -import java.lang.reflect.Field; import java.util.function.BinaryOperator; import java.util.function.IntBinaryOperator; import java.util.function.LongBinaryOperator; -import com.oracle.truffle.api.Assumption; -import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.ValueType; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.llvm.runtime.LLVMIVarBit; -import com.oracle.truffle.llvm.runtime.LLVMLanguage; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; -import com.oracle.truffle.llvm.runtime.vector.LLVMPointerVector; import com.oracle.truffle.llvm.runtime.vector.LLVMDoubleVector; import com.oracle.truffle.llvm.runtime.vector.LLVMFloatVector; import com.oracle.truffle.llvm.runtime.vector.LLVMFunctionVector; @@ -63,583 +46,198 @@ import com.oracle.truffle.llvm.runtime.vector.LLVMI32Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI64Vector; import com.oracle.truffle.llvm.runtime.vector.LLVMI8Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMPointerVector; -import sun.misc.Unsafe; +public abstract class LLVMMemory { -@SuppressWarnings("static-method") -public final class LLVMMemory { - /* must be a power of 2 */ - private static final long DEREF_HANDLE_OBJECT_SIZE = 1L << 20; - private static final long DEREF_HANDLE_OBJECT_MASK = (1L << 20) - 1L; + /** Use {@link com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode} instead. */ + @Deprecated + public abstract void memset(LLVMNativePointer address, long size, byte value); - private static final long DEREF_HANDLE_SPACE_START = 0x0FFFFFFFFFFFFFFFL & ~DEREF_HANDLE_OBJECT_MASK; - private static final long DEREF_HANDLE_SPACE_END = 0x0FFF800000000000L & ~DEREF_HANDLE_OBJECT_MASK; + /** Use {@link com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode} instead. */ + @Deprecated + public abstract void copyMemory(long sourceAddress, long targetAddress, long length); - private static final Unsafe unsafe = getUnsafe(); + public abstract void free(LLVMNativePointer address); - private final Object freeListLock = new Object(); - private FreeListNode freeList; + public abstract void free(long address); - private final Object derefSpaceTopLock = new Object(); - private long derefSpaceTop = DEREF_HANDLE_SPACE_START; + public abstract LLVMNativePointer allocateMemory(long size); - private final Assumption noDerefHandleAssumption = Truffle.getRuntime().createAssumption("no deref handle assumption"); + public abstract LLVMNativePointer reallocateMemory(LLVMNativePointer addr, long size); - private static final class FreeListNode { - protected FreeListNode(long address, FreeListNode next) { - this.address = address; - this.next = next; - } + /** + * Allocates {@code #OBJECT_SIZE} bytes in the Kernel space. + */ + public abstract LLVMNativePointer allocateDerefMemory(); - private final long address; - private final FreeListNode next; - } + public abstract boolean getI1(LLVMNativePointer addr); - private static Unsafe getUnsafe() { - CompilerAsserts.neverPartOfCompilation(); - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(null); - } catch (Exception e) { - throw new AssertionError(); - } - } + public abstract boolean getI1(long ptr); - private static final LLVMMemory INSTANCE = new LLVMMemory(); + public abstract byte getI8(LLVMNativePointer addr); - /** - * @deprecated "This method should not be called directly. Use - * {@link LLVMLanguage#getCapability(Class)} instead." - */ - @Deprecated - public static LLVMMemory getInstance() { - return INSTANCE; - } + public abstract byte getI8(long ptr); - private LLVMMemory() { - } + public abstract short getI16(LLVMNativePointer addr); - /** Use {@link com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode} instead. */ - @Deprecated - public void memset(LLVMNativePointer address, long size, byte value) { - try { - unsafe.setMemory(address.asNative(), size, value); - } catch (Throwable e) { - // this avoids unnecessary exception edges in the compiled code - CompilerDirectives.transferToInterpreter(); - throw e; - } - } + public abstract short getI16(long ptr); - /** Use {@link com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode} instead. */ - @Deprecated - public void copyMemory(long sourceAddress, long targetAddress, long length) { - unsafe.copyMemory(sourceAddress, targetAddress, length); - } + public abstract int getI32(LLVMNativePointer addr); - public void free(LLVMNativePointer address) { - free(address.asNative()); - } + public abstract int getI32(long ptr); - public void free(long address) { - if (address <= DEREF_HANDLE_SPACE_START && address > DEREF_HANDLE_SPACE_END) { - assert isAllocated(address) : "double-free of " + Long.toHexString(address); - synchronized (freeListLock) { - // We need to mask because we allow creating handles with an offset. - freeList = new FreeListNode(address & ~DEREF_HANDLE_OBJECT_MASK, freeList); - } - } else { - try { - unsafe.freeMemory(address); - } catch (Throwable e) { - // this avoids unnecessary exception edges in the compiled code - CompilerDirectives.transferToInterpreter(); - throw e; - } - } - } + public abstract LLVMIVarBit getIVarBit(LLVMNativePointer addr, int bitWidth); - public LLVMNativePointer allocateMemory(long size) { - try { - return LLVMNativePointer.create(unsafe.allocateMemory(size)); - } catch (Throwable e) { - // this avoids unnecessary exception edges in the compiled code - CompilerDirectives.transferToInterpreter(); - throw e; - } - } + public abstract long getI64(LLVMNativePointer addr); - public LLVMNativePointer reallocateMemory(LLVMNativePointer addr, long size) { - // a null pointer is a valid argument - try { - return LLVMNativePointer.create(unsafe.reallocateMemory(addr.asNative(), size)); - } catch (Throwable e) { - // this avoids unnecessary exception edges in the compiled code - CompilerDirectives.transferToInterpreter(); - throw e; - } - } + public abstract long getI64(long ptr); - /** - * Allocates {@code #OBJECT_SIZE} bytes in the Kernel space. - */ - public LLVMNativePointer allocateDerefMemory() { - noDerefHandleAssumption.invalidate(); - - // preferably consume from free list - synchronized (freeListLock) { - if (freeList != null) { - FreeListNode n = freeList; - freeList = n.next; - return LLVMNativePointer.create(n.address); - } - } + public abstract float getFloat(LLVMNativePointer addr); - synchronized (derefSpaceTopLock) { - LLVMNativePointer addr = LLVMNativePointer.create(derefSpaceTop); - assert derefSpaceTop > 0L; - derefSpaceTop -= DEREF_HANDLE_OBJECT_SIZE; - if (derefSpaceTop < DEREF_HANDLE_SPACE_END) { - CompilerDirectives.transferToInterpreter(); - throw new OutOfMemoryError(); - } - return addr; - } - } + public abstract float getFloat(long ptr); - public boolean getI1(LLVMNativePointer addr) { - return getI1(addr.asNative()); - } + public abstract double getDouble(LLVMNativePointer addr); - public boolean getI1(long ptr) { - assert ptr != 0; - return unsafe.getByte(ptr) != 0; - } + public abstract double getDouble(long ptr); - public byte getI8(LLVMNativePointer addr) { - return getI8(addr.asNative()); - } + public abstract LLVM80BitFloat get80BitFloat(LLVMNativePointer addr); - public byte getI8(long ptr) { - assert ptr != 0; - return unsafe.getByte(ptr); - } + public abstract LLVMNativePointer getPointer(LLVMNativePointer addr); - public short getI16(LLVMNativePointer addr) { - return getI16(addr.asNative()); - } + public abstract LLVMNativePointer getPointer(long ptr); - public short getI16(long ptr) { - assert ptr != 0; - return unsafe.getShort(ptr); - } + public abstract void putI1(LLVMNativePointer addr, boolean value); - public int getI32(LLVMNativePointer addr) { - return getI32(addr.asNative()); - } + public abstract void putI1(long ptr, boolean value); - public int getI32(long ptr) { - assert ptr != 0; - return unsafe.getInt(ptr); - } + public abstract void putI8(LLVMNativePointer addr, byte value); - public LLVMIVarBit getIVarBit(LLVMNativePointer addr, int bitWidth) { - if (bitWidth % Byte.SIZE != 0) { - CompilerDirectives.transferToInterpreter(); - throw new AssertionError(); - } - int bytes = bitWidth / Byte.SIZE; - byte[] loadedBytes = new byte[bytes]; - long currentAddressPtr = addr.asNative(); - for (int i = loadedBytes.length - 1; i >= 0; i--) { - loadedBytes[i] = getI8(currentAddressPtr); - currentAddressPtr += Byte.BYTES; - } - return LLVMIVarBit.create(bitWidth, loadedBytes, bitWidth, false); - } + public abstract void putI8(long ptr, byte value); - public long getI64(LLVMNativePointer addr) { - return getI64(addr.asNative()); - } + public abstract void putI16(LLVMNativePointer addr, short value); - public long getI64(long ptr) { - assert ptr != 0; - return unsafe.getLong(ptr); - } + public abstract void putI16(long ptr, short value); - public float getFloat(LLVMNativePointer addr) { - return getFloat(addr.asNative()); - } + public abstract void putI32(LLVMNativePointer addr, int value); - public float getFloat(long ptr) { - assert ptr != 0; - return unsafe.getFloat(ptr); - } + public abstract void putI32(long ptr, int value); - public double getDouble(LLVMNativePointer addr) { - return getDouble(addr.asNative()); - } + public abstract void putI64(LLVMNativePointer addr, long value); - public double getDouble(long ptr) { - assert ptr != 0; - return unsafe.getDouble(ptr); - } + public abstract void putI64(long ptr, long value); - public LLVM80BitFloat get80BitFloat(LLVMNativePointer addr) { - byte[] bytes = new byte[LLVM80BitFloat.BYTE_WIDTH]; - long currentPtr = addr.asNative(); - for (int i = 0; i < bytes.length; i++) { - bytes[i] = getI8(currentPtr); - currentPtr += Byte.BYTES; - } - return LLVM80BitFloat.fromBytes(bytes); - } + public abstract void putIVarBit(LLVMNativePointer addr, LLVMIVarBit value); - public LLVMNativePointer getPointer(LLVMNativePointer addr) { - return getPointer(addr.asNative()); - } + public abstract void putFloat(LLVMNativePointer addr, float value); - public LLVMNativePointer getPointer(long ptr) { - assert ptr != 0; - return LLVMNativePointer.create(unsafe.getAddress(ptr)); - } + public abstract void putFloat(long ptr, float value); - public void putI1(LLVMNativePointer addr, boolean value) { - putI1(addr.asNative(), value); - } + public abstract void putDouble(LLVMNativePointer addr, double value); - public void putI1(long ptr, boolean value) { - assert ptr != 0; - unsafe.putByte(ptr, (byte) (value ? 1 : 0)); - } + public abstract void putDouble(long ptr, double value); - public void putI8(LLVMNativePointer addr, byte value) { - putI8(addr.asNative(), value); - } + public abstract void put80BitFloat(LLVMNativePointer addr, LLVM80BitFloat value); - public void putI8(long ptr, byte value) { - assert ptr != 0; - unsafe.putByte(ptr, value); - } + public abstract void put80BitFloat(long ptr, LLVM80BitFloat value); - public void putI16(LLVMNativePointer addr, short value) { - putI16(addr.asNative(), value); - } + public abstract void putPointer(LLVMNativePointer addr, LLVMNativePointer value); - public void putI16(long ptr, short value) { - assert ptr != 0; - unsafe.putShort(ptr, value); - } + public abstract void putPointer(LLVMNativePointer addr, long ptrValue); - public void putI32(LLVMNativePointer addr, int value) { - putI32(addr.asNative(), value); - } + public abstract void putPointer(long ptr, LLVMNativePointer value); - public void putI32(long ptr, int value) { - assert ptr != 0; - unsafe.putInt(ptr, value); - } + public abstract void putPointer(long ptr, long ptrValue); - public void putI64(LLVMNativePointer addr, long value) { - putI64(addr.asNative(), value); - } + public abstract LLVMI32Vector getI32Vector(LLVMNativePointer address, int vectorLength); - public void putI64(long ptr, long value) { - assert ptr != 0; - unsafe.putLong(ptr, value); - } + public abstract LLVMI8Vector getI8Vector(LLVMNativePointer address, int vectorLength); - public void putIVarBit(LLVMNativePointer addr, LLVMIVarBit value) { - byte[] bytes = value.getBytes(); - long currentptr = addr.asNative(); - for (int i = bytes.length - 1; i >= 0; i--) { - putI8(currentptr, bytes[i]); - currentptr += Byte.BYTES; - } - } + public abstract LLVMI1Vector getI1Vector(LLVMNativePointer address, int vectorLength); - private void putByteArray(LLVMNativePointer addr, byte[] bytes) { - putByteArray(addr.asNative(), bytes); - } + public abstract LLVMI16Vector getI16Vector(LLVMNativePointer address, int vectorLength); - private void putByteArray(long ptr, byte[] bytes) { - long currentptr = ptr; - for (int i = 0; i < bytes.length; i++) { - putI8(currentptr, bytes[i]); - currentptr += Byte.BYTES; - } - } + public abstract LLVMI64Vector getI64Vector(LLVMNativePointer address, int vectorLength); - public void putFloat(LLVMNativePointer addr, float value) { - putFloat(addr.asNative(), value); - } + public abstract LLVMFloatVector getFloatVector(LLVMNativePointer address, int vectorLength); - public void putFloat(long ptr, float value) { - assert ptr != 0; - unsafe.putFloat(ptr, value); - } + public abstract LLVMDoubleVector getDoubleVector(LLVMNativePointer address, int vectorLength); - public void putDouble(LLVMNativePointer addr, double value) { - putDouble(addr.asNative(), value); - } + public abstract LLVMPointerVector getPointerVector(LLVMNativePointer address, int vectorLength); - public void putDouble(long ptr, double value) { - assert ptr != 0; - unsafe.putDouble(ptr, value); - } + public abstract LLVMFunctionVector getFunctionVector(LLVMNativePointer address, int vectorLength); - public void put80BitFloat(LLVMNativePointer addr, LLVM80BitFloat value) { - putByteArray(addr, value.getBytes()); - } + public abstract void putVector(LLVMNativePointer address, LLVMDoubleVector vector, int vectorLength); - public void put80BitFloat(long ptr, LLVM80BitFloat value) { - putByteArray(ptr, value.getBytes()); - } + public abstract void putVector(LLVMNativePointer address, LLVMFloatVector vector, int vectorLength); - public void putPointer(LLVMNativePointer addr, LLVMNativePointer value) { - putPointer(addr.asNative(), value); - } + public abstract void putVector(LLVMNativePointer address, LLVMI16Vector vector, int vectorLength); - public void putPointer(LLVMNativePointer addr, long ptrValue) { - putPointer(addr.asNative(), ptrValue); - } + public abstract void putVector(LLVMNativePointer address, LLVMI1Vector vector, int vectorLength); - public void putPointer(long ptr, LLVMNativePointer value) { - putPointer(ptr, value.asNative()); - } + public abstract void putVector(LLVMNativePointer address, LLVMI32Vector vector, int vectorLength); - public void putPointer(long ptr, long ptrValue) { - assert ptr != 0; - unsafe.putAddress(ptr, ptrValue); - } + public abstract void putVector(LLVMNativePointer address, LLVMI64Vector vector, int vectorLength); - @ExplodeLoop - public LLVMI32Vector getI32Vector(LLVMNativePointer address, int vectorLength) { - int[] vector = new int[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getI32(currentPtr); - currentPtr += I32_SIZE_IN_BYTES; - } - return LLVMI32Vector.create(vector); - } + public abstract void putVector(LLVMNativePointer address, LLVMI8Vector vector, int vectorLength); - @ExplodeLoop - public LLVMI8Vector getI8Vector(LLVMNativePointer address, int vectorLength) { - byte[] vector = new byte[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getI8(currentPtr); - currentPtr += I8_SIZE_IN_BYTES; - } - return LLVMI8Vector.create(vector); - } + public abstract void putVector(LLVMNativePointer address, LLVMPointerVector vector, int vectorLength); - @ExplodeLoop - public LLVMI1Vector getI1Vector(LLVMNativePointer address, int vectorLength) { - boolean[] vector = new boolean[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getI1(currentPtr); - currentPtr += I1_SIZE_IN_BYTES; - } - return LLVMI1Vector.create(vector); - } + public abstract void putVector(LLVMNativePointer address, LLVMFunctionVector vector, int vectorLength, LLVMToNativeNode toNative); - @ExplodeLoop - public LLVMI16Vector getI16Vector(LLVMNativePointer address, int vectorLength) { - short[] vector = new short[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getI16(currentPtr); - currentPtr += I16_SIZE_IN_BYTES; - } - return LLVMI16Vector.create(vector); - } + public abstract LLVMNativePointer allocateCString(String string); - @ExplodeLoop - public LLVMI64Vector getI64Vector(LLVMNativePointer address, int vectorLength) { - long[] vector = new long[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getI64(currentPtr); - currentPtr += I64_SIZE_IN_BYTES; - } - return LLVMI64Vector.create(vector); - } + public abstract void putFunctionPointer(LLVMNativePointer address, long functionIndex); - @ExplodeLoop - public LLVMFloatVector getFloatVector(LLVMNativePointer address, int vectorLength) { - float[] vector = new float[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getFloat(currentPtr); - currentPtr += FLOAT_SIZE_IN_BYTES; - } - return LLVMFloatVector.create(vector); - } + public abstract void putFunctionPointer(long ptr, long functionIndex); - @ExplodeLoop - public LLVMDoubleVector getDoubleVector(LLVMNativePointer address, int vectorLength) { - double[] vector = new double[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getDouble(currentPtr); - currentPtr += DOUBLE_SIZE_IN_BYTES; - } - return LLVMDoubleVector.create(vector); - } + public abstract long getFunctionPointer(LLVMNativePointer addr); - @ExplodeLoop - public LLVMPointerVector getPointerVector(LLVMNativePointer address, int vectorLength) { - LLVMNativePointer[] vector = new LLVMNativePointer[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getPointer(currentPtr); - currentPtr += ADDRESS_SIZE_IN_BYTES; - } - return LLVMPointerVector.create(vector); - } + public abstract CMPXCHGI32 compareAndSwapI32(LLVMNativePointer p, int comparisonValue, int newValue); - @ExplodeLoop - public LLVMFunctionVector getFunctionVector(LLVMNativePointer address, int vectorLength) { - long[] vector = new long[vectorLength]; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - vector[i] = getPointer(currentPtr).asNative(); - currentPtr += ADDRESS_SIZE_IN_BYTES; - } - return LLVMFunctionVector.create(vector); - } + public abstract CMPXCHGI64 compareAndSwapI64(LLVMNativePointer p, long comparisonValue, long newValue); - // watch out for casts such as I32* to I32Vector* when changing the way how vectors are - // implemented - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMDoubleVector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putDouble(currentPtr, vector.getValue(i)); - currentPtr += DOUBLE_SIZE_IN_BYTES; - } - } + public abstract CMPXCHGI8 compareAndSwapI8(LLVMNativePointer p, byte comparisonValue, byte newValue); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMFloatVector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putFloat(currentPtr, vector.getValue(i)); - currentPtr += FLOAT_SIZE_IN_BYTES; - } - } + public abstract CMPXCHGI16 compareAndSwapI16(LLVMNativePointer p, short comparisonValue, short newValue); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMI16Vector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putI16(currentPtr, vector.getValue(i)); - currentPtr += I16_SIZE_IN_BYTES; - } - } + public abstract long getAndSetI64(LLVMNativePointer address, long value); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMI1Vector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putI1(currentPtr, vector.getValue(i)); - currentPtr += I1_SIZE_IN_BYTES; - } - } + public abstract long getAndAddI64(LLVMNativePointer address, long value); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMI32Vector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putI32(currentPtr, vector.getValue(i)); - currentPtr += I32_SIZE_IN_BYTES; - } - } + public abstract long getAndSubI64(LLVMNativePointer address, long value); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMI64Vector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putI64(currentPtr, vector.getValue(i)); - currentPtr += I64_SIZE_IN_BYTES; - } - } + public abstract long getAndOpI64(LLVMNativePointer address, long value, LongBinaryOperator f); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMI8Vector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putI8(currentPtr, vector.getValue(i)); - currentPtr += I8_SIZE_IN_BYTES; - } - } + public abstract int getAndSetI32(LLVMNativePointer address, int value); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMPointerVector vector, int vectorLength) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putPointer(currentPtr, vector.getValue(i)); - currentPtr += ADDRESS_SIZE_IN_BYTES; - } - } + public abstract int getAndAddI32(LLVMNativePointer address, int value); - @ExplodeLoop - public void putVector(LLVMNativePointer address, LLVMFunctionVector vector, int vectorLength, LLVMToNativeNode toNative) { - assert vector.getLength() == vectorLength; - long currentPtr = address.asNative(); - for (int i = 0; i < vectorLength; i++) { - putPointer(currentPtr, toNative.executeWithTarget(vector.getValue(i))); - currentPtr += ADDRESS_SIZE_IN_BYTES; - } - } + public abstract int getAndSubI32(LLVMNativePointer address, int value); - public LLVMNativePointer allocateCString(String string) { - LLVMNativePointer basePointer = allocateMemory(string.length() + 1); - long currentPointer = basePointer.asNative(); - for (int i = 0; i < string.length(); i++) { - byte c = (byte) string.charAt(i); - putI8(currentPointer, c); - currentPointer++; - } - putI8(currentPointer, (byte) 0); - return basePointer; - } + public abstract int getAndOpI32(LLVMNativePointer address, int value, IntBinaryOperator f); - public void putFunctionPointer(LLVMNativePointer address, long functionIndex) { - putI64(address, functionIndex); - } + public abstract short getAndOpI16(LLVMNativePointer address, short value, BinaryOperator f); - public void putFunctionPointer(long ptr, long functionIndex) { - putI64(ptr, functionIndex); - } + public abstract byte getAndOpI8(LLVMNativePointer address, byte value, BinaryOperator f); - public long getFunctionPointer(LLVMNativePointer addr) { - return getI64(addr); - } + public abstract boolean getAndOpI1(LLVMNativePointer address, boolean value, BinaryOperator f); + + public abstract void fullFence(); + + public abstract boolean isDerefMemory(LLVMNativePointer addr); @ValueType - public static final class CMPXCHGI32 { - private final int value; + public static final class CMPXCHGI8 { + private final byte value; private final boolean swap; - private CMPXCHGI32(int value, boolean swap) { + public CMPXCHGI8(byte value, boolean swap) { this.value = value; this.swap = swap; } - public int getValue() { + public byte getValue() { return value; } @@ -648,33 +246,17 @@ public boolean isSwap() { } } - public CMPXCHGI32 compareAndSwapI32(LLVMNativePointer p, int comparisonValue, int newValue) { - while (true) { - boolean b = unsafe.compareAndSwapInt(null, p.asNative(), comparisonValue, newValue); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b)) { - return new CMPXCHGI32(comparisonValue, b); - } else { - int t = unsafe.getIntVolatile(null, p.asNative()); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, t == comparisonValue)) { - continue; - } else { - return new CMPXCHGI32(t, b); - } - } - } - } - @ValueType - public static final class CMPXCHGI64 { - private final long value; + public static final class CMPXCHGI16 { + private final short value; private final boolean swap; - private CMPXCHGI64(long value, boolean swap) { + public CMPXCHGI16(short value, boolean swap) { this.value = value; this.swap = swap; } - public long getValue() { + public short getValue() { return value; } @@ -683,33 +265,17 @@ public boolean isSwap() { } } - public CMPXCHGI64 compareAndSwapI64(LLVMNativePointer p, long comparisonValue, long newValue) { - while (true) { - boolean b = unsafe.compareAndSwapLong(null, p.asNative(), comparisonValue, newValue); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b)) { - return new CMPXCHGI64(comparisonValue, b); - } else { - long t = unsafe.getLongVolatile(null, p.asNative()); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, t == comparisonValue)) { - continue; - } else { - return new CMPXCHGI64(t, b); - } - } - } - } - @ValueType - public static final class CMPXCHGI8 { - private final byte value; + public static final class CMPXCHGI32 { + private final int value; private final boolean swap; - private CMPXCHGI8(byte value, boolean swap) { + public CMPXCHGI32(int value, boolean swap) { this.value = value; this.swap = swap; } - public byte getValue() { + public int getValue() { return value; } @@ -718,55 +284,17 @@ public boolean isSwap() { } } - private static long alignToI32(long address) { - long mask = 3; - return (address & ~mask); - } - - private static int getI8Index(long address) { - long mask = 3; - return (int) (address & mask); - } - - private static byte getI8At(int value, int index) { - return (byte) ((value >> (8 * index)) & 0xff); - } - - private static int replaceI8(int index, int value, byte replaceByte) { - return (value & ~(0xFF << (index * 8))) | ((replaceByte & 0xFF) << (index * 8)); - } - - public CMPXCHGI8 compareAndSwapI8(LLVMNativePointer p, byte comparisonValue, byte newValue) { - int byteIndex = getI8Index(p.asNative()); - long address = alignToI32(p.asNative()); - while (true) { - int t = unsafe.getIntVolatile(null, address); - byte b = getI8At(t, byteIndex); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b != comparisonValue)) { - return new CMPXCHGI8(b, false); - } else { - int newVal = replaceI8(byteIndex, t, newValue); - boolean c = unsafe.compareAndSwapInt(null, address, t, newVal); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, c)) { - return new CMPXCHGI8(comparisonValue, true); - } else { - continue; - } - } - } - } - @ValueType - public static final class CMPXCHGI16 { - private final short value; + public static final class CMPXCHGI64 { + private final long value; private final boolean swap; - public CMPXCHGI16(short value, boolean swap) { + public CMPXCHGI64(long value, boolean swap) { this.value = value; this.swap = swap; } - public short getValue() { + public long getValue() { return value; } @@ -774,147 +302,4 @@ public boolean isSwap() { return swap; } } - - private static int getI16Index(long address) { - long mask = 3; - return (int) (address & mask) >> 1; - } - - private static short getI16At(int value, int index) { - return (short) ((value >> (16 * index)) & 0xFFFF); - } - - private static int replaceI16(int index, int value, short replace) { - return (value & ~(0xFFFF << (index * 16))) | ((replace & 0xFFFF) << (index * 16)); - } - - public CMPXCHGI16 compareAndSwapI16(LLVMNativePointer p, short comparisonValue, short newValue) { - int idx = getI16Index(p.asNative()); - long address = alignToI32(p.asNative()); - while (true) { - int t = unsafe.getIntVolatile(null, address); - short b = getI16At(t, idx); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b != comparisonValue)) { - return new CMPXCHGI16(b, false); - } else { - int newVal = replaceI16(idx, t, newValue); - boolean c = unsafe.compareAndSwapInt(null, address, t, newVal); - if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, c)) { - return new CMPXCHGI16(comparisonValue, true); - } else { - continue; - } - } - } - } - - public long getAndSetI64(LLVMNativePointer address, long value) { - return unsafe.getAndSetLong(null, address.asNative(), value); - } - - public long getAndAddI64(LLVMNativePointer address, long value) { - return unsafe.getAndAddLong(null, address.asNative(), value); - } - - public long getAndSubI64(LLVMNativePointer address, long value) { - return unsafe.getAndAddLong(null, address.asNative(), -value); - } - - public long getAndOpI64(LLVMNativePointer address, long value, LongBinaryOperator f) { - long addr = address.asNative(); - long old; - long nevv; - do { - old = getI64(address); - nevv = f.applyAsLong(old, value); - } while (!unsafe.compareAndSwapLong(null, addr, old, nevv)); - return old; - } - - public int getAndSetI32(LLVMNativePointer address, int value) { - return unsafe.getAndSetInt(null, address.asNative(), value); - } - - public int getAndAddI32(LLVMNativePointer address, int value) { - return unsafe.getAndAddInt(null, address.asNative(), value); - } - - public int getAndSubI32(LLVMNativePointer address, int value) { - return unsafe.getAndAddInt(null, address.asNative(), -value); - } - - public int getAndOpI32(LLVMNativePointer address, int value, IntBinaryOperator f) { - long addr = address.asNative(); - int old; - int nevv; - do { - old = getI32(address); - nevv = f.applyAsInt(old, value); - } while (!unsafe.compareAndSwapInt(null, addr, old, nevv)); - return old; - } - - public short getAndOpI16(LLVMNativePointer address, short value, BinaryOperator f) { - short old; - short nevv; - do { - old = getI16(address); - nevv = f.apply(old, value); - } while (!compareAndSwapI16(address, old, nevv).swap); - return old; - } - - public byte getAndOpI8(LLVMNativePointer address, byte value, BinaryOperator f) { - byte old; - byte nevv; - do { - old = getI8(address); - nevv = f.apply(old, value); - } while (!compareAndSwapI8(address, old, nevv).swap); - return old; - } - - public boolean getAndOpI1(LLVMNativePointer address, boolean value, BinaryOperator f) { - byte old; - boolean nevv; - do { - old = getI8(address); - nevv = f.apply(old != 0, value); - } while (!compareAndSwapI8(address, old, (byte) (nevv ? 1 : 0)).swap); - return old != 0; - } - - public void fullFence() { - unsafe.fullFence(); - } - - public Assumption getNoDerefHandleAssumption() { - return noDerefHandleAssumption; - } - - public boolean isDerefMemory(LLVMNativePointer addr) { - return !noDerefHandleAssumption.isValid() && addr.asNative() > DEREF_HANDLE_SPACE_END; - } - - public static long getDerefHandleObjectMask() { - return DEREF_HANDLE_OBJECT_SIZE - 1; - } - - private boolean isAllocated(long address) { - synchronized (derefSpaceTopLock) { - if (address <= derefSpaceTop) { - return false; - } - } - - synchronized (freeListLock) { - for (FreeListNode cur = freeList; cur != null; cur = cur.next) { - if (cur.address == address) { - return false; - } - } - } - return true; - } - } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMNativeMemory.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMNativeMemory.java new file mode 100644 index 000000000..4ffbc25dc --- /dev/null +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/memory/LLVMNativeMemory.java @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.oracle.truffle.llvm.runtime.memory; + +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.ADDRESS_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.DOUBLE_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.FLOAT_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I16_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I1_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I32_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I64_SIZE_IN_BYTES; +import static com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode.I8_SIZE_IN_BYTES; + +import java.lang.reflect.Field; +import java.util.function.BinaryOperator; +import java.util.function.IntBinaryOperator; +import java.util.function.LongBinaryOperator; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.llvm.runtime.LLVMIVarBit; +import com.oracle.truffle.llvm.runtime.LLVMLanguage; +import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; +import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; +import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; +import com.oracle.truffle.llvm.runtime.vector.LLVMDoubleVector; +import com.oracle.truffle.llvm.runtime.vector.LLVMFloatVector; +import com.oracle.truffle.llvm.runtime.vector.LLVMFunctionVector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI16Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI1Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI32Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI64Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMI8Vector; +import com.oracle.truffle.llvm.runtime.vector.LLVMPointerVector; + +import sun.misc.Unsafe; + +public final class LLVMNativeMemory extends LLVMMemory { + /* must be a power of 2 */ + private static final long DEREF_HANDLE_OBJECT_SIZE = 1L << 20; + private static final long DEREF_HANDLE_OBJECT_MASK = (1L << 20) - 1L; + + private static final long DEREF_HANDLE_SPACE_START = 0x0FFFFFFFFFFFFFFFL & ~DEREF_HANDLE_OBJECT_MASK; + private static final long DEREF_HANDLE_SPACE_END = 0x0FFF800000000000L & ~DEREF_HANDLE_OBJECT_MASK; + + private static final Unsafe unsafe = getUnsafe(); + + private final Object freeListLock = new Object(); + private FreeListNode freeList; + + private final Object derefSpaceTopLock = new Object(); + private long derefSpaceTop = DEREF_HANDLE_SPACE_START; + + private final Assumption noDerefHandleAssumption = Truffle.getRuntime().createAssumption("no deref handle assumption"); + + private static final class FreeListNode { + protected FreeListNode(long address, FreeListNode next) { + this.address = address; + this.next = next; + } + + private final long address; + private final FreeListNode next; + } + + private static Unsafe getUnsafe() { + CompilerAsserts.neverPartOfCompilation(); + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(null); + } catch (Exception e) { + throw new AssertionError(); + } + } + + private static final LLVMNativeMemory INSTANCE = new LLVMNativeMemory(); + + /** + * @deprecated "This method should not be called directly. Use + * {@link LLVMLanguage#getCapability(Class)} instead." + */ + @Deprecated + public static LLVMNativeMemory getInstance() { + return INSTANCE; + } + + private LLVMNativeMemory() { + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public void memset(LLVMNativePointer address, long size, byte value) { + try { + unsafe.setMemory(address.asNative(), size, value); + } catch (Throwable e) { + // this avoids unnecessary exception edges in the compiled code + CompilerDirectives.transferToInterpreter(); + throw e; + } + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public void copyMemory(long sourceAddress, long targetAddress, long length) { + unsafe.copyMemory(sourceAddress, targetAddress, length); + } + + @Override + public void free(LLVMNativePointer address) { + free(address.asNative()); + } + + @Override + public void free(long address) { + if (address <= DEREF_HANDLE_SPACE_START && address > DEREF_HANDLE_SPACE_END) { + assert isAllocated(address) : "double-free of " + Long.toHexString(address); + synchronized (freeListLock) { + // We need to mask because we allow creating handles with an offset. + freeList = new FreeListNode(address & ~DEREF_HANDLE_OBJECT_MASK, freeList); + } + } else { + try { + unsafe.freeMemory(address); + } catch (Throwable e) { + // this avoids unnecessary exception edges in the compiled code + CompilerDirectives.transferToInterpreter(); + throw e; + } + } + } + + @Override + public LLVMNativePointer allocateMemory(long size) { + try { + return LLVMNativePointer.create(unsafe.allocateMemory(size)); + } catch (Throwable e) { + // this avoids unnecessary exception edges in the compiled code + CompilerDirectives.transferToInterpreter(); + throw e; + } + } + + @Override + public LLVMNativePointer reallocateMemory(LLVMNativePointer addr, long size) { + // a null pointer is a valid argument + try { + return LLVMNativePointer.create(unsafe.reallocateMemory(addr.asNative(), size)); + } catch (Throwable e) { + // this avoids unnecessary exception edges in the compiled code + CompilerDirectives.transferToInterpreter(); + throw e; + } + } + + /** + * Allocates {@code #OBJECT_SIZE} bytes in the Kernel space. + */ + @Override + public LLVMNativePointer allocateDerefMemory() { + noDerefHandleAssumption.invalidate(); + + // preferably consume from free list + synchronized (freeListLock) { + if (freeList != null) { + FreeListNode n = freeList; + freeList = n.next; + return LLVMNativePointer.create(n.address); + } + } + + synchronized (derefSpaceTopLock) { + LLVMNativePointer addr = LLVMNativePointer.create(derefSpaceTop); + assert derefSpaceTop > 0L; + derefSpaceTop -= DEREF_HANDLE_OBJECT_SIZE; + if (derefSpaceTop < DEREF_HANDLE_SPACE_END) { + CompilerDirectives.transferToInterpreter(); + throw new OutOfMemoryError(); + } + return addr; + } + } + + @Override + public boolean getI1(LLVMNativePointer addr) { + return getI1(addr.asNative()); + } + + @Override + public boolean getI1(long ptr) { + assert ptr != 0; + return unsafe.getByte(ptr) != 0; + } + + @Override + public byte getI8(LLVMNativePointer addr) { + return getI8(addr.asNative()); + } + + @Override + public byte getI8(long ptr) { + assert ptr != 0; + return unsafe.getByte(ptr); + } + + @Override + public short getI16(LLVMNativePointer addr) { + return getI16(addr.asNative()); + } + + @Override + public short getI16(long ptr) { + assert ptr != 0; + return unsafe.getShort(ptr); + } + + @Override + public int getI32(LLVMNativePointer addr) { + return getI32(addr.asNative()); + } + + @Override + public int getI32(long ptr) { + assert ptr != 0; + return unsafe.getInt(ptr); + } + + @Override + public LLVMIVarBit getIVarBit(LLVMNativePointer addr, int bitWidth) { + if (bitWidth % Byte.SIZE != 0) { + CompilerDirectives.transferToInterpreter(); + throw new AssertionError(); + } + int bytes = bitWidth / Byte.SIZE; + byte[] loadedBytes = new byte[bytes]; + long currentAddressPtr = addr.asNative(); + for (int i = loadedBytes.length - 1; i >= 0; i--) { + loadedBytes[i] = getI8(currentAddressPtr); + currentAddressPtr += Byte.BYTES; + } + return LLVMIVarBit.create(bitWidth, loadedBytes, bitWidth, false); + } + + @Override + public long getI64(LLVMNativePointer addr) { + return getI64(addr.asNative()); + } + + @Override + public long getI64(long ptr) { + assert ptr != 0; + return unsafe.getLong(ptr); + } + + @Override + public float getFloat(LLVMNativePointer addr) { + return getFloat(addr.asNative()); + } + + @Override + public float getFloat(long ptr) { + assert ptr != 0; + return unsafe.getFloat(ptr); + } + + @Override + public double getDouble(LLVMNativePointer addr) { + return getDouble(addr.asNative()); + } + + @Override + public double getDouble(long ptr) { + assert ptr != 0; + return unsafe.getDouble(ptr); + } + + @Override + public LLVM80BitFloat get80BitFloat(LLVMNativePointer addr) { + byte[] bytes = new byte[LLVM80BitFloat.BYTE_WIDTH]; + long currentPtr = addr.asNative(); + for (int i = 0; i < bytes.length; i++) { + bytes[i] = getI8(currentPtr); + currentPtr += Byte.BYTES; + } + return LLVM80BitFloat.fromBytes(bytes); + } + + @Override + public LLVMNativePointer getPointer(LLVMNativePointer addr) { + return getPointer(addr.asNative()); + } + + @Override + public LLVMNativePointer getPointer(long ptr) { + assert ptr != 0; + return LLVMNativePointer.create(unsafe.getAddress(ptr)); + } + + @Override + public void putI1(LLVMNativePointer addr, boolean value) { + putI1(addr.asNative(), value); + } + + @Override + public void putI1(long ptr, boolean value) { + assert ptr != 0; + unsafe.putByte(ptr, (byte) (value ? 1 : 0)); + } + + @Override + public void putI8(LLVMNativePointer addr, byte value) { + putI8(addr.asNative(), value); + } + + @Override + public void putI8(long ptr, byte value) { + assert ptr != 0; + unsafe.putByte(ptr, value); + } + + @Override + public void putI16(LLVMNativePointer addr, short value) { + putI16(addr.asNative(), value); + } + + @Override + public void putI16(long ptr, short value) { + assert ptr != 0; + unsafe.putShort(ptr, value); + } + + @Override + public void putI32(LLVMNativePointer addr, int value) { + putI32(addr.asNative(), value); + } + + @Override + public void putI32(long ptr, int value) { + assert ptr != 0; + unsafe.putInt(ptr, value); + } + + @Override + public void putI64(LLVMNativePointer addr, long value) { + putI64(addr.asNative(), value); + } + + @Override + public void putI64(long ptr, long value) { + assert ptr != 0; + unsafe.putLong(ptr, value); + } + + @Override + public void putIVarBit(LLVMNativePointer addr, LLVMIVarBit value) { + byte[] bytes = value.getBytes(); + long currentptr = addr.asNative(); + for (int i = bytes.length - 1; i >= 0; i--) { + putI8(currentptr, bytes[i]); + currentptr += Byte.BYTES; + } + } + + private void putByteArray(LLVMNativePointer addr, byte[] bytes) { + putByteArray(addr.asNative(), bytes); + } + + private void putByteArray(long ptr, byte[] bytes) { + long currentptr = ptr; + for (int i = 0; i < bytes.length; i++) { + putI8(currentptr, bytes[i]); + currentptr += Byte.BYTES; + } + } + + @Override + public void putFloat(LLVMNativePointer addr, float value) { + putFloat(addr.asNative(), value); + } + + @Override + public void putFloat(long ptr, float value) { + assert ptr != 0; + unsafe.putFloat(ptr, value); + } + + @Override + public void putDouble(LLVMNativePointer addr, double value) { + putDouble(addr.asNative(), value); + } + + @Override + public void putDouble(long ptr, double value) { + assert ptr != 0; + unsafe.putDouble(ptr, value); + } + + @Override + public void put80BitFloat(LLVMNativePointer addr, LLVM80BitFloat value) { + putByteArray(addr, value.getBytes()); + } + + @Override + public void put80BitFloat(long ptr, LLVM80BitFloat value) { + putByteArray(ptr, value.getBytes()); + } + + @Override + public void putPointer(LLVMNativePointer addr, LLVMNativePointer value) { + putPointer(addr.asNative(), value); + } + + @Override + public void putPointer(LLVMNativePointer addr, long ptrValue) { + putPointer(addr.asNative(), ptrValue); + } + + @Override + public void putPointer(long ptr, LLVMNativePointer value) { + putPointer(ptr, value.asNative()); + } + + @Override + public void putPointer(long ptr, long ptrValue) { + assert ptr != 0; + unsafe.putAddress(ptr, ptrValue); + } + + @Override + @ExplodeLoop + public LLVMI32Vector getI32Vector(LLVMNativePointer address, int vectorLength) { + int[] vector = new int[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getI32(currentPtr); + currentPtr += I32_SIZE_IN_BYTES; + } + return LLVMI32Vector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMI8Vector getI8Vector(LLVMNativePointer address, int vectorLength) { + byte[] vector = new byte[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getI8(currentPtr); + currentPtr += I8_SIZE_IN_BYTES; + } + return LLVMI8Vector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMI1Vector getI1Vector(LLVMNativePointer address, int vectorLength) { + boolean[] vector = new boolean[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getI1(currentPtr); + currentPtr += I1_SIZE_IN_BYTES; + } + return LLVMI1Vector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMI16Vector getI16Vector(LLVMNativePointer address, int vectorLength) { + short[] vector = new short[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getI16(currentPtr); + currentPtr += I16_SIZE_IN_BYTES; + } + return LLVMI16Vector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMI64Vector getI64Vector(LLVMNativePointer address, int vectorLength) { + long[] vector = new long[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getI64(currentPtr); + currentPtr += I64_SIZE_IN_BYTES; + } + return LLVMI64Vector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMFloatVector getFloatVector(LLVMNativePointer address, int vectorLength) { + float[] vector = new float[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getFloat(currentPtr); + currentPtr += FLOAT_SIZE_IN_BYTES; + } + return LLVMFloatVector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMDoubleVector getDoubleVector(LLVMNativePointer address, int vectorLength) { + double[] vector = new double[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getDouble(currentPtr); + currentPtr += DOUBLE_SIZE_IN_BYTES; + } + return LLVMDoubleVector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMPointerVector getPointerVector(LLVMNativePointer address, int vectorLength) { + LLVMNativePointer[] vector = new LLVMNativePointer[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getPointer(currentPtr); + currentPtr += ADDRESS_SIZE_IN_BYTES; + } + return LLVMPointerVector.create(vector); + } + + @Override + @ExplodeLoop + public LLVMFunctionVector getFunctionVector(LLVMNativePointer address, int vectorLength) { + long[] vector = new long[vectorLength]; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + vector[i] = getPointer(currentPtr).asNative(); + currentPtr += ADDRESS_SIZE_IN_BYTES; + } + return LLVMFunctionVector.create(vector); + } + + // watch out for casts such as I32* to I32Vector* when changing the way how vectors are + // implemented + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMDoubleVector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putDouble(currentPtr, vector.getValue(i)); + currentPtr += DOUBLE_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMFloatVector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putFloat(currentPtr, vector.getValue(i)); + currentPtr += FLOAT_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMI16Vector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putI16(currentPtr, vector.getValue(i)); + currentPtr += I16_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMI1Vector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putI1(currentPtr, vector.getValue(i)); + currentPtr += I1_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMI32Vector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putI32(currentPtr, vector.getValue(i)); + currentPtr += I32_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMI64Vector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putI64(currentPtr, vector.getValue(i)); + currentPtr += I64_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMI8Vector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putI8(currentPtr, vector.getValue(i)); + currentPtr += I8_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMPointerVector vector, int vectorLength) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putPointer(currentPtr, vector.getValue(i)); + currentPtr += ADDRESS_SIZE_IN_BYTES; + } + } + + @Override + @ExplodeLoop + public void putVector(LLVMNativePointer address, LLVMFunctionVector vector, int vectorLength, LLVMToNativeNode toNative) { + assert vector.getLength() == vectorLength; + long currentPtr = address.asNative(); + for (int i = 0; i < vectorLength; i++) { + putPointer(currentPtr, toNative.executeWithTarget(vector.getValue(i))); + currentPtr += ADDRESS_SIZE_IN_BYTES; + } + } + + @Override + public LLVMNativePointer allocateCString(String string) { + LLVMNativePointer basePointer = allocateMemory(string.length() + 1); + long currentPointer = basePointer.asNative(); + for (int i = 0; i < string.length(); i++) { + byte c = (byte) string.charAt(i); + putI8(currentPointer, c); + currentPointer++; + } + putI8(currentPointer, (byte) 0); + return basePointer; + } + + @Override + public void putFunctionPointer(LLVMNativePointer address, long functionIndex) { + putI64(address, functionIndex); + } + + @Override + public void putFunctionPointer(long ptr, long functionIndex) { + putI64(ptr, functionIndex); + } + + @Override + public long getFunctionPointer(LLVMNativePointer addr) { + return getI64(addr); + } + + @Override + public CMPXCHGI32 compareAndSwapI32(LLVMNativePointer p, int comparisonValue, int newValue) { + while (true) { + boolean b = unsafe.compareAndSwapInt(null, p.asNative(), comparisonValue, newValue); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b)) { + return new CMPXCHGI32(comparisonValue, b); + } else { + int t = unsafe.getIntVolatile(null, p.asNative()); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, t == comparisonValue)) { + continue; + } else { + return new CMPXCHGI32(t, b); + } + } + } + } + + @Override + public CMPXCHGI64 compareAndSwapI64(LLVMNativePointer p, long comparisonValue, long newValue) { + while (true) { + boolean b = unsafe.compareAndSwapLong(null, p.asNative(), comparisonValue, newValue); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b)) { + return new CMPXCHGI64(comparisonValue, b); + } else { + long t = unsafe.getLongVolatile(null, p.asNative()); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, t == comparisonValue)) { + continue; + } else { + return new CMPXCHGI64(t, b); + } + } + } + } + + private static long alignToI32(long address) { + long mask = 3; + return (address & ~mask); + } + + private static int getI8Index(long address) { + long mask = 3; + return (int) (address & mask); + } + + private static byte getI8At(int value, int index) { + return (byte) ((value >> (8 * index)) & 0xff); + } + + private static int replaceI8(int index, int value, byte replaceByte) { + return (value & ~(0xFF << (index * 8))) | ((replaceByte & 0xFF) << (index * 8)); + } + + @Override + public CMPXCHGI8 compareAndSwapI8(LLVMNativePointer p, byte comparisonValue, byte newValue) { + int byteIndex = getI8Index(p.asNative()); + long address = alignToI32(p.asNative()); + while (true) { + int t = unsafe.getIntVolatile(null, address); + byte b = getI8At(t, byteIndex); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b != comparisonValue)) { + return new CMPXCHGI8(b, false); + } else { + int newVal = replaceI8(byteIndex, t, newValue); + boolean c = unsafe.compareAndSwapInt(null, address, t, newVal); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, c)) { + return new CMPXCHGI8(comparisonValue, true); + } else { + continue; + } + } + } + } + + private static int getI16Index(long address) { + long mask = 3; + return (int) (address & mask) >> 1; + } + + private static short getI16At(int value, int index) { + return (short) ((value >> (16 * index)) & 0xFFFF); + } + + private static int replaceI16(int index, int value, short replace) { + return (value & ~(0xFFFF << (index * 16))) | ((replace & 0xFFFF) << (index * 16)); + } + + @Override + public CMPXCHGI16 compareAndSwapI16(LLVMNativePointer p, short comparisonValue, short newValue) { + int idx = getI16Index(p.asNative()); + long address = alignToI32(p.asNative()); + while (true) { + int t = unsafe.getIntVolatile(null, address); + short b = getI16At(t, idx); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, b != comparisonValue)) { + return new CMPXCHGI16(b, false); + } else { + int newVal = replaceI16(idx, t, newValue); + boolean c = unsafe.compareAndSwapInt(null, address, t, newVal); + if (CompilerDirectives.injectBranchProbability(CompilerDirectives.LIKELY_PROBABILITY, c)) { + return new CMPXCHGI16(comparisonValue, true); + } else { + continue; + } + } + } + } + + @Override + public long getAndSetI64(LLVMNativePointer address, long value) { + return unsafe.getAndSetLong(null, address.asNative(), value); + } + + @Override + public long getAndAddI64(LLVMNativePointer address, long value) { + return unsafe.getAndAddLong(null, address.asNative(), value); + } + + @Override + public long getAndSubI64(LLVMNativePointer address, long value) { + return unsafe.getAndAddLong(null, address.asNative(), -value); + } + + @Override + public long getAndOpI64(LLVMNativePointer address, long value, LongBinaryOperator f) { + long addr = address.asNative(); + long old; + long nevv; + do { + old = getI64(address); + nevv = f.applyAsLong(old, value); + } while (!unsafe.compareAndSwapLong(null, addr, old, nevv)); + return old; + } + + @Override + public int getAndSetI32(LLVMNativePointer address, int value) { + return unsafe.getAndSetInt(null, address.asNative(), value); + } + + @Override + public int getAndAddI32(LLVMNativePointer address, int value) { + return unsafe.getAndAddInt(null, address.asNative(), value); + } + + @Override + public int getAndSubI32(LLVMNativePointer address, int value) { + return unsafe.getAndAddInt(null, address.asNative(), -value); + } + + @Override + public int getAndOpI32(LLVMNativePointer address, int value, IntBinaryOperator f) { + long addr = address.asNative(); + int old; + int nevv; + do { + old = getI32(address); + nevv = f.applyAsInt(old, value); + } while (!unsafe.compareAndSwapInt(null, addr, old, nevv)); + return old; + } + + @Override + public short getAndOpI16(LLVMNativePointer address, short value, BinaryOperator f) { + short old; + short nevv; + do { + old = getI16(address); + nevv = f.apply(old, value); + } while (!compareAndSwapI16(address, old, nevv).isSwap()); + return old; + } + + @Override + public byte getAndOpI8(LLVMNativePointer address, byte value, BinaryOperator f) { + byte old; + byte nevv; + do { + old = getI8(address); + nevv = f.apply(old, value); + } while (!compareAndSwapI8(address, old, nevv).isSwap()); + return old; + } + + @Override + public boolean getAndOpI1(LLVMNativePointer address, boolean value, BinaryOperator f) { + byte old; + boolean nevv; + do { + old = getI8(address); + nevv = f.apply(old != 0, value); + } while (!compareAndSwapI8(address, old, (byte) (nevv ? 1 : 0)).isSwap()); + return old != 0; + } + + @Override + public void fullFence() { + unsafe.fullFence(); + } + + @Override + public boolean isDerefMemory(LLVMNativePointer addr) { + return !noDerefHandleAssumption.isValid() && addr.asNative() > DEREF_HANDLE_SPACE_END; + } + + public static long getDerefHandleObjectMask() { + return DEREF_HANDLE_OBJECT_SIZE - 1; + } + + private boolean isAllocated(long address) { + synchronized (derefSpaceTopLock) { + if (address <= derefSpaceTop) { + return false; + } + } + + synchronized (freeListLock) { + for (FreeListNode cur = freeList; cur != null; cur = cur.next) { + if (cur.address == address) { + return false; + } + } + } + return true; + } + +} diff --git a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java index e3f7e78aa..4a731125d 100644 --- a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java +++ b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java @@ -43,6 +43,7 @@ import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.NFIContextExtension; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; +import com.oracle.truffle.llvm.runtime.memory.LLVMNativeMemory; import com.oracle.truffle.llvm.runtime.memory.UnsafeArrayAccess; import com.oracle.truffle.llvm.runtime.options.SulongEngineOption; @@ -78,7 +79,7 @@ public List createContextExtensions(com.oracle.truffle.api.Tru @SuppressWarnings("deprecation") public E getCapability(Class type) { if (type.equals(LLVMMemory.class)) { - return type.cast(LLVMMemory.getInstance()); + return type.cast(LLVMNativeMemory.getInstance()); } else if (type.equals(UnsafeArrayAccess.class)) { return type.cast(UnsafeArrayAccess.getInstance()); } From f0be0e5700d115f3e6215a4ff3db832e1f2fc8f5 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 11 Jul 2018 14:59:17 +0200 Subject: [PATCH 05/12] Better C++ exception handling. --- .../LLVMAMD64SyscallClockGetTimeNode.java | 50 ++++---- .../llvm/nodes/func/LLVMLandingpadNode.java | 121 +++++++++--------- .../nodes/func/LLVMRaiseExceptionNode.java | 9 +- .../func/LLVMTypeIdForExceptionNode.java | 21 ++- .../literal/LLVMPointerArrayLiteralNode.java | 6 +- .../llvm/nodes/op/LLVMArithmeticNode.java | 6 +- .../llvm/nodes/op/LLVMPointerCompareNode.java | 2 +- .../llvm/nodes/op/ToComparableValue.java | 14 +- .../parser/factories/BasicNodeFactory.java | 5 +- .../runtime/except/LLVMUserException.java | 9 +- .../runtime/nodes/api/LLVMExpressionNode.java | 4 + 11 files changed, 136 insertions(+), 111 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/asm/syscall/LLVMAMD64SyscallClockGetTimeNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/asm/syscall/LLVMAMD64SyscallClockGetTimeNode.java index 8a18f5ebb..2f92e0741 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/asm/syscall/LLVMAMD64SyscallClockGetTimeNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/asm/syscall/LLVMAMD64SyscallClockGetTimeNode.java @@ -29,57 +29,51 @@ */ package com.oracle.truffle.llvm.nodes.asm.syscall; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.Cached; +import static com.oracle.truffle.llvm.nodes.asm.syscall.LLVMAMD64Time.CLOCK_MONOTONIC; +import static com.oracle.truffle.llvm.nodes.asm.syscall.LLVMAMD64Time.CLOCK_REALTIME; + import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMI64StoreNode; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMI64StoreNodeGen; import com.oracle.truffle.llvm.runtime.memory.LLVMSyscallOperationNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; - -import static com.oracle.truffle.llvm.nodes.asm.syscall.LLVMAMD64Time.CLOCK_MONOTONIC; -import static com.oracle.truffle.llvm.nodes.asm.syscall.LLVMAMD64Time.CLOCK_REALTIME; +import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; public abstract class LLVMAMD64SyscallClockGetTimeNode extends LLVMSyscallOperationNode { + @Child private LLVMI64StoreNode writeI64; + + public LLVMAMD64SyscallClockGetTimeNode() { + this.writeI64 = LLVMI64StoreNodeGen.create(null, null); + } + @Override public final String getName() { return "clock_gettime"; } @Specialization - protected long doI64(long clkId, LLVMNativePointer tp, - @Cached("getLLVMMemory()") LLVMMemory memory) { - return clockGetTime(memory, (int) clkId, tp); + protected long doI64(long clkId, LLVMPointer tp) { + return clockGetTime((int) clkId, tp); } @Specialization - protected long doI64(long clkId, long tp, - @Cached("getLLVMMemory()") LLVMMemory memory) { - return doI64(clkId, LLVMNativePointer.create(tp), memory); - } - - @TruffleBoundary - private static long currentTimeMillis() { - return System.currentTimeMillis(); - } - - @TruffleBoundary - private static long nanoTime() { - return System.nanoTime(); + protected long doI64(long clkId, long tp) { + return doI64(clkId, LLVMNativePointer.create(tp)); } - private static int clockGetTime(LLVMMemory memory, int clkId, LLVMNativePointer timespec) { + private int clockGetTime(int clkId, LLVMPointer timespec) { long s; long ns; switch (clkId) { case CLOCK_REALTIME: { - long t = currentTimeMillis(); + long t = System.currentTimeMillis(); s = t / 1000; ns = (t % 1000) * 1000000; break; } case CLOCK_MONOTONIC: { - long t = nanoTime(); + long t = System.nanoTime(); s = t / 1000000000L; ns = (t % 1000000000L); break; @@ -87,10 +81,10 @@ private static int clockGetTime(LLVMMemory memory, int clkId, LLVMNativePointer default: return -LLVMAMD64Error.EINVAL; } - LLVMNativePointer ptr = timespec; - memory.putI64(ptr, s); + LLVMPointer ptr = timespec; + writeI64.executeWithTarget(ptr, s); ptr = ptr.increment(8); - memory.putI64(ptr, ns); + writeI64.executeWithTarget(ptr, ns); return 0; } } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLandingpadNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLandingpadNode.java index 960cfa05c..a8d7cadc1 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLandingpadNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMLandingpadNode.java @@ -30,75 +30,69 @@ package com.oracle.truffle.llvm.nodes.func; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.UnexpectedResultException; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMI32StoreNode; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMI32StoreNodeGen; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMPointerStoreNode; +import com.oracle.truffle.llvm.nodes.memory.store.LLVMPointerStoreNodeGen; +import com.oracle.truffle.llvm.nodes.op.ToComparableValue; +import com.oracle.truffle.llvm.nodes.op.ToComparableValueNodeGen; import com.oracle.truffle.llvm.runtime.LLVMBitcodeLibraryFunctions; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.except.LLVMUserException; -import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.memory.LLVMStack; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNodeGen; -import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; +import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; public final class LLVMLandingpadNode extends LLVMExpressionNode { @Child private LLVMExpressionNode getStack; - @Child private LLVMToNativeNode allocateLandingPadValue; + @Child private LLVMExpressionNode allocateLandingPadValue; + @Child private LLVMPointerStoreNode writePointer; + @Child private LLVMI32StoreNode writeI32; @Children private final LandingpadEntryNode[] entries; private final FrameSlot exceptionSlot; private final boolean cleanup; - @Child private LLVMToNativeNode unwindHeaderToNative; - public LLVMLandingpadNode(LLVMExpressionNode getStack, LLVMExpressionNode allocateLandingPadValue, FrameSlot exceptionSlot, boolean cleanup, LandingpadEntryNode[] entries) { this.getStack = getStack; - this.allocateLandingPadValue = LLVMToNativeNodeGen.create(allocateLandingPadValue); + this.allocateLandingPadValue = allocateLandingPadValue; + this.writePointer = LLVMPointerStoreNodeGen.create(null, null); + this.writeI32 = LLVMI32StoreNodeGen.create(null, null); this.exceptionSlot = exceptionSlot; this.cleanup = cleanup; this.entries = entries; - this.unwindHeaderToNative = LLVMToNativeNode.createToNativeWithTarget(); - } - - @CompilationFinal private LLVMMemory memory; - - private LLVMMemory getMemory() { - if (memory == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - memory = getLLVMMemory(); - } - return memory; } @Override public Object executeGeneric(VirtualFrame frame) { try { LLVMUserException exception = (LLVMUserException) frame.getObject(exceptionSlot); - Object unwindHeader = exception.getUnwindHeader(); + LLVMPointer unwindHeader = exception.getUnwindHeader(); LLVMStack.StackPointer stack = (LLVMStack.StackPointer) getStack.executeGeneric(frame); int clauseId = getEntryIdentifier(frame, stack, unwindHeader); if (clauseId == 0 && !cleanup) { throw exception; } else { - LLVMNativePointer landingPadValue = allocateLandingPadValue.execute(frame); - getMemory().putPointer(landingPadValue, unwindHeaderToNative.executeWithTarget(unwindHeader)); - getMemory().putI32(landingPadValue.increment(LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES), clauseId); + LLVMPointer landingPadValue = allocateLandingPadValue.executeLLVMPointer(frame); + writePointer.executeWithTarget(landingPadValue, unwindHeader); + writeI32.executeWithTarget(landingPadValue.increment(LLVMExpressionNode.ADDRESS_SIZE_IN_BYTES), clauseId); return landingPadValue; } - } catch (FrameSlotTypeException e) { + } catch (FrameSlotTypeException | UnexpectedResultException e) { CompilerDirectives.transferToInterpreter(); throw new IllegalStateException(e); } } @ExplodeLoop - private int getEntryIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, Object unwindHeader) { + private int getEntryIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, LLVMPointer unwindHeader) { for (int i = 0; i < entries.length; i++) { int clauseId = entries[i].getIdentifier(frame, stack, unwindHeader); if (clauseId != 0) { @@ -110,7 +104,7 @@ private int getEntryIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, public abstract static class LandingpadEntryNode extends LLVMExpressionNode { - public abstract int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, Object unwindHeader); + public abstract int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, LLVMPointer unwindHeader); @Override public final Object executeGeneric(VirtualFrame frame) { @@ -121,11 +115,13 @@ public final Object executeGeneric(VirtualFrame frame) { public static final class LandingpadCatchEntryNode extends LandingpadEntryNode { - @Child private LLVMToNativeNode catchType; + @Child private LLVMExpressionNode catchType; @Child private LLVMBitcodeLibraryFunctions.SulongCanCatchNode canCatch; + @Child private ToComparableValue toComparableValue; public LandingpadCatchEntryNode(LLVMExpressionNode catchType) { - this.catchType = LLVMToNativeNodeGen.create(catchType); + this.catchType = catchType; + this.toComparableValue = ToComparableValueNodeGen.create(); } public LLVMBitcodeLibraryFunctions.SulongCanCatchNode getCanCatch() { @@ -138,28 +134,33 @@ public LLVMBitcodeLibraryFunctions.SulongCanCatchNode getCanCatch() { } @Override - public int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, Object unwindHeader) { - LLVMNativePointer catchAddress = catchType.execute(frame); - if (catchAddress.asNative() == 0) { - /* - * If ExcType is null, any exception matches, so the landing pad should always be - * entered. catch (...) - */ - return 1; - } - if (getCanCatch().canCatch(stack, unwindHeader, catchAddress) != 0) { - return (int) catchAddress.asNative(); + public int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, LLVMPointer unwindHeader) { + try { + LLVMPointer catchAddress = catchType.executeLLVMPointer(frame); + if (catchAddress.isNull()) { + /* + * If ExcType is null, any exception matches, so the landing pad should always + * be entered. catch (...) + */ + return 1; + } + if (getCanCatch().canCatch(stack, unwindHeader, catchAddress) != 0) { + return (int) toComparableValue.executeWithTarget(catchAddress); + } + return 0; + } catch (UnexpectedResultException e) { + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException(e); } - return 0; } } public static final class LandingpadFilterEntryNode extends LandingpadEntryNode { - @Children private final LLVMToNativeNode[] filterTypes; + @Children private final LLVMExpressionNode[] filterTypes; @Child private LLVMBitcodeLibraryFunctions.SulongCanCatchNode canCatch; - public LandingpadFilterEntryNode(LLVMToNativeNode[] filterTypes) { + public LandingpadFilterEntryNode(LLVMExpressionNode[] filterTypes) { this.filterTypes = filterTypes; } @@ -173,7 +174,7 @@ public LLVMBitcodeLibraryFunctions.SulongCanCatchNode getCanCatch() { } @Override - public int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, Object unwindHeader) { + public int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, LLVMPointer unwindHeader) { if (!filterMatches(frame, stack, unwindHeader)) { // when this clause is matched, the selector value has to be negative return -1; @@ -182,26 +183,30 @@ public int getIdentifier(VirtualFrame frame, LLVMStack.StackPointer stack, Objec } @ExplodeLoop - private boolean filterMatches(VirtualFrame frame, LLVMStack.StackPointer stack, Object unwindHeader) { + private boolean filterMatches(VirtualFrame frame, LLVMStack.StackPointer stack, LLVMPointer unwindHeader) { /* * Landingpad should be entered if the exception being thrown does not match any of the * types in the list */ - for (int i = 0; i < filterTypes.length; i++) { - LLVMNativePointer filterAddress = filterTypes[i].execute(frame); - if (filterAddress.asNative() == 0) { - /* - * If ExcType is null, any exception matches, so the landing pad should always - * be entered. catch (...) - */ - return true; - } - if (getCanCatch().canCatch(stack, unwindHeader, filterAddress) != 0) { - return true; + try { + for (int i = 0; i < filterTypes.length; i++) { + LLVMPointer filterAddress = filterTypes[i].executeLLVMPointer(frame); + if (filterAddress.isNull()) { + /* + * If ExcType is null, any exception matches, so the landing pad should + * always be entered. catch (...) + */ + return true; + } + if (getCanCatch().canCatch(stack, unwindHeader, filterAddress) != 0) { + return true; + } } + return false; + } catch (UnexpectedResultException e) { + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException(e); } - return false; } } - } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMRaiseExceptionNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMRaiseExceptionNode.java index fe9fc1737..56ae97fd8 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMRaiseExceptionNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMRaiseExceptionNode.java @@ -29,7 +29,9 @@ */ package com.oracle.truffle.llvm.nodes.func; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.llvm.runtime.except.LLVMUserException; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; @@ -43,6 +45,11 @@ public LLVMRaiseExceptionNode(LLVMExpressionNode unwindHeader) { @Override public Object executeGeneric(VirtualFrame frame) { - throw new LLVMUserException(this, unwindHeader.executeGeneric(frame)); + try { + throw new LLVMUserException(this, unwindHeader.executeLLVMPointer(frame)); + } catch (UnexpectedResultException e) { + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException(e); + } } } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMTypeIdForExceptionNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMTypeIdForExceptionNode.java index e91a7b23a..7a9f1a857 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMTypeIdForExceptionNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/func/LLVMTypeIdForExceptionNode.java @@ -29,21 +29,26 @@ */ package com.oracle.truffle.llvm.nodes.func; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.UnexpectedResultException; +import com.oracle.truffle.llvm.nodes.op.ToComparableValue; +import com.oracle.truffle.llvm.nodes.op.ToComparableValueNodeGen; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNodeGen; +import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; public final class LLVMTypeIdForExceptionNode extends LLVMExpressionNode { - @Child private LLVMToNativeNode thrownTypeID; + @Child private LLVMExpressionNode thrownTypeID; + @Child private ToComparableValue toComparableValue; private final LLVMSourceLocation source; public LLVMTypeIdForExceptionNode(LLVMExpressionNode thrownTypeID, LLVMSourceLocation sourceSection) { - this.thrownTypeID = LLVMToNativeNodeGen.create(thrownTypeID); + this.thrownTypeID = thrownTypeID; this.source = sourceSection; + this.toComparableValue = ToComparableValueNodeGen.create(); } @Override @@ -53,6 +58,12 @@ public LLVMSourceLocation getSourceLocation() { @Override public Object executeGeneric(VirtualFrame frame) { - return (int) thrownTypeID.execute(frame).asNative(); + try { + LLVMPointer pointer = thrownTypeID.executeLLVMPointer(frame); + return (int) toComparableValue.executeWithTarget(pointer); + } catch (UnexpectedResultException e) { + CompilerDirectives.transferToInterpreter(); + throw new IllegalStateException(e); + } } } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/literal/LLVMPointerArrayLiteralNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/literal/LLVMPointerArrayLiteralNode.java index 8e33dea67..df367acde 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/literal/LLVMPointerArrayLiteralNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/memory/literal/LLVMPointerArrayLiteralNode.java @@ -58,7 +58,11 @@ public LLVMPointerArrayLiteralNode(LLVMExpressionNode[] values, int stride) { this.stride = stride; } - public LLVMToNativeNode[] getNativeValues() { + public LLVMExpressionNode[] getValues() { + return values; + } + + private LLVMToNativeNode[] getNativeValues() { if (nativeValues == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); nativeValues = getForceNativeNodes(values); diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java index fa08804cb..123e0673b 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java @@ -284,7 +284,7 @@ protected long sub(LLVMManagedPointer left, LLVMManagedPointer right) { protected long sub(LLVMManagedPointer left, LLVMManagedPointer right, @Cached("createToComparableValue()") ToComparableValue toComparableValueLeft, @Cached("createToComparableValue()") ToComparableValue toComparableValueRight) { - return sub(toComparableValueLeft.execute(left), toComparableValueRight.execute(right)); + return sub(toComparableValueLeft.executeWithTarget(left), toComparableValueRight.executeWithTarget(right)); } @Specialization @@ -307,13 +307,13 @@ protected long sub(LLVMNativePointer left, LLVMNativePointer right) { @Specialization protected long sub(long left, LLVMPointer right, @Cached("createToComparableValue()") ToComparableValue toComparableValue) { - return sub(left, toComparableValue.execute(right)); + return sub(left, toComparableValue.executeWithTarget(right)); } @Specialization protected long sub(LLVMPointer left, long right, @Cached("createToComparableValue()") ToComparableValue toComparableValue) { - return toComparableValue.execute(left) - right; + return toComparableValue.executeWithTarget(left) - right; } @Specialization diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMPointerCompareNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMPointerCompareNode.java index 37b3c3041..31f08af4c 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMPointerCompareNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMPointerCompareNode.java @@ -51,7 +51,7 @@ public LLVMPointerCompareNode(NativePointerCompare op) { @Specialization protected boolean doGenericCompare(Object val1, Object val2) { - return op.compare(convertVal1.execute(val1), convertVal2.execute(val2)); + return op.compare(convertVal1.executeWithTarget(val1), convertVal2.executeWithTarget(val2)); } public enum Kind { diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/ToComparableValue.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/ToComparableValue.java index 9b9305875..4e76b5813 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/ToComparableValue.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/ToComparableValue.java @@ -49,7 +49,7 @@ import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; public abstract class ToComparableValue extends LLVMNode { - protected abstract long execute(Object obj); + public abstract long executeWithTarget(Object obj); @Specialization(guards = "lib.guard(obj)") protected long doNativeCached(Object obj, @@ -62,7 +62,7 @@ protected long doNativeCached(Object obj, protected long doNative(Object obj, @Cached("createGeneric()") LLVMObjectNativeLibrary lib, @Cached("createToComparable()") NativeToComparableValue toComparable) { - return toComparable.execute(obj, lib); + return toComparable.executeWithTarget(obj, lib); } protected static NativeToComparableValue createToComparable() { @@ -76,7 +76,7 @@ private static int getHashCode(Object address) { protected abstract static class ForeignToComparableValue extends LLVMNode { - abstract long execute(TruffleObject obj); + abstract long executeWithTarget(TruffleObject obj); public static ForeignToComparableValue create() { return ForeignToComparableValueNodeGen.create(); @@ -96,7 +96,7 @@ protected long doOther(TruffleObject obj) { @ImportStatic(ForeignToLLVMType.class) protected abstract static class ManagedToComparableValue extends LLVMNode { - abstract long execute(Object obj); + abstract long executeWithTarget(Object obj); @Specialization protected long doAddress(long address) { @@ -115,7 +115,7 @@ protected long doManagedMalloc(LLVMVirtualAllocationAddress address) { @Specialization protected long doManaged(LLVMManagedPointer address, @Cached("create()") ForeignToComparableValue toComparable) { - return toComparable.execute(address.getObject()) + address.getOffset(); + return toComparable.executeWithTarget(address.getObject()) + address.getOffset(); } @Specialization @@ -131,7 +131,7 @@ public static ManagedToComparableValue create() { protected abstract static class NativeToComparableValue extends LLVMNode { - protected abstract long execute(Object obj, LLVMObjectNativeLibrary lib); + protected abstract long executeWithTarget(Object obj, LLVMObjectNativeLibrary lib); @Specialization(guards = "lib.isPointer(obj)") protected long doPointer(Object obj, LLVMObjectNativeLibrary lib) { @@ -146,7 +146,7 @@ protected long doPointer(Object obj, LLVMObjectNativeLibrary lib) { @SuppressWarnings("unused") protected long doManaged(Object obj, LLVMObjectNativeLibrary lib, @Cached("create()") ManagedToComparableValue toComparable) { - return toComparable.execute(obj); + return toComparable.executeWithTarget(obj); } } } diff --git a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index 008d49497..9a252eab1 100644 --- a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -364,8 +364,8 @@ import com.oracle.truffle.llvm.runtime.memory.LLVMMemMoveNode; import com.oracle.truffle.llvm.runtime.memory.LLVMMemSetNode; import com.oracle.truffle.llvm.runtime.memory.LLVMStack.UniquesRegion; -import com.oracle.truffle.llvm.runtime.memory.LLVMStack.UniquesRegion.UniquesRegionAllocator; import com.oracle.truffle.llvm.runtime.memory.LLVMStack.UniquesRegion.UniqueSlot; +import com.oracle.truffle.llvm.runtime.memory.LLVMStack.UniquesRegion.UniquesRegionAllocator; import com.oracle.truffle.llvm.runtime.memory.LLVMUniquesRegionAllocNode; import com.oracle.truffle.llvm.runtime.memory.LLVMUniquesRegionAllocNodeGen; import com.oracle.truffle.llvm.runtime.memory.VarargsAreaStackAllocationNode; @@ -374,7 +374,6 @@ import com.oracle.truffle.llvm.runtime.nodes.api.LLVMLoadNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStoreNode; -import com.oracle.truffle.llvm.runtime.nodes.api.LLVMToNativeNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMTypesGen; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; import com.oracle.truffle.llvm.runtime.pointer.LLVMNativePointer; @@ -1519,7 +1518,7 @@ private static LLVMLandingpadNode.LandingpadEntryNode getLandingpadCatchEntry(LL private static LLVMLandingpadNode.LandingpadEntryNode getLandingpadFilterEntry(LLVMExpressionNode exp) { LLVMPointerArrayLiteralNode array = (LLVMPointerArrayLiteralNode) exp; - LLVMToNativeNode[] types = array == null ? new LLVMToNativeNode[]{} : array.getNativeValues(); + LLVMExpressionNode[] types = array == null ? LLVMExpressionNode.NO_EXPRESSIONS : array.getValues(); return new LLVMLandingpadNode.LandingpadFilterEntryNode(types); } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/except/LLVMUserException.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/except/LLVMUserException.java index 95fe68629..814a73aaa 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/except/LLVMUserException.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/except/LLVMUserException.java @@ -30,6 +30,7 @@ package com.oracle.truffle.llvm.runtime.except; import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; /** * Used for implementing try catch blocks within LLVM bitcode (e.g., when executing __cxa_throw). @@ -40,19 +41,19 @@ public final class LLVMUserException extends LLVMException { private static final long serialVersionUID = 1L; - private final Object unwindHeader; + private final LLVMPointer unwindHeader; - public LLVMUserException(Node location, Object unwindHeader) { + public LLVMUserException(Node location, LLVMPointer unwindHeader) { super(location); this.unwindHeader = unwindHeader; } - public Object getUnwindHeader() { + public LLVMPointer getUnwindHeader() { return unwindHeader; } @Override - public Object getExceptionObject() { + public LLVMPointer getExceptionObject() { return unwindHeader; } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMExpressionNode.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMExpressionNode.java index 25e29d3b3..bef04760a 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMExpressionNode.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/api/LLVMExpressionNode.java @@ -80,6 +80,10 @@ public LLVM80BitFloat executeLLVM80BitFloat(VirtualFrame frame) throws Unexpecte return LLVMTypesGen.expectLLVM80BitFloat(executeGeneric(frame)); } + public LLVMPointer executeLLVMPointer(VirtualFrame frame) throws UnexpectedResultException { + return LLVMTypesGen.expectLLVMPointer(executeGeneric(frame)); + } + public LLVMNativePointer executeLLVMNativePointer(VirtualFrame frame) throws UnexpectedResultException { return LLVMTypesGen.expectLLVMNativePointer(executeGeneric(frame)); } From 06e551b20cf7b424c416f7a38a9d351400a951e0 Mon Sep 17 00:00:00 2001 From: Jacob Kreindl Date: Wed, 11 Jul 2018 15:16:54 +0200 Subject: [PATCH 06/12] Unwrap values from LLVMGlobalContainer for the Debugger --- .../llvm/debug/LLVMToDebugValueNode.java | 20 ++++++++++++++++--- .../parser/factories/BasicNodeFactory.java | 8 ++------ .../runtime/global/LLVMGlobalContainer.java | 9 +++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/debug/LLVMToDebugValueNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/debug/LLVMToDebugValueNode.java index bb1121bb4..06164299f 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/debug/LLVMToDebugValueNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/debug/LLVMToDebugValueNode.java @@ -40,6 +40,7 @@ import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugValue; import com.oracle.truffle.llvm.runtime.floating.LLVM80BitFloat; import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; +import com.oracle.truffle.llvm.runtime.global.LLVMGlobalContainer; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode; import com.oracle.truffle.llvm.runtime.pointer.LLVMManagedPointer; @@ -166,11 +167,24 @@ protected LLVMDebugValue fromAddressVector(LLVMPointerVector value) { @Specialization protected LLVMDebugValue fromManagedPointer(LLVMManagedPointer value) { - return new LLVMConstantValueProvider.InteropValue(value.getObject(), value.getOffset()); + final Object obj = value.getObject(); + final long offset = value.getOffset(); + if (offset == 0) { + final LLVMDebugValue unwrappedValue = executeWithTarget(obj); + if (unwrappedValue != LLVMDebugValue.UNAVAILABLE) { + return unwrappedValue; + } + } + return new LLVMConstantValueProvider.InteropValue(obj, offset); } - protected LLVMDebugValue createFromGlobal(@SuppressWarnings("unused") LLVMGlobal value, @SuppressWarnings("unused") LLVMMemory memory) { - return LLVMDebugValue.UNAVAILABLE; + @Specialization + protected LLVMDebugValue fromGlobalContainer(LLVMGlobalContainer value) { + if (value.isInNative()) { + return executeWithTarget(LLVMNativePointer.create(value.getAddress())); + } else { + return executeWithTarget(value.get()); + } } @Specialization diff --git a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index 008d49497..18fe33a59 100644 --- a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -1892,20 +1892,16 @@ public LLVMStatementNode createDebugValueInit(FrameSlot targetSlot, int[] offset public LLVMDebugObjectBuilder createDebugStaticValue(LLVMExpressionNode valueNode, boolean isGlobal) { LLVMDebugValue.Builder toDebugNode = LLVMToDebugValueNodeGen.create(); - Object value; + Object value = null; if (isGlobal) { assert valueNode instanceof LLVMAccessGlobalVariableStorageNode; LLVMAccessGlobalVariableStorageNode node = (LLVMAccessGlobalVariableStorageNode) valueNode; value = new LLVMDebugGlobalVariable(node.getDescriptor()); } else { - if (valueNode == null) { - return LLVMDebugObjectBuilder.UNAVAILABLE; - } try { value = valueNode.executeGeneric(null); - } catch (Throwable t) { + } catch (Throwable ignored) { // constant values should not need frame access - value = null; } } diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/global/LLVMGlobalContainer.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/global/LLVMGlobalContainer.java index e4f6ee93b..bbd02d68d 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/global/LLVMGlobalContainer.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/global/LLVMGlobalContainer.java @@ -147,6 +147,14 @@ public void set(Object value) { contents = value; } + public boolean isInNative() { + return address != 0; + } + + public long getAddress() { + return address; + } + @SuppressWarnings("static-method") public int getSize() { return 1; @@ -318,6 +326,7 @@ public void dispose() { if (address != 0) { LLVMMemory memory = LLVMLanguage.getLanguage().getCapability(LLVMMemory.class); memory.free(address); + address = 0; } } } From 8256da7abf2abbb47bf84d0f97fa19c7b57451af Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Wed, 11 Jul 2018 15:49:22 +0200 Subject: [PATCH 07/12] Fix performance regression in foreign object access. --- .../truffle/llvm/runtime/interop/LLVMTypedForeignObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMTypedForeignObject.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMTypedForeignObject.java index 63af4e986..039146f1c 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMTypedForeignObject.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/interop/LLVMTypedForeignObject.java @@ -128,7 +128,7 @@ static Node createGetDynamicType() { return GetDynamicType.INSTANCE.createNode(); } - @Specialization(guards = "clazz.isInstance(object)") + @Specialization(guards = "clazz.isInstance(object.getForeign())") public LLVMInteropType.Structured doCached(LLVMTypedForeignObject object, @Cached("object.getForeign().getClass()") @SuppressWarnings("unused") Class clazz, @Cached("create()") TypeCacheNode typeCache) { From 2fed34769f15ae13aea49990cb330a5e7fc46e22 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 11 Jul 2018 15:57:02 +0200 Subject: [PATCH 08/12] More flexible pointer arithmetics. --- .../llvm/nodes/op/LLVMArithmeticNode.java | 22 +++++++------------ .../truffle/llvm/nodes/op/LLVMLogicNode.java | 21 +++++++++++++++++- .../runtime/pointer/LLVMManagedPointer.java | 15 ++++++++++--- .../runtime/pointer/LLVMNativePointer.java | 6 +++++ .../llvm/runtime/pointer/LLVMPointer.java | 5 ++--- .../llvm/runtime/pointer/LLVMPointerImpl.java | 21 ++++++++++++++++-- 6 files changed, 67 insertions(+), 23 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java index 123e0673b..e3ff60900 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMArithmeticNode.java @@ -674,24 +674,24 @@ protected long urem(long left, long right) { } @Specialization - protected long urem(LLVMNativePointer left, long right) { - return urem(left.asNative(), right); + protected long urem(LLVMPointer left, long right) { + return left.urem(right); } @Specialization - protected long urem(long left, LLVMNativePointer right) { + protected long urem(LLVMPointer left, LLVMNativePointer right) { return urem(left, right.asNative()); } @Specialization - protected long urem(LLVMNativePointer left, LLVMNativePointer right) { - return urem(left.asNative(), right.asNative()); + protected long urem(LLVMPointer left, LLVMManagedPointer right, + @Cached("createToNativeWithTarget()") LLVMToNativeNode toNative) { + return urem(left, toNative.executeWithTarget(right).asNative()); } @Specialization - protected long urem(LLVMManagedPointer left, long right, - @Cached("createToNativeWithTarget()") LLVMToNativeNode toNative) { - return urem(toNative.executeWithTarget(left).asNative(), right); + protected long urem(long left, LLVMNativePointer right) { + return urem(left, right.asNative()); } @Specialization @@ -700,12 +700,6 @@ protected long urem(long left, LLVMManagedPointer right, return urem(left, toNative.executeWithTarget(right).asNative()); } - @Specialization - protected long urem(LLVMManagedPointer left, LLVMManagedPointer right, - @Cached("createToNativeWithTarget()") LLVMToNativeNode toNative) { - return urem(toNative.executeWithTarget(left).asNative(), toNative.executeWithTarget(right).asNative()); - } - @Specialization protected LLVMIVarBit urem(LLVMIVarBit left, LLVMIVarBit right) { return left.unsignedRem(right); diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java index 5df6ae1cb..5ded213d7 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/op/LLVMLogicNode.java @@ -49,6 +49,9 @@ public abstract class LLVMLogicNode extends LLVMExpressionNode { public abstract static class LLVMAndNode extends LLVMLogicNode { + private static final long ALIGNMENT_BITS = 8; + private static final long IS_ALIGNMENT = (-1L) >>> ALIGNMENT_BITS; + @Specialization protected boolean and(boolean left, boolean right) { return left & right; @@ -75,10 +78,20 @@ protected long and(long left, long right) { } @Specialization - protected LLVMPointer and(LLVMPointer left, long right) { + protected LLVMNativePointer and(LLVMNativePointer left, long right) { return left.and(right); } + @Specialization(guards = "doesAlignment(right)") + protected LLVMPointer andAlign(LLVMManagedPointer left, long right) { + return left.andAlign(right); + } + + @Specialization(guards = "!doesAlignment(right)") + protected long andRem(LLVMManagedPointer left, long right) { + return left.andRem(right); + } + @Specialization protected LLVMIVarBit and(LLVMIVarBit left, LLVMIVarBit right) { return left.and(right); @@ -108,6 +121,12 @@ protected LLVMI64Vector doI64Vector(LLVMI64Vector left, LLVMI64Vector right) { protected LLVMI8Vector doI8Vector(LLVMI8Vector left, LLVMI8Vector right) { return left.and(right); } + + protected static boolean doesAlignment(long right) { + // we assume that the AND operation is used for alignment if all upper bits of the right + // AND operand are 1 + return (right >>> ALIGNMENT_BITS) == IS_ALIGNMENT; + } } public abstract static class LLVMOrNode extends LLVMLogicNode { diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMManagedPointer.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMManagedPointer.java index 7c96af6d1..48929f0d0 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMManagedPointer.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMManagedPointer.java @@ -69,12 +69,21 @@ public interface LLVMManagedPointer extends LLVMPointer { @Override LLVMManagedPointer increment(long offset); - @Override - LLVMManagedPointer and(long value); - @Override LLVMManagedPointer export(LLVMInteropType newType); + /** + * Aligns the pointer by doing a binary AND operation. The {@link #getExportType export type} of + * the result pointer is reset to {@code null}. + */ + LLVMPointerImpl andAlign(long value); + + /** + * Computes the remainder by doing a binary AND operation. The {@link #getExportType export + * type} of the result pointer is reset to {@code null}. + */ + long andRem(long value); + /** * Create a new managed pointer, pointing to the beginning of a managed object. */ diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMNativePointer.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMNativePointer.java index 1f82c1e22..669cc2567 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMNativePointer.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMNativePointer.java @@ -65,6 +65,12 @@ public interface LLVMNativePointer extends LLVMPointer { @Override LLVMNativePointer export(LLVMInteropType newType); + /** + * Does a binary AND operation. The {@link #getExportType export type} of the result pointer is + * reset to {@code null}. + */ + LLVMNativePointer and(long value); + /** * Create a null pointer. */ diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointer.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointer.java index 19d1d171e..7da1f2f0e 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointer.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointer.java @@ -70,10 +70,9 @@ public interface LLVMPointer extends TruffleObject { LLVMPointer increment(long offset); /** - * Does a binary AND operation (typically for alignment). The {@link #getExportType export type} - * of the result pointer is reset to {@code null}. + * Computes the unsigned remainder. */ - LLVMPointer and(long value); + long urem(long value); /** * Get the {@link LLVMInteropType} of this pointer. This type is used to determine access diff --git a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointerImpl.java b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointerImpl.java index f2aa95f81..2e8591150 100644 --- a/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointerImpl.java +++ b/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/pointer/LLVMPointerImpl.java @@ -124,11 +124,28 @@ public LLVMPointerImpl increment(long incr) { } @Override - public LLVMPointerImpl and(long value) { - // reset type, since the result points to something else now + public LLVMNativePointer and(long value) { + assert isNative(); + return new LLVMPointerImpl(object, offset & value, null); + } + + @Override + public LLVMPointerImpl andAlign(long value) { + assert isManaged(); return new LLVMPointerImpl(object, offset & value, null); } + @Override + public long andRem(long value) { + assert isManaged(); + return offset & value; + } + + @Override + public long urem(long value) { + return Long.remainderUnsigned(offset, value); + } + @Override public LLVMPointerImpl export(LLVMInteropType newType) { return new LLVMPointerImpl(object, offset, newType); From 16274ec80e064b35ac94058d9d5de488eec962f0 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 12 Jul 2018 13:04:14 +0200 Subject: [PATCH 09/12] Removed some code duplication. --- .../parser/factories/BasicNodeFactory.java | 14 +++++- .../truffle/llvm/parser/NodeFactory.java | 4 ++ .../truffle/llvm/BasicConfiguration.java | 2 +- .../src/com/oracle/truffle/llvm/Sulong.java | 44 +++++++------------ 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index 9a252eab1..bab3ffd7f 100644 --- a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -1654,9 +1654,9 @@ protected LLVMExpressionNode getLLVMBuiltin(LLVMContext context, FunctionDeclara case "@llvm.invariant.end.p0i8": return LLVMInvariantEndNodeGen.create(args[1], args[2], sourceSection); case "@llvm.stacksave": - return LLVMStackSaveNodeGen.create(sourceSection); + return createStackSave(context, sourceSection); case "@llvm.stackrestore": - return LLVMStackRestoreNodeGen.create(args[1], sourceSection); + return createStackRestore(context, args[1], sourceSection); case "@llvm.frameaddress": return LLVMFrameAddressNodeGen.create(args[1], sourceSection); case "@llvm.va_start": @@ -1774,6 +1774,16 @@ protected LLVMExpressionNode getLLVMBuiltin(LLVMContext context, FunctionDeclara } } + @Override + public LLVMExpressionNode createStackSave(LLVMContext context, LLVMSourceLocation sourceSection) { + return LLVMStackSaveNodeGen.create(sourceSection); + } + + @Override + public LLVMExpressionNode createStackRestore(LLVMContext context, LLVMExpressionNode stackPointer, LLVMSourceLocation sourceSection) { + return LLVMStackRestoreNodeGen.create(stackPointer, sourceSection); + } + private static long getOverflowFieldOffset(LLVMContext context, FunctionDeclaration declaration) { return context.getIndexOffset(1, (AggregateType) declaration.getType().getReturnType()); } diff --git a/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/NodeFactory.java b/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/NodeFactory.java index 850ce390c..e654f8b6f 100644 --- a/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/NodeFactory.java +++ b/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/NodeFactory.java @@ -214,4 +214,8 @@ LLVMExpressionNode createCompareExchangeInstruction(LLVMContext context, Aggrega LLVMAllocateStringNode createAllocateString(); LLVMAllocateStructNode createAllocateStruct(LLVMContext context, StructureType structType); + + LLVMExpressionNode createStackSave(LLVMContext context, LLVMSourceLocation sourceSection); + + LLVMExpressionNode createStackRestore(LLVMContext context, LLVMExpressionNode stackPointer, LLVMSourceLocation sourceSection); } diff --git a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java index 4a731125d..5249e2687 100644 --- a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java +++ b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/BasicConfiguration.java @@ -35,9 +35,9 @@ import org.graalvm.options.OptionDescriptor; import com.oracle.truffle.api.TruffleLanguage; -import com.oracle.truffle.llvm.parser.NodeFactory; import com.oracle.truffle.llvm.parser.factories.BasicNodeFactory; import com.oracle.truffle.llvm.parser.factories.BasicSystemContextExtension; +import com.oracle.truffle.llvm.parser.NodeFactory; import com.oracle.truffle.llvm.parser.factories.BasicIntrinsicsProvider; import com.oracle.truffle.llvm.runtime.ContextExtension; import com.oracle.truffle.llvm.runtime.LLVMContext; diff --git a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Sulong.java b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Sulong.java index a33051d68..2a57d6203 100644 --- a/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Sulong.java +++ b/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/Sulong.java @@ -50,14 +50,13 @@ import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.llvm.Runner.SulongLibrary; import com.oracle.truffle.llvm.parser.NodeFactory; -import com.oracle.truffle.llvm.runtime.ContextExtension; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; import com.oracle.truffle.llvm.runtime.LLVMSymbol; -import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; -import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; -import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; import com.oracle.truffle.llvm.runtime.debug.scope.LLVMDebuggerScopeFactory; +import com.oracle.truffle.llvm.runtime.debug.scope.LLVMSourceLocation; +import com.oracle.truffle.llvm.runtime.debug.type.LLVMSourceType; +import com.oracle.truffle.llvm.runtime.debug.value.LLVMDebugObject; import com.oracle.truffle.llvm.runtime.interop.LLVMInternalTruffleObject; import com.oracle.truffle.llvm.runtime.interop.access.LLVMInteropType; import com.oracle.truffle.llvm.runtime.memory.LLVMMemory; @@ -82,21 +81,15 @@ public final class Sulong extends LLVMLanguage { @TruffleBoundary @Override public E getCapability(Class type) { - String config = findLLVMContext().getEnv().getOptions().get(SulongEngineOption.CONFIGURATION); - E capability = null; - for (Configuration c : configurations) { - if (config.equals(c.getConfigurationName())) { - capability = c.getCapability(type); - } - } - return capability; + return getActiveConfiguration(findLLVMContext().getEnv()).getCapability(type); } private LLVMContext mainContext = null; @Override protected LLVMContext createContext(com.oracle.truffle.api.TruffleLanguage.Env env) { - LLVMContext newContext = new LLVMContext(this, env, getContextExtensions(env), getNodeFactory(env), getLanguageHome()); + Configuration activeConfiguration = getActiveConfiguration(env); + LLVMContext newContext = new LLVMContext(this, env, activeConfiguration.createContextExtensions(env, this), getNodeFactory(env), getLanguageHome()); if (mainContext == null) { mainContext = newContext; } else { @@ -175,16 +168,6 @@ public LLVMContext findLLVMContext() { return getContextReference().get(); } - private List getContextExtensions(com.oracle.truffle.api.TruffleLanguage.Env env) { - String config = env.getOptions().get(SulongEngineOption.CONFIGURATION); - for (Configuration c : configurations) { - if (config.equals(c.getConfigurationName())) { - return c.createContextExtensions(env, this); - } - } - throw new IllegalStateException(); - } - @Override protected OptionDescriptors getOptionDescriptors() { List optionDescriptors = new ArrayList<>(); @@ -195,13 +178,18 @@ protected OptionDescriptors getOptionDescriptors() { } private NodeFactory getNodeFactory(Env env) { - String config = env.getOptions().get(SulongEngineOption.CONFIGURATION); - for (Configuration c : configurations) { - if (config.equals(c.getConfigurationName())) { - return c.getNodeFactory(findLLVMContext()); + return getActiveConfiguration(env).getNodeFactory(findLLVMContext()); + } + + @TruffleBoundary + private static Configuration getActiveConfiguration(Env env) { + String name = env.getOptions().get(SulongEngineOption.CONFIGURATION); + for (Configuration config : configurations) { + if (name.equals(config.getConfigurationName())) { + return config; } } - throw new IllegalStateException(); + throw new IllegalStateException("Unknown configuration: " + name); } @Override From 6d0f8114490ebc4e35013abf1b241991dc1947d5 Mon Sep 17 00:00:00 2001 From: Roland Schatz Date: Thu, 12 Jul 2018 16:13:19 +0200 Subject: [PATCH 10/12] Update truffle import. --- ci.hocon | 2 +- mx.sulong/suite.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci.hocon b/ci.hocon index 82aa6557f..8aa86f343 100644 --- a/ci.hocon +++ b/ci.hocon @@ -1,4 +1,4 @@ -overlay = 28a74bfc8ad6d6a7cffc2b7835f6cc27cd03993a +overlay = 285c321ec6602bca64076afe572c7b116977c01b java8: {name: labsjdk, version: "8u172-jvmci-0.46", platformspecific: true} eclipse: {name: eclipse, version: "4.5.2", platformspecific: true} diff --git a/mx.sulong/suite.py b/mx.sulong/suite.py index 72252332f..c7e93e521 100644 --- a/mx.sulong/suite.py +++ b/mx.sulong/suite.py @@ -8,7 +8,7 @@ { "name" : "truffle", "subdir" : True, - "version" : "a2267424f072edbef5916cd519a08a0514658bdd", + "version" : "dc37c9a244fc97a92b7b37f716e484cb4b7ee5ed", "urls" : [ {"url" : "https://github.com/graalvm/graal", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, From 79490cfbc72956fa75cedfb31adacb8693f83c57 Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Wed, 4 Jul 2018 10:09:50 +0200 Subject: [PATCH 11/12] Small fix to README and add some build artifacts to .gitignore --- .gitignore | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a12c4513e..072c98183 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ mx.sulong/eclipse-launches/** mx.sulong/libs/*.ll mx.sulong/libs/*.bc mx.sulong/*.iml +mx.sulong/.project +mx.sulong/.pydevproject .DS_Store build.xml workingsets.xml @@ -29,6 +31,9 @@ projects/*/\bin projects/*/\.checkstyle projects/*/*.iml projects/*/\.factorypath +projects/SULONG.dist/ +projects/SULONG_LAUNCHER.dist/ +projects/SULONG_TEST.dist/ cache/** projects/com.oracle.truffle.llvm.bench/languagegame/** diff --git a/README.md b/README.md index 65c4a5c00..bb357594c 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Set `JAVA_HOME` to point to the extracted labsjdk from above: Sulong partially consists of C/C++ code that is compiled using `make`. To speed up the build process you can edit the `MAKEFLAGS` environment variable: - echo MAKEFLAGS=-j9 > sulong/mx.sulong/env + echo MAKEFLAGS=-j9 >> sulong/mx.sulong/env Finally, build the project: From ccf8d858b66efb4614fad7a8c42055552c65744d Mon Sep 17 00:00:00 2001 From: Thomas Pointhuber Date: Wed, 4 Jul 2018 11:51:53 +0200 Subject: [PATCH 12/12] Force locale on LC_ALL=C for testcases Some testcases compare strings, which are local dependent. --- mx.sulong/mx_sulong.py | 94 ++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 19706cfbd..f0b2ee154 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -50,8 +50,6 @@ # re-export SulongTestSuite class so it can be used from suite.py from mx_testsuites import SulongTestSuite #pylint: disable=unused-import -os.environ["LC_NUMERIC"] = "C" # required for some testcases - _suite = mx.suite('sulong') _mx = join(_suite.dir, "mx.sulong") _root = join(_suite.dir, "projects") @@ -117,46 +115,62 @@ def _unittest_config_participant(config): add_config_participant(_unittest_config_participant) +class TemporaryEnv(object): + def __init__(self, key, value): + self.key = key + self.value = value + self.old_value = None + + def __enter__(self): + self.old_value = os.environ.get(self.key) + os.environ[self.key] = self.value + + def __exit__(self, ex_type, value, traceback): + if self.old_value is None: + del os.environ[self.key] + else: + os.environ[self.key] = self.old_value def _sulong_gate_runner(args, tasks): - with Task('CheckCopyright', tasks, tags=['style']) as t: - if t: - if mx.checkcopyrights(['--primary']) != 0: - t.abort('Copyright errors found. Please run "mx checkcopyrights --primary -- --fix" to fix them.') - with Task('ClangFormat', tasks, tags=['style', 'clangformat']) as t: - if t: clangformatcheck() - with Task('TestBenchmarks', tasks, tags=['benchmarks', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('shootout') - with Task('TestTypes', tasks, tags=['type', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('type') - with Task('TestPipe', tasks, tags=['pipe', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('pipe') - with Task('TestLLVM', tasks, tags=['llvm']) as t: - if t: mx_testsuites.runSuite('llvm') - with Task('TestNWCC', tasks, tags=['nwcc']) as t: - if t: mx_testsuites.runSuite('nwcc') - with Task('TestGCCParserTorture', tasks, tags=['parser']) as t: - if t: mx_testsuites.runSuite('parserTorture') - with Task('TestGCC_C', tasks, tags=['gcc_c']) as t: - if t: mx_testsuites.runSuite('gcc_c') - with Task('TestGCC_CPP', tasks, tags=['gcc_cpp']) as t: - if t: mx_testsuites.runSuite('gcc_cpp') - with Task('TestGCC_Fortran', tasks, tags=['gcc_fortran']) as t: - if t: mx_testsuites.runSuite('gcc_fortran') - with Task("TestSulong", tasks, tags=['sulong', 'sulongBasic']) as t: - if t: mx_unittest.unittest(['SulongSuite']) - with Task("TestInterop", tasks, tags=['interop', 'sulongBasic']) as t: - if t: mx_unittest.unittest(['com.oracle.truffle.llvm.test.interop']) - with Task("TestDebug", tasks, tags=['debug', 'sulongBasic']) as t: - if t: mx_unittest.unittest(['LLVMDebugTest']) - with Task('TestAssembly', tasks, tags=['assembly', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('assembly') - with Task('TestArgs', tasks, tags=['args', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('args') - with Task('TestCallback', tasks, tags=['callback', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('callback') - with Task('TestVarargs', tasks, tags=['vaargs', 'sulongMisc']) as t: - if t: mx_testsuites.runSuite('vaargs') + with TemporaryEnv('LC_ALL', 'C'): + with Task('CheckCopyright', tasks, tags=['style']) as t: + if t: + if mx.checkcopyrights(['--primary']) != 0: + t.abort('Copyright errors found. Please run "mx checkcopyrights --primary -- --fix" to fix them.') + with Task('ClangFormat', tasks, tags=['style', 'clangformat']) as t: + if t: clangformatcheck() + with Task('TestBenchmarks', tasks, tags=['benchmarks', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('shootout') + with Task('TestTypes', tasks, tags=['type', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('type') + with Task('TestPipe', tasks, tags=['pipe', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('pipe') + with Task('TestLLVM', tasks, tags=['llvm']) as t: + if t: mx_testsuites.runSuite('llvm') + with Task('TestNWCC', tasks, tags=['nwcc']) as t: + if t: mx_testsuites.runSuite('nwcc') + with Task('TestGCCParserTorture', tasks, tags=['parser']) as t: + if t: mx_testsuites.runSuite('parserTorture') + with Task('TestGCC_C', tasks, tags=['gcc_c']) as t: + if t: mx_testsuites.runSuite('gcc_c') + with Task('TestGCC_CPP', tasks, tags=['gcc_cpp']) as t: + if t: mx_testsuites.runSuite('gcc_cpp') + with Task('TestGCC_Fortran', tasks, tags=['gcc_fortran']) as t: + if t: mx_testsuites.runSuite('gcc_fortran') + with Task("TestSulong", tasks, tags=['sulong', 'sulongBasic']) as t: + if t: mx_unittest.unittest(['SulongSuite']) + with Task("TestInterop", tasks, tags=['interop', 'sulongBasic']) as t: + if t: mx_unittest.unittest(['com.oracle.truffle.llvm.test.interop']) + with Task("TestDebug", tasks, tags=['debug', 'sulongBasic']) as t: + if t: mx_unittest.unittest(['LLVMDebugTest']) + with Task('TestAssembly', tasks, tags=['assembly', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('assembly') + with Task('TestArgs', tasks, tags=['args', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('args') + with Task('TestCallback', tasks, tags=['callback', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('callback') + with Task('TestVarargs', tasks, tags=['vaargs', 'sulongMisc']) as t: + if t: mx_testsuites.runSuite('vaargs') add_gate_runner(_suite, _sulong_gate_runner)