[VM/AOT] Make trampolines look like free list elements to enable heap walking
Issue https://github.com/dart-lang/sdk/issues/33274
Change-Id: Ib6afdbc80012326134d409c4065a680d67de3ed8
Reviewed-on: https://dart-review.googlesource.com/c/90064
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index ef2d64a..83ff87c 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -20,6 +20,8 @@
false,
"Generate always trampolines (for testing purposes).");
+// The trampolines will have a 1-word object header in front of them.
+const intptr_t kOffsetInTrampoline = kWordSize;
const intptr_t kTrampolineSize = OS::kMaxPreferredCodeAlignment;
CodeRelocator::CodeRelocator(Thread* thread,
@@ -382,7 +384,8 @@
FindDestinationInText(callee, unresolved_trampoline->offset_into_target);
const int32_t distance = destination_text - trampoline_text_offset;
- PcRelativeTrampolineJumpPattern pattern(trampoline_start);
+ PcRelativeTrampolineJumpPattern pattern(trampoline_start +
+ kOffsetInTrampoline);
pattern.Initialize();
pattern.set_distance(distance);
ASSERT(pattern.distance() == distance);
@@ -396,6 +399,20 @@
forward_distance < PcRelativeCallPattern::kUpperCallingRange;
}
+static void MarkAsFreeListElement(uint8_t* trampoline_bytes,
+ intptr_t trampoline_length) {
+ uint32_t tags = 0;
+ tags = RawObject::SizeTag::update(trampoline_length, tags);
+ tags = RawObject::ClassIdTag::update(kFreeListElement, tags);
+ tags = RawObject::OldBit::update(true, tags);
+ tags = RawObject::OldAndNotMarkedBit::update(true, tags);
+ tags = RawObject::OldAndNotRememberedBit::update(true, tags);
+ tags = RawObject::NewBit::update(false, tags);
+
+ auto header_word = reinterpret_cast<uintptr_t*>(trampoline_bytes);
+ *header_word = tags;
+}
+
void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
while (!all_unresolved_calls_.IsEmpty()) {
UnresolvedCall* unresolved_call = all_unresolved_calls_.First();
@@ -407,7 +424,8 @@
const intptr_t future_boundary =
next_text_offset_ + max_instructions_size_ +
kTrampolineSize *
- (unresolved_calls_by_destination_.Length() + max_calls_);
+ (unresolved_calls_by_destination_.Length() + max_calls_) +
+ kOffsetInTrampoline;
if (IsTargetInRangeFor(unresolved_call, future_boundary) &&
!FLAG_always_generate_trampolines_for_testing) {
break;
@@ -440,12 +458,16 @@
// buffer.
auto trampoline_bytes = new uint8_t[kTrampolineSize];
memset(trampoline_bytes, 0x00, kTrampolineSize);
+ ASSERT((kOffsetInTrampoline +
+ PcRelativeTrampolineJumpPattern::kLengthInBytes) <
+ kTrampolineSize);
auto unresolved_trampoline = new UnresolvedTrampoline{
unresolved_call->callee,
unresolved_call->offset_into_target,
trampoline_bytes,
- next_text_offset_,
+ next_text_offset_ + kOffsetInTrampoline,
};
+ MarkAsFreeListElement(trampoline_bytes, kTrampolineSize);
AddTrampolineToText(callee, trampoline_bytes, kTrampolineSize);
EnqueueUnresolvedTrampoline(unresolved_trampoline);
trampoline_text_offset = unresolved_trampoline->text_offset;
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 8cc2add..e2848d3 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -639,15 +639,6 @@
}
bool Heap::Verify(MarkExpectation mark_expectation) const {
-#if defined(DART_PRECOMPILED_RUNTIME)
- // We cannot simply walk the heap pages which contain instructions, because
- // they also contain trampolines inserted during AOT compilation time.
- const bool have_bare_trampolines =
- FLAG_precompiled_mode && FLAG_use_bare_instructions;
- if (have_bare_trampolines) {
- return true;
- }
-#endif
HeapIterationScope heap_iteration_scope(Thread::Current());
return VerifyGC(mark_expectation);
}
diff --git a/runtime/vm/instructions_x64.h b/runtime/vm/instructions_x64.h
index b41a95d..056f48f 100644
--- a/runtime/vm/instructions_x64.h
+++ b/runtime/vm/instructions_x64.h
@@ -157,6 +157,8 @@
// allow testing of trampolines on X64 we have it nonetheless)
class PcRelativeTrampolineJumpPattern : public ValueObject {
public:
+ static const int kLengthInBytes = 5;
+
explicit PcRelativeTrampolineJumpPattern(uword pattern_start)
: pattern_start_(pattern_start) {}
@@ -181,8 +183,6 @@
}
private:
- static const int kLengthInBytes = 5;
-
uword pattern_start_;
};