Skip to content

Commit dc5f9d7

Browse files
committed
Fix infinite recursion with LLVMGlobalContainer.
1 parent 347f858 commit dc5f9d7

File tree

1 file changed

+116
-68
lines changed

1 file changed

+116
-68
lines changed

sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/global/LLVMGlobalContainer.java

Lines changed: 116 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2021, Oracle and/or its affiliates.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates.
33
*
44
* All rights reserved.
55
*
@@ -174,9 +174,15 @@ public int getSize() {
174174
return 1;
175175
}
176176

177-
@TruffleBoundary
178177
@ExportMessage
179178
public void toNative(@Cached LLVMToNativeNode toNative) {
179+
if (address == 0) {
180+
doToNative(toNative);
181+
}
182+
}
183+
184+
@TruffleBoundary
185+
private synchronized void doToNative(LLVMToNativeNode toNative) {
180186
if (address == 0) {
181187
LLVMMemory memory = LLVMLanguage.get(null).getLLVMMemory();
182188
LLVMNativePointer pointer = memory.allocateMemory(toNative, 8);
@@ -205,16 +211,19 @@ static class ReadI8 {
205211
@Specialization(guards = "self.isPointer()")
206212
static byte readNative(LLVMGlobalContainer self, long offset,
207213
@CachedLibrary("self") LLVMManagedReadLibrary location) {
214+
assert self.isPointer();
208215
return LLVMLanguage.get(location).getLLVMMemory().getI8(location, self.getAddress() + offset);
209216
}
210217

211-
@Specialization(guards = "!self.isPointer()")
218+
@Specialization(replaces = "readNative")
212219
@GenerateAOT.Exclude
213220
static byte readManaged(LLVMGlobalContainer self, long offset,
214-
@CachedLibrary("self") InteropLibrary interop,
215-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
216-
interop.toNative(self);
217-
return read.readI8(self, offset);
221+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
222+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
223+
self.toNative(toNative);
224+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
225+
// We already know we'll be in the self.isPointer() case after toNative.
226+
return readNative(self, offset, location);
218227
}
219228
}
220229

@@ -224,16 +233,19 @@ static class ReadI16 {
224233
@Specialization(guards = "self.isPointer()")
225234
static short readNative(LLVMGlobalContainer self, long offset,
226235
@CachedLibrary("self") LLVMManagedReadLibrary location) {
236+
assert self.isPointer();
227237
return LLVMLanguage.get(location).getLLVMMemory().getI16(location, self.getAddress() + offset);
228238
}
229239

230-
@Specialization(guards = "!self.isPointer()")
240+
@Specialization(replaces = "readNative")
231241
@GenerateAOT.Exclude
232242
static short readManaged(LLVMGlobalContainer self, long offset,
233-
@CachedLibrary("self") InteropLibrary interop,
234-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
235-
interop.toNative(self);
236-
return read.readI16(self, offset);
243+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
244+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
245+
self.toNative(toNative);
246+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
247+
// We already know we'll be in the self.isPointer() case after toNative.
248+
return readNative(self, offset, location);
237249
}
238250
}
239251

@@ -243,16 +255,19 @@ static class ReadI32 {
243255
@Specialization(guards = "self.isPointer()")
244256
static int readNative(LLVMGlobalContainer self, long offset,
245257
@CachedLibrary("self") LLVMManagedReadLibrary location) {
258+
assert self.isPointer();
246259
return LLVMLanguage.get(location).getLLVMMemory().getI32(location, self.getAddress() + offset);
247260
}
248261

249-
@Specialization(guards = "!self.isPointer()")
262+
@Specialization(replaces = "readNative")
250263
@GenerateAOT.Exclude
251264
static int readManaged(LLVMGlobalContainer self, long offset,
252-
@CachedLibrary("self") InteropLibrary interop,
253-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
254-
interop.toNative(self);
255-
return read.readI32(self, offset);
265+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
266+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
267+
self.toNative(toNative);
268+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
269+
// We already know we'll be in the self.isPointer() case after toNative.
270+
return readNative(self, offset, location);
256271
}
257272
}
258273

@@ -262,16 +277,19 @@ static class ReadFloat {
262277
@Specialization(guards = "self.isPointer()")
263278
static float readNative(LLVMGlobalContainer self, long offset,
264279
@CachedLibrary("self") LLVMManagedReadLibrary location) {
280+
assert self.isPointer();
265281
return LLVMLanguage.get(location).getLLVMMemory().getFloat(location, self.getAddress() + offset);
266282
}
267283

268-
@Specialization(guards = "!self.isPointer()")
284+
@Specialization(replaces = "readNative")
269285
@GenerateAOT.Exclude
270286
static float readManaged(LLVMGlobalContainer self, long offset,
271-
@CachedLibrary("self") InteropLibrary interop,
272-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
273-
interop.toNative(self);
274-
return read.readFloat(self, offset);
287+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
288+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
289+
self.toNative(toNative);
290+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
291+
// We already know we'll be in the self.isPointer() case after toNative.
292+
return readNative(self, offset, location);
275293
}
276294
}
277295

@@ -281,16 +299,19 @@ static class ReadDouble {
281299
@Specialization(guards = "self.isPointer()")
282300
static double readNative(LLVMGlobalContainer self, long offset,
283301
@CachedLibrary("self") LLVMManagedReadLibrary location) {
302+
assert self.isPointer();
284303
return LLVMLanguage.get(location).getLLVMMemory().getDouble(location, self.getAddress() + offset);
285304
}
286305

287-
@Specialization(guards = "!self.isPointer()")
306+
@Specialization(replaces = "readNative")
288307
@GenerateAOT.Exclude
289308
static double readManaged(LLVMGlobalContainer self, long offset,
290-
@CachedLibrary("self") InteropLibrary interop,
291-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
292-
interop.toNative(self);
293-
return read.readDouble(self, offset);
309+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
310+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
311+
self.toNative(toNative);
312+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
313+
// We already know we'll be in the self.isPointer() case after toNative.
314+
return readNative(self, offset, location);
294315
}
295316
}
296317

@@ -304,6 +325,7 @@ static Assumption singleContextAssumption() {
304325
@Specialization(guards = "self.isPointer()")
305326
static long readNative(LLVMGlobalContainer self, long offset,
306327
@CachedLibrary("self") LLVMManagedReadLibrary location) {
328+
assert self.isPointer();
307329
return LLVMLanguage.get(location).getLLVMMemory().getI64(location, self.getAddress() + offset);
308330
}
309331

@@ -322,10 +344,12 @@ static Object readI64Managed(LLVMGlobalContainer self, long offset) {
322344
@Specialization(guards = {"!self.isPointer()", "offset != 0"})
323345
@GenerateAOT.Exclude
324346
static Object readFallback(LLVMGlobalContainer self, long offset,
325-
@CachedLibrary("self") InteropLibrary interop,
326-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
327-
interop.toNative(self);
328-
return read.readGenericI64(self, offset);
347+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
348+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
349+
self.toNative(toNative);
350+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
351+
// We already know we'll be in the self.isPointer() case after toNative.
352+
return readNative(self, offset, location);
329353
}
330354
}
331355

@@ -339,6 +363,7 @@ static Assumption singleContextAssumption() {
339363
@Specialization(guards = "self.isPointer()")
340364
static LLVMPointer readNative(LLVMGlobalContainer self, long offset,
341365
@CachedLibrary("self") LLVMManagedReadLibrary location) {
366+
assert self.isPointer();
342367
return LLVMLanguage.get(location).getLLVMMemory().getPointer(location, self.getAddress() + offset);
343368
}
344369

@@ -359,10 +384,12 @@ static LLVMPointer readManaged(LLVMGlobalContainer self, long offset,
359384
@Specialization(guards = {"!self.isPointer()", "offset != 0"})
360385
@GenerateAOT.Exclude
361386
static LLVMPointer readFallback(LLVMGlobalContainer self, long offset,
362-
@CachedLibrary("self") InteropLibrary interop,
363-
@CachedLibrary("self") LLVMManagedReadLibrary read) {
364-
interop.toNative(self);
365-
return read.readPointer(self, offset);
387+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
388+
@CachedLibrary("self") LLVMManagedReadLibrary location) {
389+
self.toNative(toNative);
390+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
391+
// We already know we'll be in the self.isPointer() case after toNative.
392+
return readNative(self, offset, location);
366393
}
367394
}
368395

@@ -372,16 +399,19 @@ static class WriteI8 {
372399
@Specialization(guards = "self.isPointer()")
373400
static void writeNative(LLVMGlobalContainer self, long offset, byte value,
374401
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
402+
assert self.isPointer();
375403
LLVMLanguage.get(location).getLLVMMemory().putI8(location, self.getAddress() + offset, value);
376404
}
377405

378-
@Specialization(guards = "!self.isPointer()")
406+
@Specialization(replaces = "writeNative")
379407
@GenerateAOT.Exclude
380408
static void writeManaged(LLVMGlobalContainer self, long offset, byte value,
381-
@CachedLibrary("self") InteropLibrary interop,
382-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
383-
interop.toNative(self);
384-
write.writeI8(self, offset, value);
409+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
410+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
411+
self.toNative(toNative);
412+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
413+
// We already know we'll be in the self.isPointer() case after toNative.
414+
writeNative(self, offset, value, location);
385415
}
386416
}
387417

@@ -391,16 +421,19 @@ static class WriteI16 {
391421
@Specialization(guards = "self.isPointer()")
392422
static void writeNative(LLVMGlobalContainer self, long offset, short value,
393423
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
424+
assert self.isPointer();
394425
LLVMLanguage.get(location).getLLVMMemory().putI16(location, self.getAddress() + offset, value);
395426
}
396427

397-
@Specialization(guards = "!self.isPointer()")
428+
@Specialization(replaces = "writeNative")
398429
@GenerateAOT.Exclude
399430
static void writeManaged(LLVMGlobalContainer self, long offset, short value,
400-
@CachedLibrary("self") InteropLibrary interop,
401-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
402-
interop.toNative(self);
403-
write.writeI16(self, offset, value);
431+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
432+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
433+
self.toNative(toNative);
434+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
435+
// We already know we'll be in the self.isPointer() case after toNative.
436+
writeNative(self, offset, value, location);
404437
}
405438
}
406439

@@ -410,16 +443,19 @@ static class WriteI32 {
410443
@Specialization(guards = "self.isPointer()")
411444
static void writeNative(LLVMGlobalContainer self, long offset, int value,
412445
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
446+
assert self.isPointer();
413447
LLVMLanguage.get(location).getLLVMMemory().putI32(location, self.getAddress() + offset, value);
414448
}
415449

416-
@Specialization(guards = "!self.isPointer()")
450+
@Specialization(replaces = "writeNative")
417451
@GenerateAOT.Exclude
418452
static void writeManaged(LLVMGlobalContainer self, long offset, int value,
419-
@CachedLibrary("self") InteropLibrary interop,
420-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
421-
interop.toNative(self);
422-
write.writeI32(self, offset, value);
453+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
454+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
455+
self.toNative(toNative);
456+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
457+
// We already know we'll be in the self.isPointer() case after toNative.
458+
writeNative(self, offset, value, location);
423459
}
424460
}
425461

@@ -429,16 +465,19 @@ static class WriteFloat {
429465
@Specialization(guards = "self.isPointer()")
430466
static void writeNative(LLVMGlobalContainer self, long offset, float value,
431467
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
468+
assert self.isPointer();
432469
LLVMLanguage.get(location).getLLVMMemory().putFloat(location, self.getAddress() + offset, value);
433470
}
434471

435-
@Specialization(guards = "!self.isPointer()")
472+
@Specialization(replaces = "writeNative")
436473
@GenerateAOT.Exclude
437474
static void writeManaged(LLVMGlobalContainer self, long offset, float value,
438-
@CachedLibrary("self") InteropLibrary interop,
439-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
440-
interop.toNative(self);
441-
write.writeFloat(self, offset, value);
475+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
476+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
477+
self.toNative(toNative);
478+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
479+
// We already know we'll be in the self.isPointer() case after toNative.
480+
writeNative(self, offset, value, location);
442481
}
443482
}
444483

@@ -448,16 +487,19 @@ static class WriteDouble {
448487
@Specialization(guards = "self.isPointer()")
449488
static void writeNative(LLVMGlobalContainer self, long offset, double value,
450489
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
490+
assert self.isPointer();
451491
LLVMLanguage.get(location).getLLVMMemory().putDouble(location, self.getAddress() + offset, value);
452492
}
453493

454-
@Specialization(guards = "!self.isPointer()")
494+
@Specialization(replaces = "writeNative")
455495
@GenerateAOT.Exclude
456496
static void writeManaged(LLVMGlobalContainer self, long offset, double value,
457-
@CachedLibrary("self") InteropLibrary interop,
458-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
459-
interop.toNative(self);
460-
write.writeDouble(self, offset, value);
497+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
498+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
499+
self.toNative(toNative);
500+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
501+
// We already know we'll be in the self.isPointer() case after toNative.
502+
writeNative(self, offset, value, location);
461503
}
462504
}
463505

@@ -471,6 +513,7 @@ static Assumption singleContextAssumption() {
471513
@Specialization(guards = "self.isPointer()")
472514
static void writeNative(LLVMGlobalContainer self, long offset, long value,
473515
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
516+
assert self.isPointer();
474517
LLVMLanguage.get(location).getLLVMMemory().putI64(location, self.getAddress() + offset, value);
475518
}
476519

@@ -498,10 +541,12 @@ static void writeManaged(LLVMGlobalContainer self, long offset, long value) {
498541
@Specialization(guards = {"!self.isPointer()", "offset != 0"})
499542
@GenerateAOT.Exclude
500543
static void writeFallback(LLVMGlobalContainer self, long offset, long value,
501-
@CachedLibrary("self") InteropLibrary interop,
502-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
503-
interop.toNative(self);
504-
write.writeI64(self, offset, value);
544+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
545+
@CachedLibrary("self") LLVMManagedWriteLibrary location) {
546+
self.toNative(toNative);
547+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
548+
// We already know we'll be in the self.isPointer() case after toNative.
549+
writeNative(self, offset, value, location);
505550
}
506551
}
507552

@@ -515,6 +560,7 @@ static Assumption singleContextAssumption() {
515560
@Specialization(limit = "3", guards = "self.isPointer()")
516561
static void writeNative(LLVMGlobalContainer self, long offset, Object value,
517562
@CachedLibrary("value") LLVMNativeLibrary toNative) {
563+
assert self.isPointer();
518564
long ptr = toNative.toNativePointer(value).asNative();
519565
LLVMLanguage.get(toNative).getLLVMMemory().putI64(toNative, self.getAddress() + offset, ptr);
520566
}
@@ -543,10 +589,12 @@ static void writeI64Managed(LLVMGlobalContainer self, long offset, Object value)
543589
@Specialization(guards = {"!self.isPointer()", "offset != 0"})
544590
@GenerateAOT.Exclude
545591
static void writeFallback(LLVMGlobalContainer self, long offset, Object value,
546-
@CachedLibrary("self") InteropLibrary interop,
547-
@CachedLibrary("self") LLVMManagedWriteLibrary write) {
548-
interop.toNative(self);
549-
write.writeGenericI64(self, offset, value);
592+
@Shared("toNative") @Cached LLVMToNativeNode toNative,
593+
@CachedLibrary("self") LLVMNativeLibrary nativeLib) {
594+
self.toNative(toNative);
595+
// Don't dispatch through the LLVMManagedReadLibrary again to break recursion.
596+
// We already know we'll be in the self.isPointer() case after toNative.
597+
writeNative(self, offset, value, nativeLib);
550598
}
551599
}
552600

0 commit comments

Comments
 (0)