Skip to content

Commit 0b55b3a

Browse files
committed
Move obtaining Unsafe to PythonContext and make it checked
1 parent 28746f3 commit 0b55b3a

File tree

2 files changed

+86
-52
lines changed

2 files changed

+86
-52
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/memory/PointerNodes.java

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.WCHAR_T_SIZE;
55
import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR;
66

7-
import java.lang.reflect.Field;
8-
97
import com.oracle.graal.python.builtins.modules.ctypes.FFIType;
108
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.ByteArrayStorage;
119
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer.LongPointerStorage;
@@ -25,10 +23,12 @@
2523
import com.oracle.graal.python.nodes.ErrorMessages;
2624
import com.oracle.graal.python.nodes.PRaiseNode;
2725
import com.oracle.graal.python.nodes.util.CastToJavaUnsignedLongNode;
26+
import com.oracle.graal.python.runtime.PythonContext;
2827
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
2928
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
3029
import com.oracle.graal.python.util.PythonUtils;
3130
import com.oracle.truffle.api.CompilerDirectives;
31+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
3232
import com.oracle.truffle.api.dsl.Cached;
3333
import com.oracle.truffle.api.dsl.Cached.Shared;
3434
import com.oracle.truffle.api.dsl.Fallback;
@@ -95,8 +95,9 @@ static void doPointerArray(Node inliningTarget, byte[] dst, int dstOffset, Memor
9595
}
9696

9797
@Specialization
98-
static void doNativeMemory(byte[] dst, int dstOffset, @SuppressWarnings("unused") MemoryBlock srcMemory, LongPointerStorage src, int srcOffset, int size) {
99-
UNSAFE.copyMemory(null, src.pointer + srcOffset, dst, byteArrayOffset(dstOffset), size);
98+
static void doNativeMemory(Node inliningTarget, byte[] dst, int dstOffset, @SuppressWarnings("unused") MemoryBlock srcMemory, LongPointerStorage src, int srcOffset, int size) {
99+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
100+
unsafe.copyMemory(null, src.pointer + srcOffset, dst, byteArrayOffset(dstOffset), size);
100101
}
101102
}
102103

@@ -128,8 +129,9 @@ static byte doMemoryView(@SuppressWarnings("unused") MemoryBlock memory, MemoryV
128129
}
129130

130131
@Specialization
131-
static byte doNativeMemory(@SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
132-
return UNSAFE.getByte(storage.pointer + offset);
132+
static byte doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
133+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
134+
return unsafe.getByte(storage.pointer + offset);
133135
}
134136

135137
@Fallback
@@ -163,8 +165,9 @@ static short doZero(@SuppressWarnings("unused") MemoryBlock memory, ZeroStorage
163165
}
164166

165167
@Specialization
166-
static short doNativeMemory(@SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
167-
return UNSAFE.getShort(storage.pointer + offset);
168+
static short doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
169+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
170+
return unsafe.getShort(storage.pointer + offset);
168171
}
169172

170173
@Fallback
@@ -198,8 +201,9 @@ static int doZero(@SuppressWarnings("unused") MemoryBlock memory, ZeroStorage st
198201
}
199202

200203
@Specialization
201-
static int doNativeMemory(@SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
202-
return UNSAFE.getInt(storage.pointer + offset);
204+
static int doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
205+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
206+
return unsafe.getInt(storage.pointer + offset);
203207
}
204208

205209
@Fallback
@@ -233,8 +237,9 @@ static long doZero(@SuppressWarnings("unused") MemoryBlock memory, ZeroStorage s
233237
}
234238

235239
@Specialization
236-
static long doNativeMemory(@SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
237-
return UNSAFE.getLong(storage.pointer + offset);
240+
static long doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock memory, LongPointerStorage storage, int offset) {
241+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
242+
return unsafe.getLong(storage.pointer + offset);
238243
}
239244

240245
@Fallback
@@ -283,8 +288,9 @@ static void doMemoryView(@SuppressWarnings("unused") MemoryBlock dstMemory, Memo
283288
}
284289

285290
@Specialization
286-
static void doNativeMemory(@SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, byte[] src, int srcOffset, int size) {
287-
UNSAFE.copyMemory(src, byteArrayOffset(srcOffset), null, dst.pointer + dstOffset, size);
291+
static void doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, byte[] src, int srcOffset, int size) {
292+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
293+
unsafe.copyMemory(src, byteArrayOffset(srcOffset), null, dst.pointer + dstOffset, size);
288294
}
289295

