Index: runtime/vm/stack_frame.cc |
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc |
index 28636b8ff9208da680185e95dc8b3ef7ae056795..827407d72e91e07d5277f2d18862538481553d52 100644 |
--- a/runtime/vm/stack_frame.cc |
+++ b/runtime/vm/stack_frame.cc |
@@ -89,7 +89,6 @@ void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
ASSERT(thread() == Thread::Current()); |
ASSERT(visitor != NULL); |
-#if !defined(TARGET_ARCH_DBC) |
// NOTE: This code runs while GC is in progress and runs within |
// a NoHandleScope block. Hence it is not ok to use regular Zone or |
// Scope handles. We use direct stack handles, the raw pointers in |
@@ -113,6 +112,7 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
Instructions::HeaderSize(); |
map = code.GetStackmap(pc() - entry, &maps, &map); |
if (!map.IsNull()) { |
+#if !defined(TARGET_ARCH_DBC) |
RawObject** first = reinterpret_cast<RawObject**>(sp()); |
RawObject** last = reinterpret_cast<RawObject**>( |
fp() + (kFirstLocalSlotFromFp * kWordSize)); |
@@ -157,24 +157,59 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
last = reinterpret_cast<RawObject**>( |
fp() + (kFirstObjectSlotFromFp * kWordSize)); |
visitor->VisitPointers(first, last); |
+#else |
+ RawObject** first = reinterpret_cast<RawObject**>(fp()); |
+ RawObject** last = reinterpret_cast<RawObject**>(sp()); |
+ |
+ // Visit fixed prefix of the frame. |
+ ASSERT((first + kFirstObjectSlotFromFp) < first); |
+ visitor->VisitPointers(first + kFirstObjectSlotFromFp, first - 1); |
+ |
+ // A stack map is present in the code object, use the stack map to |
+ // visit frame slots which are marked as having objects. |
+ // |
+ // The layout of the frame is (lower addresses to the left): |
+ // | registers | outgoing arguments | |
+ // |XXXXXXXXXXX|--------------------| |
+ // |
+ // The DBC registers are described in the stack map. |
+ // The outgoing arguments are assumed to be tagged; the number |
+ // of outgoing arguments is not explicitly tracked. |
+ ASSERT(map.SlowPathBitCount() == 0); |
+ |
+ // Visit DBC registers that contain tagged values. |
+ intptr_t length = map.Length(); |
+ for (intptr_t bit = 0; bit < length; ++bit) { |
+ if (map.IsObject(bit)) { |
+ visitor->VisitPointer(first + bit); |
+ } |
+ } |
+ |
+ // Visit outgoing arguments. |
+ if ((first + length) <= last) { |
+ visitor->VisitPointers(first + length, last); |
+ } |
+#endif // !defined(TARGET_ARCH_DBC) |
return; |
} |
// No stack map, fall through. |
} |
+ |
+#if !defined(TARGET_ARCH_DBC) |
// For normal unoptimized Dart frames and Stub frames each slot |
// between the first and last included are tagged objects. |
RawObject** first = reinterpret_cast<RawObject**>(sp()); |
RawObject** last = reinterpret_cast<RawObject**>( |
fp() + (kFirstObjectSlotFromFp * kWordSize)); |
- visitor->VisitPointers(first, last); |
#else |
// On DBC stack grows upwards: fp() <= sp(). |
RawObject** first = reinterpret_cast<RawObject**>( |
fp() + (kFirstObjectSlotFromFp * kWordSize)); |
RawObject** last = reinterpret_cast<RawObject**>(sp()); |
- visitor->VisitPointers(first, last); |
#endif // !defined(TARGET_ARCH_DBC) |
+ |
+ visitor->VisitPointers(first, last); |
} |