[vm] Adjust concurrent marker to re-enable code W^X.
Bug: https://github.com/dart-lang/sdk/issues/34002
Change-Id: I53081e8a19b21804bee776ecab0779c723907008
Reviewed-on: https://dart-review.googlesource.com/c/85624
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index f0ec1db..3546b60 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -10,7 +10,7 @@
namespace dart {
-DEFINE_FLAG(bool, write_protect_code, false, "Write protect jitted code");
+DEFINE_FLAG(bool, write_protect_code, true, "Write protect jitted code");
WritableInstructionsScope::WritableInstructionsScope(uword address,
intptr_t size)
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 3145090..7d5ac17 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -260,8 +260,7 @@
if (class_id != kWeakPropertyCid) {
size = raw_obj->VisitPointersNonvirtual(this);
} else {
- RawWeakProperty* raw_weak =
- reinterpret_cast<RawWeakProperty*>(raw_obj);
+ RawWeakProperty* raw_weak = static_cast<RawWeakProperty*>(raw_obj);
size = ProcessWeakProperty(raw_weak);
}
marked_bytes_ += size;
@@ -315,8 +314,20 @@
return raw_weak->VisitPointersNonvirtual(this);
}
+ void FinalizeInstructions() {
+ while (!delayed_instructions_.is_empty()) {
+ RawInstructions* instr = delayed_instructions_.RemoveLast();
+ if (TryAcquireMarkBit(instr)) {
+ intptr_t size = instr->Size();
+ marked_bytes_ += size;
+ NOT_IN_PRODUCT(UpdateLiveOld(kInstructionsCid, size));
+ }
+ }
+ }
+
// Called when all marking is complete.
void Finalize() {
+ ASSERT(delayed_instructions_.is_empty());
work_list_.Finalize();
// Detach code from functions.
if (skipped_code_functions_ != NULL) {
@@ -370,7 +381,15 @@
return;
}
- ASSERT(raw_obj->GetClassId() != kFreeListElement);
+ intptr_t class_id = raw_obj->GetClassId();
+ ASSERT(class_id != kFreeListElement);
+
+ if (sync && UNLIKELY(class_id == kInstructionsCid)) {
+ // If this is the concurrent marker, instruction pages may be
+ // non-writable.
+ delayed_instructions_.Add(static_cast<RawInstructions*>(raw_obj));
+ return;
+ }
if (!TryAcquireMarkBit(raw_obj)) {
// Already marked.
@@ -397,6 +416,7 @@
PageSpace* page_space_;
MarkerWorkList work_list_;
RawWeakProperty* delayed_weak_properties_;
+ MallocGrowableArray<RawInstructions*> delayed_instructions_;
SkippedCodeFunctions* skipped_code_functions_;
uintptr_t marked_bytes_;
int64_t marked_micros_;
@@ -636,6 +656,8 @@
barrier_->Sync();
} while (more_to_mark);
+ visitor_->FinalizeInstructions();
+
// Phase 2: Weak processing and follow-up marking on main thread.
barrier_->Sync();
@@ -873,6 +895,7 @@
skipped_code_functions);
IterateRoots(&mark, 0, 1);
mark.DrainMarkingStack();
+ mark.FinalizeInstructions();
{
TIMELINE_FUNCTION_GC_DURATION(thread, "ProcessWeakHandles");
MarkingWeakVisitor mark_weak(thread);
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 8e769bf4..90ac254 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1081,7 +1081,7 @@
}
// Make code pages writable.
- WriteProtectCode(false);
+ if (finalize) WriteProtectCode(false);
// Save old value before GCMarker visits the weak persistent handles.
SpaceUsage usage_before = GetCurrentUsage();
@@ -1186,7 +1186,7 @@
}
// Make code pages read-only.
- WriteProtectCode(true);
+ if (finalize) WriteProtectCode(true);
int64_t end = OS::GetCurrentMonotonicMicros();