290296
@Specialization
@@ -318,8 +324,9 @@ static void doZero(MemoryBlock dstMemory, ZeroStorage dst, int dstOffset, byte v
318324
}
319325

320326
@Specialization
321-
static void doNativeMemory(@SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, byte value) {
322-
UNSAFE.putByte(dst.pointer + dstOffset, value);
327+
static void doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, byte value) {
328+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
329+
unsafe.putByte(dst.pointer + dstOffset, value);
323330
}
324331

325332
@Fallback
@@ -352,8 +359,9 @@ static void doZero(MemoryBlock dstMemory, ZeroStorage dst, int dstOffset, short
352359
}
353360

354361
@Specialization
355-
static void doNativeMemory(@SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, short value) {
356-
UNSAFE.putShort(dst.pointer + dstOffset, value);
362+
static void doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, short value) {
363+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
364+
unsafe.putShort(dst.pointer + dstOffset, value);
357365
}
358366

359367
@Fallback
@@ -388,8 +396,9 @@ static void doZero(MemoryBlock dstMemory, ZeroStorage dst, int dstOffset, int va
388396
}
389397

390398
@Specialization
391-
static void doNativeMemory(@SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, int value) {
392-
UNSAFE.putInt(dst.pointer + dstOffset, value);
399+
static void doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, int value) {
400+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
401+
unsafe.putInt(dst.pointer + dstOffset, value);
393402
}
394403

395404
@Fallback
@@ -431,8 +440,9 @@ static void doPointerArray(@SuppressWarnings("unused") MemoryBlock dstMemory, Po
431440
}
432441

