74
74
import com .oracle .svm .core .heap .Heap ;
75
75
import com .oracle .svm .core .imagelayer .ImageLayerBuildingSupport ;
76
76
import com .oracle .svm .core .imagelayer .ImageLayerSection ;
77
+ import com .oracle .svm .core .jdk .UninterruptibleUtils ;
77
78
import com .oracle .svm .core .os .AbstractImageHeapProvider ;
78
79
import com .oracle .svm .core .os .VirtualMemoryProvider ;
79
80
import com .oracle .svm .core .os .VirtualMemoryProvider .Access ;
84
85
import com .oracle .svm .core .util .PointerUtils ;
85
86
import com .oracle .svm .core .util .UnsignedUtils ;
86
87
import com .oracle .svm .core .util .VMError ;
88
+ import com .oracle .svm .hosted .imagelayer .ImageLayerSectionFeature ;
89
+ import com .oracle .svm .hosted .imagelayer .LayeredDispatchTableFeature ;
87
90
88
91
import jdk .graal .compiler .nodes .NamedLocationIdentity ;
89
92
import jdk .graal .compiler .nodes .PauseNode ;
90
- import jdk .graal .compiler .replacements .nodes .CountTrailingZerosNode ;
91
93
import jdk .graal .compiler .word .Word ;
92
94
93
95
/**
@@ -133,7 +135,7 @@ private static final class ImageHeapPatchingState {
133
135
static final Word SUCCESSFUL = Word .unsigned (2 );
134
136
}
135
137
136
- private static final CGlobalData <Word > IMAGE_HEAP_PATCHING_STATE = CGlobalDataFactory .createWord ();
138
+ private static final CGlobalData <Word > IMAGE_HEAP_PATCHING_STATE = CGlobalDataFactory .createWord (ImageHeapPatchingState . UNINITIALIZED );
137
139
138
140
@ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
139
141
private static UnsignedWord getLayeredImageHeapAddressSpaceSize () {
@@ -228,17 +230,22 @@ protected int initializeLayeredImage(Pointer firstHeapStart, Pointer selfReserve
228
230
return result ;
229
231
}
230
232
233
+ /**
234
+ * Apply patches to the image heap as specified by each layer. See {@link ImageLayerSection} and
235
+ * {@link ImageLayerSectionFeature} for the layout of the section that contains the patches and
236
+ * {@link LayeredDispatchTableFeature} where code patches are gathered.
237
+ */
231
238
@ Uninterruptible (reason = "Thread state not yet set up." )
232
239
public static void patchLayeredImageHeap () {
233
240
Word heapPatchStateAddr = IMAGE_HEAP_PATCHING_STATE .get ();
234
241
boolean firstIsolate = heapPatchStateAddr .logicCompareAndSwapWord (0 , ImageHeapPatchingState .UNINITIALIZED , ImageHeapPatchingState .IN_PROGRESS , NamedLocationIdentity .OFF_HEAP_LOCATION );
235
242
236
243
if (!firstIsolate ) {
237
244
// spin-wait for first isolate
238
- Word state = heapPatchStateAddr .readWordVolatile (0 , LocationIdentity . ANY_LOCATION );
245
+ Word state = heapPatchStateAddr .readWordVolatile (0 , NamedLocationIdentity . OFF_HEAP_LOCATION );
239
246
while (state .equal (ImageHeapPatchingState .IN_PROGRESS )) {
240
247
PauseNode .pause ();
241
- state = heapPatchStateAddr .readWordVolatile (0 , LocationIdentity . ANY_LOCATION );
248
+ state = heapPatchStateAddr .readWordVolatile (0 , NamedLocationIdentity . OFF_HEAP_LOCATION );
242
249
}
243
250
244
251
/* Patching has already been successfully completed, nothing needs to be done. */
@@ -254,19 +261,24 @@ public static void patchLayeredImageHeap() {
254
261
Pointer data = layerSection .add (ImageLayerSection .getEntryOffset (VARIABLY_SIZED_DATA ));
255
262
int offset = 0 ;
256
263
257
- // Skip singletons table
258
- long singletonTableEntryCount = data .readLong (offset );
259
- UnsignedWord singletonTableAlignedSize = roundUp (unsigned (singletonTableEntryCount * referenceSize ), unsigned (Long .BYTES ));
260
- offset += Long .BYTES + (int ) singletonTableAlignedSize .rawValue ();
264
+ offset = skipSingletonsTable (data , offset , referenceSize );
261
265
266
+ /* Patch code offsets to become relative to the code base. */
262
267
Pointer layerHeapRelocs = layerSection .readWord (ImageLayerSection .getEntryOffset (HEAP_RELOCATABLE_BEGIN ));
263
268
Pointer layerCode = layerSection .readWord (ImageLayerSection .getEntryOffset (CODE_START ));
269
+ /*
270
+ * Note that the code base can be above the layer's code section, in which case the
271
+ * subtraction underflows and the additions of code address computations overflow,
272
+ * giving the correct result.
273
+ */
264
274
Word layerCodeOffsetToBase = (Word ) layerCode .subtract (codeBase );
265
275
offset = applyLayerCodePointerPatches (data , offset , layerHeapRelocs , layerCodeOffsetToBase );
266
276
277
+ /* Patch absolute addresses to become relative to the code base. */
267
278
Word negativeCodeBase = Word .<Word > zero ().subtract (codeBase );
268
279
offset = applyLayerCodePointerPatches (data , offset , layerHeapRelocs , negativeCodeBase );
269
280
281
+ /* Patch references in the image heap. */
270
282
applyLayerImageHeapRefPatches (data .add (offset ), initialLayerImageHeap );
271
283
272
284
layerSection = layerSection .readWord (ImageLayerSection .getEntryOffset (NEXT_SECTION ));
@@ -275,14 +287,23 @@ public static void patchLayeredImageHeap() {
275
287
heapPatchStateAddr .writeWordVolatile (0 , ImageHeapPatchingState .SUCCESSFUL );
276
288
}
277
289
290
+ @ Uninterruptible (reason = "Thread state not yet set up." )
291
+ private static int skipSingletonsTable (Pointer data , int offset , int referenceSize ) {
292
+ long singletonTableEntryCount = data .readLong (offset );
293
+ UnsignedWord singletonTableAlignedSize = roundUp (unsigned (singletonTableEntryCount * referenceSize ), unsigned (Long .BYTES ));
294
+ return offset + Long .BYTES + UnsignedUtils .safeToInt (singletonTableAlignedSize );
295
+ }
296
+
278
297
@ Uninterruptible (reason = "Thread state not yet set up." )
279
298
private static int applyLayerCodePointerPatches (Pointer data , int startOffset , Pointer layerHeapRelocs , Word addend ) {
280
299
int wordSize = ConfigurationValues .getTarget ().wordSize ;
281
300
282
301
int offset = startOffset ;
283
- int bitmapWordCount = (int ) data .readLong (offset );
302
+ long bitmapWordCountAsLong = data .readLong (offset );
303
+ int bitmapWordCount = UninterruptibleUtils .NumUtil .safeToInt (bitmapWordCountAsLong );
284
304
offset += Long .BYTES ;
285
305
if (addend .equal (0 )) {
306
+ /* Nothing to do. */
286
307
offset += bitmapWordCount * Long .BYTES ;
287
308
return offset ;
288
309
}
@@ -292,7 +313,7 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
292
313
offset += Long .BYTES ;
293
314
int j = 0 ; // index of a 1-bit
294
315
while (bits != 0 ) {
295
- int ntz = CountTrailingZerosNode . countLongTrailingZeros (bits );
316
+ int ntz = UninterruptibleUtils . Long . countTrailingZeros (bits );
296
317
j += ntz ;
297
318
298
319
int at = (i * 64 + j ) * wordSize ;
@@ -301,11 +322,8 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
301
322
layerHeapRelocs .writeWord (at , w );
302
323
303
324
/*
304
- * Note that we must not shift by ntz+1 here because it can be 64, and according to
305
- * the Java Language Specification, 15.19. Shift Operators: If the promoted type of
306
- * the left-hand operand is long, then only the six lowest-order bits of the
307
- * right-hand operand are used as the shift distance. [..] The shift distance
308
- * actually used is therefore always in the range 0 to 63, inclusive.
325
+ * Note that we must not shift by ntz+1 here because it can be 64, which would be a
326
+ * no-op according to the Java Language Specification, 15.19. Shift Operators.
309
327
*/
310
328
bits = (bits >>> ntz ) >>> 1 ;
311
329
j ++;
@@ -317,7 +335,8 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
317
335
@ Uninterruptible (reason = "Thread state not yet set up." )
318
336
private static void applyLayerImageHeapRefPatches (Pointer patches , Pointer layerImageHeap ) {
319
337
int referenceSize = ConfigurationValues .getObjectLayout ().getReferenceSize ();
320
- int count = (int ) patches .readLong (0 );
338
+ long countAsLong = patches .readLong (0 );
339
+ int count = UninterruptibleUtils .NumUtil .safeToInt (countAsLong );
321
340
int offset = Long .BYTES ;
322
341
int endOffset = offset + count * Integer .BYTES ;
323
342
while (offset < endOffset ) {
0 commit comments