[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();