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 ;
@@ -433,15 +434,15 @@ public void transferFrame(FrameWithoutBoxing source, FrameWithoutBoxing target,
433
434
434
435
OptimizedRuntimeAccessor .ACCESSOR .startOSRFrameTransfer (target );
435
436
// Transfer indexed frame slots
436
- transferLoop (description .indexedFrameTags . length , source , target , description . indexedFrameTags );
437
+ transferLoop (description .indexedFrameTags , source , target );
437
438
// transfer auxiliary slots
438
439
transferAuxiliarySlots (source , target , state );
439
440
}
440
441
441
442
/**
442
443
* Transfer state from {@code source} to {@code target}. Can be used to transfer state from an
443
444
* OSR frame to a parent frame. Overall less efficient than its
444
- * {@link #transferFrame(FrameWithoutBoxing, FrameWithoutBoxing, int , Object) counterpart},
445
+ * {@link #transferFrame(FrameWithoutBoxing, FrameWithoutBoxing, long , Object) counterpart},
445
446
* mainly due to not being able to speculate on the source tags: While entering bytecode OSR is
446
447
* done through specific entry points (likely back edges), returning could be done from anywhere
447
448
* within a method body (through regular returns, or exception thrown).
@@ -483,10 +484,11 @@ public void restoreFrame(FrameWithoutBoxing source, FrameWithoutBoxing target) {
483
484
// The frames should use the same descriptor.
484
485
validateDescriptors (source , target , state );
485
486
486
- // We can't reasonably have constant expected tags for parent frame restoration.
487
+ // We can't reasonably have constant expected tags for parent frame restoration. We pass
488
+ // state.frameDescriptor to restoreLoop in order to correctly account for static slots.
487
489
488
490
// transfer indexed frame slots
489
- transferLoop (state .frameDescriptor . getNumberOfSlots () , source , target , null );
491
+ restoreLoop (state .frameDescriptor , source , target );
490
492
// transfer auxiliary slots
491
493
transferAuxiliarySlots (source , target , state );
492
494
}
@@ -506,26 +508,23 @@ private static void validateDescriptors(FrameWithoutBoxing source, FrameWithoutB
506
508
}
507
509
508
510
/**
509
- * Common transfer loop for copying over legacy frame slot or indexed slots from a source frame
510
- * to a target frame.
511
+ * Transfer loop for copying over indexed frame slots from a source parent frame to a target OSR
512
+ * frame.
511
513
*
512
- * @param length Number of slots to transfer. Must be
513
- * {@link CompilerDirectives#isCompilationConstant(Object) compilation constant}
514
+ * @param expectedTags The array of tags the source is expected to have. If compilation
515
+ * constant, frame slot accesses may be simplified.
514
516
* @param source The frame to copy from
515
517
* @param target The frame to copy to
516
- * @param expectedTags The array of tags the source is expected to have, or null if no previous
517
- * knowledge of tags was collected. If compilation constant, frame slot accesses may
518
- * be simplified.
519
518
*/
520
519
@ ExplodeLoop
521
520
private static void transferLoop (
522
- int length ,
523
- FrameWithoutBoxing source , FrameWithoutBoxing target ,
524
- byte [] expectedTags ) {
521
+ byte [] expectedTags ,
522
+ FrameWithoutBoxing source , FrameWithoutBoxing target ) {
523
+ CompilerAsserts . partialEvaluationConstant ( expectedTags . length );
525
524
int i = 0 ;
526
- while (i < length ) {
525
+ while (i < expectedTags . length ) {
527
526
byte actualTag = source .getTag (i );
528
- byte expectedTag = expectedTags == null ? actualTag : expectedTags [i ];
527
+ byte expectedTag = expectedTags [i ];
529
528
530
529
if (expectedTag == FrameWithoutBoxing .STATIC_TAG ) {
531
530
// Here we can skip incompatible tag check in case of static slot since the frame
@@ -547,6 +546,33 @@ private static void transferLoop(
547
546
}
548
547
}
549
548
549
+ /**
550
+ * Transfer loop for copying over indexed frame slots from a source OSR frame to a target parent
551
+ * frame.
552
+ *
553
+ * @param frameDescriptor The common frame descriptor of source and target
554
+ * @param source The frame to copy from
555
+ * @param target The frame to copy to
556
+ */
557
+ private static void restoreLoop (
558
+ FrameDescriptor frameDescriptor ,
559
+ FrameWithoutBoxing source , FrameWithoutBoxing target ) {
560
+ CompilerAsserts .neverPartOfCompilation ();
561
+ for (int i = 0 ; i < frameDescriptor .getNumberOfSlots (); i ++) {
562
+ byte tag = source .getTag (i );
563
+
564
+ if (tag == 0 && frameDescriptor .getSlotKind (i ) == FrameSlotKind .Static ) {
565
+ // When using static slots, the tags might never be initialized. We cannot rely
566
+ // solely on the source frame instance tags in order to detect static slots and
567
+ // distinguish them from non-static Object-type slots. Hence, if the tag is 0, we
568
+ // check the FrameDescriptor whether the slot has a static kind.
569
+ tag = FrameWithoutBoxing .STATIC_TAG ;
570
+ }
571
+
572
+ transferIndexedFrameSlot (source , target , i , tag );
573
+ }
574
+ }
575
+
550
576
@ ExplodeLoop
551
577
private static void transferAuxiliarySlots (FrameWithoutBoxing source , FrameWithoutBoxing target , LazyState state ) {
552
578
for (int auxSlot = 0 ; auxSlot < state .frameDescriptor .getNumberOfAuxiliarySlots (); auxSlot ++) {
0 commit comments