Index: src/objects-debug.cc |
diff --git a/src/objects-debug.cc b/src/objects-debug.cc |
index 5babfdf1a7f434ce341a735b9daf1f9ee61813a5..3a2ec3e559a16863db44acfcbce63a72cc9762aa 100644 |
--- a/src/objects-debug.cc |
+++ b/src/objects-debug.cc |
@@ -1277,6 +1277,57 @@ void Code::VerifyEmbeddedObjects(VerifyMode mode) { |
} |
+// Verify that the debugger can redirect old code to the new code. |
+void Code::VerifyRecompiledCode(Code* old_code, Code* new_code) { |
+ if (old_code->kind() != FUNCTION) return; |
+ if (new_code->kind() != FUNCTION) return; |
+ static const int mask = RelocInfo::kCodeTargetMask; |
+ |
+ Isolate* isolate = old_code->GetIsolate(); |
+ RelocIterator old_it(old_code, mask); |
+ RelocIterator new_it(new_code, mask); |
+ Code* stack_check = isolate->builtins()->builtin(Builtins::kStackCheck); |
+ |
+ while (!old_it.done()) { |
+ RelocInfo* rinfo = old_it.rinfo(); |
+ Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
+ if (target == stack_check) break; |
+ old_it.next(); |
+ } |
+ |
+ while (!new_it.done()) { |
+ RelocInfo* rinfo = new_it.rinfo(); |
+ Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
+ CHECK(!target->is_handler() && !target->is_inline_cache_stub()); |
+ if (target == stack_check) break; |
+ new_it.next(); |
+ } |
+ |
+ // Either both are done because there is no stack check. |
+ // Or we are past the prologue for both. |
+ CHECK_EQ(new_it.done(), old_it.done()); |
+ |
+ // After the prologue, each call in the old code has a corresponding call |
+ // in the new code. |
+ while (!old_it.done() && !new_it.done()) { |
+ Code* old_target = |
+ Code::GetCodeFromTargetAddress(old_it.rinfo()->target_address()); |
+ Code* new_target = |
+ Code::GetCodeFromTargetAddress(new_it.rinfo()->target_address()); |
+ CHECK_EQ(old_target->kind(), new_target->kind()); |
+ if (!old_target->is_handler() && !old_target->is_inline_cache_stub()) { |
+ CHECK_EQ(old_target, new_target); |
+ } |
+ old_it.next(); |
+ new_it.next(); |
+ } |
+ |
+ // Both are done at the same time. |
+ CHECK_EQ(new_it.done(), old_it.done()); |
+} |
+ |
+ |
#endif // DEBUG |
} // namespace internal |