52
52
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
53
53
import com .oracle .truffle .api .TruffleLanguage ;
54
54
import com .oracle .truffle .api .frame .FrameDescriptor ;
55
+ import com .oracle .truffle .api .frame .FrameSlotKind ;
55
56
import com .oracle .truffle .api .frame .FrameSlotTypeException ;
56
57
import com .oracle .truffle .api .frame .VirtualFrame ;
57
58
import com .oracle .truffle .api .impl .FrameWithoutBoxing ;
@@ -414,15 +415,15 @@ public void transferFrame(FrameWithoutBoxing source, FrameWithoutBoxing target,
414
415
415
416
OptimizedRuntimeAccessor .ACCESSOR .startOSRFrameTransfer (target );
416
417
// Transfer indexed frame slots
417
- transferLoop (description .indexedFrameTags . length , source , target , description . indexedFrameTags );
418
+ transferLoop (description .indexedFrameTags , source , target );
418
419
// transfer auxiliary slots
419
420
transferAuxiliarySlots (source , target , state );
420
421
}
421
422
422
423
/**
423
424
* Transfer state from {@code source} to {@code target}. Can be used to transfer state from an
424
425
* OSR frame to a parent frame. Overall less efficient than its
425
- * {@link #transferFrame(FrameWithoutBoxing, FrameWithoutBoxing, int , Object) counterpart},
426
+ * {@link #transferFrame(FrameWithoutBoxing, FrameWithoutBoxing, long , Object) counterpart},
426
427
* mainly due to not being able to speculate on the source tags: While entering bytecode OSR is
427
428
* done through specific entry points (likely back edges), returning could be done from anywhere
428
429
* within a method body (through regular returns, or exception thrown).
@@ -464,10 +465,11 @@ public void restoreFrame(FrameWithoutBoxing source, FrameWithoutBoxing target) {
464
465
// The frames should use the same descriptor.
465
466
validateDescriptors (source , target , state );
466
467
467
- // We can't reasonably have constant expected tags for parent frame restoration.
468
+ // We can't reasonably have constant expected tags for parent frame restoration. We pass
469
+ // state.frameDescriptor to restoreLoop in order to correctly account for static slots.
468
470
469
471
// transfer indexed frame slots
470
- transferLoop (state .frameDescriptor . getNumberOfSlots () , source , target , null );
472
+ restoreLoop (state .frameDescriptor , source , target );
471
473
// transfer auxiliary slots
472
474
transferAuxiliarySlots (source , target , state );
473
475
}
@@ -487,26 +489,23 @@ private static void validateDescriptors(FrameWithoutBoxing source, FrameWithoutB
487
489
}
488
490
489
491
/**
490
- * Common transfer loop for copying over legacy frame slot or indexed slots from a source frame
491
- * to a target frame.
492
+ * Transfer loop for copying over indexed frame slots from a source parent frame to a target OSR
493
+ * frame.
492
494
*
493
- * @param length Number of slots to transfer. Must be
494
- * {@link CompilerDirectives#isCompilationConstant(Object) compilation constant}
495
+ * @param expectedTags The array of tags the source is expected to have. If compilation
496
+ * constant, frame slot accesses may be simplified.
495
497
* @param source The frame to copy from
496
498
* @param target The frame to copy to
497
- * @param expectedTags The array of tags the source is expected to have, or null if no previous
498
- * knowledge of tags was collected. If compilation constant, frame slot accesses may
499
- * be simplified.
500
499
*/
501
500
@ ExplodeLoop
502
501
private static void transferLoop (
503
- int length ,
504
- FrameWithoutBoxing source , FrameWithoutBoxing target ,
505
- byte [] expectedTags ) {
502
+ byte [] expectedTags ,
503
+ FrameWithoutBoxing source , FrameWithoutBoxing target ) {
504
+ CompilerAsserts . partialEvaluationConstant ( expectedTags . length );
506
505
int i = 0 ;
507
- while (i < length ) {
506
+ while (i < expectedTags . length ) {
508
507
byte actualTag = source .getTag (i );
509
- byte expectedTag = expectedTags == null ? actualTag : expectedTags [i ];
508
+ byte expectedTag = expectedTags [i ];
510
509
511
510
boolean incompatibleTags = expectedTag != actualTag ;
512
511
if (incompatibleTags ) {
@@ -521,6 +520,33 @@ private static void transferLoop(
521
520
}
522
521
}
523
522
523
+ /**
524
+ * Transfer loop for copying over indexed frame slots from a source OSR frame to a target parent
525
+ * frame.
526
+ *
527
+ * @param frameDescriptor The common frame descriptor of source and target
528
+ * @param source The frame to copy from
529
+ * @param target The frame to copy to
530
+ */
531
+ private static void restoreLoop (
532
+ FrameDescriptor frameDescriptor ,
533
+ FrameWithoutBoxing source , FrameWithoutBoxing target ) {
534
+ CompilerAsserts .neverPartOfCompilation ();
535
+ for (int i = 0 ; i < frameDescriptor .getNumberOfSlots (); i ++) {
536
+ byte tag = source .getTag (i );
537
+
538
+ if (tag == 0 && frameDescriptor .getSlotKind (i ) == FrameSlotKind .Static ) {
539
+ // When using static slots, the tags might never be initialized. We cannot rely
540
+ // solely on the source frame instance tags in order to detect static slots and
541
+ // distinguish them from non-static Object-type slots. Hence, if the tag is 0, we
542
+ // check the FrameDescriptor whether the slot has a static kind.
543
+ tag = FrameWithoutBoxing .STATIC_TAG ;
544
+ }
545
+
546
+ transferIndexedFrameSlot (source , target , i , tag );
547
+ }
548
+ }
549
+
524
550
@ ExplodeLoop
525
551
private static void transferAuxiliarySlots (FrameWithoutBoxing source , FrameWithoutBoxing target , LazyState state ) {
526
552
for (int auxSlot = 0 ; auxSlot < state .frameDescriptor .getNumberOfAuxiliarySlots (); auxSlot ++) {
0 commit comments