[vm] Add missing save of shadow call stack in DartEntryScope.

Thread::saved_shadow_call_stack_ has the value for the top-most Dart entry, and needs to be saved and restored for nested Dart entries.

TEST=fuchsia
Change-Id: Id035bec7e798458fdfcf85678a7246d5f7eef850
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464603
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index e02f2af..c59b714 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -52,8 +52,11 @@
 #if defined(USING_SAFE_STACK)
     // Remember the safestack pointer at entry so it can be restored in
     // Exceptions::JumpToFrame when a Dart exception jumps over C++ frames.
-    saved_safestack_limit_ = OSThread::GetCurrentSafestackPointer();
-    thread->set_saved_safestack_limit(saved_safestack_limit_);
+    saved_safestack_ = thread->saved_safestack();
+    thread->set_saved_safestack(OSThread::GetCurrentSafestackPointer());
+#endif
+#if defined(USING_SHADOW_CALL_STACK)
+    saved_shadow_call_stack_ = thread->saved_shadow_call_stack();
 #endif
 
     saved_api_scope_ = thread->api_top_scope();
@@ -67,8 +70,11 @@
       thread()->ExitApiScope();
     }
 
+#if defined(USING_SHADOW_CALL_STACK)
+    thread()->set_saved_shadow_call_stack(saved_shadow_call_stack_);
+#endif
 #if defined(USING_SAFE_STACK)
-    thread()->set_saved_safestack_limit(saved_safestack_limit_);
+    thread()->set_saved_safestack(saved_safestack_);
 #endif
 
     ASSERT(thread()->long_jump_base() == nullptr);
@@ -78,7 +84,10 @@
  private:
   LongJumpScope* saved_long_jump_base_;
 #if defined(USING_SAFE_STACK)
-  uword saved_safestack_limit_ = 0;
+  uword saved_safestack_ = 0;
+#endif
+#if defined(USING_SHADOW_CALL_STACK)
+  uword saved_shadow_call_stack_ = 0;
 #endif
   ApiLocalScope* saved_api_scope_;
 };
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index b101048..3e36df0 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -650,7 +650,7 @@
   // We are jumping over C++ frames, so we have to set the safestack pointer
   // back to what it was when we entered the runtime from Dart code.
 #if defined(USING_SAFE_STACK)
-  const uword saved_ssp = thread->saved_safestack_limit();
+  const uword saved_ssp = thread->saved_safestack();
   OSThread::SetCurrentSafestackPointer(saved_ssp);
 #endif
 
diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc
index a1ff522..8b6c962 100644
--- a/runtime/vm/os_thread_fuchsia.cc
+++ b/runtime/vm/os_thread_fuchsia.cc
@@ -153,7 +153,7 @@
 }
 
 void OSThread::Detach(ThreadJoinId id) {
-  int result = pthread_detach(id);
+  int result = pthread_detach(id);  // NOLINT
   VALIDATE_PTHREAD_RESULT(result);
 }
 
@@ -202,6 +202,10 @@
   asm volatile("mrs %0, TPIDR_EL0;\n" _loadword(ZX_TLS_UNSAFE_SP_OFFSET)
                : "=r"(result)  // outputs
   );
+#elif defined(HOST_ARCH_RISCV64)
+  asm volatile("ld %0, " STRINGIFY(ZX_TLS_UNSAFE_SP_OFFSET) "(tp)"
+               : "=r"(result)  // outputs
+  );
 #else
 #error "Architecture not supported"
 #endif
@@ -229,6 +233,12 @@
                : "r"(ssp)   // inputs.
                :            // clobbered.
   );
+#elif defined(HOST_ARCH_RISCV64)
+  asm volatile("sd %0, " STRINGIFY(ZX_TLS_UNSAFE_SP_OFFSET) "(tp)"
+               :           // outputs.
+               : "r"(ssp)  // inputs.
+               :           // clobbered.
+  );
 #else
 #error "Architecture not supported"
 #endif
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index e10c2c5..2e25f3a 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -425,9 +425,9 @@
   void SetStackLimit(uword value);
   void ClearStackLimit();
 
-  // Access to the current stack limit for generated code. Either the true OS
-  // thread's stack limit minus some headroom, or a special value to trigger
-  // interrupts.
+  // The stack limit used by stack overflow checks in generated code. Either the
+  // true OS thread's stack limit minus some headroom, or a special value to
+  // trigger interrupts.
   uword stack_limit_address() const {
     return reinterpret_cast<uword>(&stack_limit_);
   }
@@ -435,19 +435,27 @@
     return OFFSET_OF(Thread, stack_limit_);
   }
 
-  // The true stack limit for this OS thread.
+  // The true stack limit for this OS thread minus some headroom. Used on ARM64
+  // to keep CSP/R31 signal-handler safe while Dart uses R15 as its stack
+  // pointer.
   static intptr_t saved_stack_limit_offset() {
     return OFFSET_OF(Thread, saved_stack_limit_);
   }
   uword saved_stack_limit() const { return saved_stack_limit_; }
 
 #if defined(USING_SAFE_STACK)
-  uword saved_safestack_limit() const { return saved_safestack_limit_; }
-  void set_saved_safestack_limit(uword limit) {
-    saved_safestack_limit_ = limit;
-  }
+  // The SafeStack pointer during the top-most DartEntry. Needs to be restored
+  // on Dart throw like longjmp would.
+  uword saved_safestack() const { return saved_safestack_; }
+  void set_saved_safestack(uword ssp) { saved_safestack_ = ssp; }
 #endif
+
+  // The ShadowCallStack pointer during the top-most entry frame. Needs to be
+  // restored on Dart throw like longjmp would.
   uword saved_shadow_call_stack() const { return saved_shadow_call_stack_; }
+  void set_saved_shadow_call_stack(uword ssp) {
+    saved_shadow_call_stack_ = ssp;
+  }
   static uword saved_shadow_call_stack_offset() {
     return OFFSET_OF(Thread, saved_shadow_call_stack_);
   }
@@ -1634,7 +1642,7 @@
   }
 
 #if defined(USING_SAFE_STACK)
-  uword saved_safestack_limit_ = 0;
+  uword saved_safestack_ = 0;
 #endif
 
   Thread* next_;  // Used to chain the thread structures in an isolate.