7474import com .oracle .svm .core .heap .Heap ;
7575import com .oracle .svm .core .imagelayer .ImageLayerBuildingSupport ;
7676import com .oracle .svm .core .imagelayer .ImageLayerSection ;
77+ import com .oracle .svm .core .jdk .UninterruptibleUtils ;
7778import com .oracle .svm .core .os .AbstractImageHeapProvider ;
7879import com .oracle .svm .core .os .VirtualMemoryProvider ;
7980import com .oracle .svm .core .os .VirtualMemoryProvider .Access ;
8485import com .oracle .svm .core .util .PointerUtils ;
8586import com .oracle .svm .core .util .UnsignedUtils ;
8687import com .oracle .svm .core .util .VMError ;
88+ import com .oracle .svm .hosted .imagelayer .ImageLayerSectionFeature ;
89+ import com .oracle .svm .hosted .imagelayer .LayeredDispatchTableFeature ;
8790
8891import jdk .graal .compiler .nodes .NamedLocationIdentity ;
8992import jdk .graal .compiler .nodes .PauseNode ;
90- import jdk .graal .compiler .replacements .nodes .CountTrailingZerosNode ;
9193import jdk .graal .compiler .word .Word ;
9294
9395/**
@@ -133,7 +135,7 @@ private static final class ImageHeapPatchingState {
133135 static final Word SUCCESSFUL = Word .unsigned (2 );
134136 }
135137
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 );
137139
138140 @ Uninterruptible (reason = "Called from uninterruptible code." , mayBeInlined = true )
139141 private static UnsignedWord getLayeredImageHeapAddressSpaceSize () {
@@ -228,17 +230,22 @@ protected int initializeLayeredImage(Pointer firstHeapStart, Pointer selfReserve
228230 return result ;
229231 }
230232
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+ */
231238 @ Uninterruptible (reason = "Thread state not yet set up." )
232239 public static void patchLayeredImageHeap () {
233240 Word heapPatchStateAddr = IMAGE_HEAP_PATCHING_STATE .get ();
234241 boolean firstIsolate = heapPatchStateAddr .logicCompareAndSwapWord (0 , ImageHeapPatchingState .UNINITIALIZED , ImageHeapPatchingState .IN_PROGRESS , NamedLocationIdentity .OFF_HEAP_LOCATION );
235242
236243 if (!firstIsolate ) {
237244 // spin-wait for first isolate
238- Word state = heapPatchStateAddr .readWordVolatile (0 , LocationIdentity . ANY_LOCATION );
245+ Word state = heapPatchStateAddr .readWordVolatile (0 , NamedLocationIdentity . OFF_HEAP_LOCATION );
239246 while (state .equal (ImageHeapPatchingState .IN_PROGRESS )) {
240247 PauseNode .pause ();
241- state = heapPatchStateAddr .readWordVolatile (0 , LocationIdentity . ANY_LOCATION );
248+ state = heapPatchStateAddr .readWordVolatile (0 , NamedLocationIdentity . OFF_HEAP_LOCATION );
242249 }
243250
244251 /* Patching has already been successfully completed, nothing needs to be done. */
@@ -254,19 +261,24 @@ public static void patchLayeredImageHeap() {
254261 Pointer data = layerSection .add (ImageLayerSection .getEntryOffset (VARIABLY_SIZED_DATA ));
255262 int offset = 0 ;
256263
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 );
261265
266+ /* Patch code offsets to become relative to the code base. */
262267 Pointer layerHeapRelocs = layerSection .readWord (ImageLayerSection .getEntryOffset (HEAP_RELOCATABLE_BEGIN ));
263268 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+ */
264274 Word layerCodeOffsetToBase = (Word ) layerCode .subtract (codeBase );
265275 offset = applyLayerCodePointerPatches (data , offset , layerHeapRelocs , layerCodeOffsetToBase );
266276
277+ /* Patch absolute addresses to become relative to the code base. */
267278 Word negativeCodeBase = Word .<Word > zero ().subtract (codeBase );
268279 offset = applyLayerCodePointerPatches (data , offset , layerHeapRelocs , negativeCodeBase );
269280
281+ /* Patch references in the image heap. */
270282 applyLayerImageHeapRefPatches (data .add (offset ), initialLayerImageHeap );
271283
272284 layerSection = layerSection .readWord (ImageLayerSection .getEntryOffset (NEXT_SECTION ));
@@ -275,14 +287,23 @@ public static void patchLayeredImageHeap() {
275287 heapPatchStateAddr .writeWordVolatile (0 , ImageHeapPatchingState .SUCCESSFUL );
276288 }
277289
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+
278297 @ Uninterruptible (reason = "Thread state not yet set up." )
279298 private static int applyLayerCodePointerPatches (Pointer data , int startOffset , Pointer layerHeapRelocs , Word addend ) {
280299 int wordSize = ConfigurationValues .getTarget ().wordSize ;
281300
282301 int offset = startOffset ;
283- int bitmapWordCount = (int ) data .readLong (offset );
302+ long bitmapWordCountAsLong = data .readLong (offset );
303+ int bitmapWordCount = UninterruptibleUtils .NumUtil .safeToInt (bitmapWordCountAsLong );
284304 offset += Long .BYTES ;
285305 if (addend .equal (0 )) {
306+ /* Nothing to do. */
286307 offset += bitmapWordCount * Long .BYTES ;
287308 return offset ;
288309 }
@@ -292,7 +313,7 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
292313 offset += Long .BYTES ;
293314 int j = 0 ; // index of a 1-bit
294315 while (bits != 0 ) {
295- int ntz = CountTrailingZerosNode . countLongTrailingZeros (bits );
316+ int ntz = UninterruptibleUtils . Long . countTrailingZeros (bits );
296317 j += ntz ;
297318
298319 int at = (i * 64 + j ) * wordSize ;
@@ -301,11 +322,8 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
301322 layerHeapRelocs .writeWord (at , w );
302323
303324 /*
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.
309327 */
310328 bits = (bits >>> ntz ) >>> 1 ;
311329 j ++;
@@ -317,7 +335,8 @@ private static int applyLayerCodePointerPatches(Pointer data, int startOffset, P
317335 @ Uninterruptible (reason = "Thread state not yet set up." )
318336 private static void applyLayerImageHeapRefPatches (Pointer patches , Pointer layerImageHeap ) {
319337 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 );
321340 int offset = Long .BYTES ;
322341 int endOffset = offset + count * Integer .BYTES ;
323342 while (offset < endOffset ) {
0 commit comments