433442
@Specialization
434-
static void doNativeMemory(@SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, long value) {
435-
UNSAFE.putLong(dst.pointer + dstOffset, value);
443+
static void doNativeMemory(Node inliningTarget, @SuppressWarnings("unused") MemoryBlock dstMemory, LongPointerStorage dst, int dstOffset, long value) {
444+
Unsafe unsafe = PythonContext.get(inliningTarget).getUnsafe();
445+
unsafe.putLong(dst.pointer + dstOffset, value);
436446
}
437447

438448
@Fallback
@@ -574,35 +584,35 @@ static long doNativePointer(@SuppressWarnings("unused") MemoryBlock memory, Long
574584
}
575585

576586
@Specialization
577-
static long doBytes(MemoryBlock memory, ByteArrayStorage storage, int offset) {
587+
static long doBytes(Node inliningTarget, MemoryBlock memory, ByteArrayStorage storage, int offset) {
578588
int len = storage.bytes.length;
579-
// TODO check permissions
580589
// We need to copy the whole memory block to keep the pointer offsets consistent
581-
long pointer = UNSAFE.allocateMemory(len);
582-
UNSAFE.copyMemory(storage.bytes, byteArrayOffset(0), null, pointer, len);
590+
PythonContext context = PythonContext.get(inliningTarget);
591+
long pointer = context.allocateNativeMemory(len);
592+
context.getUnsafe().copyMemory(storage.bytes, byteArrayOffset(0), null, pointer, len);
583593
memory.storage = new LongPointerStorage(pointer);
584594
return pointer + offset;
585595
}
586596

587597
@Specialization
588-
static long doZero(MemoryBlock memory, ZeroStorage storage, int offset) {
598+
static long doZero(Node inliningTarget, MemoryBlock memory, ZeroStorage storage, int offset) {
589599
int len = storage.size;
590-
// TODO check permissions
591-
long pointer = UNSAFE.allocateMemory(len);
592-
UNSAFE.setMemory(pointer, len, (byte) 0);
600+
PythonContext context = PythonContext.get(inliningTarget);
601+
long pointer = context.allocateNativeMemory(len);
602+
context.getUnsafe().setMemory(pointer, len, (byte) 0);
593603
memory.storage = new LongPointerStorage(pointer);
594604
return pointer + offset;
595605
}
596606

597607
@Specialization
598608
static long doPointerArray(Node inliningTarget, MemoryBlock memory, PointerArrayStorage storage, int offset,
599609
@Cached(inline = false) GetPointerValueAsLongNode toNativeNode) {
600-
// TODO check permissions
601-
long pointer = UNSAFE.allocateMemory(storage.pointers.length * 8L);
610+
PythonContext context = PythonContext.get(inliningTarget);
611+
long pointer = context.allocateNativeMemory(storage.pointers.length * 8L);
602612
for (int i = 0; i < storage.pointers.length; i++) {
603613
Pointer itemPointer = storage.pointers[i];
604614
long subpointer = toNativeNode.execute(inliningTarget, itemPointer.memory, itemPointer.memory.storage, itemPointer.offset);
605-
UNSAFE.putLong(pointer + i * 8L, subpointer);
615+
context.getUnsafe().putLong(pointer + i * 8L, subpointer);
606616
}
607617
memory.storage = new LongPointerStorage(pointer);
608618
return pointer + offset;
@@ -686,9 +696,10 @@ public final void execute(Node inliningTarget, Pointer pointer) {
686696
abstract void execute(Node inliningTarget, Storage storage, int offset);
687697

688698
@Specialization
689-
void doNativeMemory(LongPointerStorage storage, int offset) {
690-
// TODO check permissions
691-
UNSAFE.freeMemory(storage.pointer + offset);
699+
@TruffleBoundary
700+
void doNativeMemory(Node inliningTarget, LongPointerStorage storage, int offset) {
701+
PythonContext context = PythonContext.get(inliningTarget);
702+
context.freeNativeMemory(storage.pointer + offset);
692703
}
693704

694705
@Specialization
@@ -886,22 +897,6 @@ static ByteArrayStorage convert(Node inliningTarget, MemoryBlock memory, Pointer
886897
}
887898
}
888899

889-
private static Unsafe UNSAFE = getUnsafe();
890-
891-
private static Unsafe getUnsafe() {
892-
try {
893-
return Unsafe.getUnsafe();
894-
} catch (SecurityException e) {
895-
}
896-
try {
897-
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
898-
theUnsafeInstance.setAccessible(true);
899-
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
900-
} catch (Exception e) {
901-
throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
902-
}
903-
}
904-
905900
private static long byteArrayOffset(int offset) {
906901
return (long) Unsafe.ARRAY_BYTE_BASE_OFFSET + (long) Unsafe.ARRAY_BYTE_INDEX_SCALE * (long) offset;
907902
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import java.io.PrintWriter;
6464
import java.lang.invoke.VarHandle;
6565
import java.lang.ref.WeakReference;
66+
import java.lang.reflect.Field;
6667
import java.nio.file.LinkOption;
6768
import java.security.NoSuchAlgorithmException;
6869
import java.security.SecureRandom;
@@ -181,6 +182,8 @@
181182
import com.oracle.truffle.api.utilities.TruffleWeakReference;
182183
import com.oracle.truffle.llvm.api.Toolchain;
183184

185+
import sun.misc.Unsafe;
186+
184187
public final class PythonContext extends Python3Core {
185188
public static final TruffleString T_IMPLEMENTATION = tsLiteral("implementation");
186189

@@ -2507,4 +2510,40 @@ public int getDlopenFlags() {
25072510
public void setDlopenFlags(int dlopenFlags) {
25082511
this.dlopenFlags = dlopenFlags;
25092512
}
2513+
2514+
private static final class UnsafeWrapper {
2515+
private static final Unsafe UNSAFE = initUnsafe();
2516+
2517+
private static Unsafe initUnsafe() {
2518+
try {
2519+
return Unsafe.getUnsafe();
2520+
} catch (SecurityException e) {
2521+
}
2522+
try {
2523+
Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
2524+
theUnsafeInstance.setAccessible(true);
2525+
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
2526+
} catch (Exception e) {
2527+
throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
2528+
}
2529+
}
2530+
}
2531+
2532+
public Unsafe getUnsafe() {
2533+
if (isNativeAccessAllowed()) {
2534+
return UnsafeWrapper.UNSAFE;
2535+
}
2536+
CompilerDirectives.transferToInterpreterAndInvalidate();
2537+
throw new RuntimeException("NAtive access not allowed, cannot manipulate native memory");
2538+
}
2539+
2540+
@TruffleBoundary
2541+
public long allocateNativeMemory(long size) {
2542+
return getUnsafe().allocateMemory(size);
2543+
}
2544+
2545+
@TruffleBoundary
2546+
public void freeNativeMemory(long address) {
2547+
getUnsafe().freeMemory(address);
2548+
}
25102549
}

0 commit comments

Comments
 (0)