[vm] Initial implementation of dynamic modules in the VM/AOT

TEST=Manually tested dynamic modules

Change-Id: Icb2616e414167bd1fbd10f01dea64c57dbdeeac7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/380281
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov
2024-08-15 14:09:52 +00:00
committed by Commit Queue
parent a09fbf8468
commit 8fbca8ba67
73 changed files with 14701 additions and 3515 deletions
+58 -10
View File
@@ -7,7 +7,9 @@
#include "vm/allocation.h"
#include "vm/frame_layout.h"
#include "vm/interpreter.h"
#include "vm/object.h"
#include "vm/stack_frame_kbc.h"
#include "vm/stub_code.h"
#if defined(TARGET_ARCH_IA32)
@@ -44,6 +46,7 @@ class StackFrame : public ValueObject {
// The pool pointer is not implemented on all architectures.
static int SavedCallerPpSlotFromFp() {
// Never called on an interpreter frame.
if (runtime_frame_layout.saved_caller_pp_from_fp !=
kSavedCallerFpSlotFromFp) {
return runtime_frame_layout.saved_caller_pp_from_fp;
@@ -53,30 +56,37 @@ class StackFrame : public ValueObject {
}
bool IsMarkedForLazyDeopt() const {
ASSERT(!is_interpreted());
uword raw_pc =
*reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize));
return raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint();
}
void MarkForLazyDeopt() {
ASSERT(!is_interpreted());
set_pc(StubCode::DeoptimizeLazyFromReturn().EntryPoint());
}
void UnmarkForLazyDeopt() {
// If this frame was marked for lazy deopt, pc_ was computed to be the
// original return address using the pending deopts table in GetCallerPc.
// Write this value back into the frame.
ASSERT(!is_interpreted());
uword original_pc = pc();
ASSERT(original_pc != StubCode::DeoptimizeLazyFromReturn().EntryPoint());
set_pc(original_pc);
}
void set_pc(uword value) {
*reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize)) = value;
*reinterpret_cast<uword*>(sp() + ((is_interpreted() ? kKBCSavedPcSlotFromSp
: kSavedPcSlotFromSp) *
kWordSize)) = value;
pc_ = value;
}
void set_pc_marker(CodePtr code) {
*reinterpret_cast<CodePtr*>(
fp() + (runtime_frame_layout.code_from_fp * kWordSize)) = code;
fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
: runtime_frame_layout.code_from_fp) *
kWordSize)) = code;
}
// Visit objects in the frame.
@@ -102,8 +112,15 @@ class StackFrame : public ValueObject {
virtual bool IsEntryFrame() const { return false; }
virtual bool IsExitFrame() const { return false; }
#if defined(DART_DYNAMIC_MODULES)
bool is_interpreted() const { return is_interpreted_; }
#else
bool is_interpreted() const { return false; }
#endif
FunctionPtr LookupDartFunction() const;
CodePtr LookupDartCode() const;
BytecodePtr LookupDartBytecode() const;
bool FindExceptionHandler(Thread* thread,
uword* handler_pc,
bool* needs_stacktrace,
@@ -114,7 +131,11 @@ class StackFrame : public ValueObject {
static void DumpCurrentTrace();
uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }
uword GetCallerSp() const {
return fp() +
((is_interpreted() ? kKBCCallerSpSlotFromFp : kCallerSpSlotFromFp) *
kWordSize);
}
protected:
explicit StackFrame(Thread* thread)
@@ -134,15 +155,20 @@ class StackFrame : public ValueObject {
private:
CodePtr GetCodeObject() const;
BytecodePtr GetBytecodeObject() const;
uword GetCallerFp() const {
return *(reinterpret_cast<uword*>(fp() +
(kSavedCallerFpSlotFromFp * kWordSize)));
return *(reinterpret_cast<uword*>(
fp() + ((is_interpreted() ? kKBCSavedCallerFpSlotFromFp
: kSavedCallerFpSlotFromFp) *
kWordSize)));
}
uword GetCallerPc() const {
uword raw_pc = *(reinterpret_cast<uword*>(
fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
fp() + ((is_interpreted() ? kKBCSavedCallerPcSlotFromFp
: kSavedCallerPcSlotFromFp) *
kWordSize)));
ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow().EntryPoint());
if (raw_pc == StubCode::DeoptimizeLazyFromReturn().EntryPoint()) {
return thread_->pending_deopts().FindPendingDeopt(GetCallerFp());
@@ -155,6 +181,10 @@ class StackFrame : public ValueObject {
uword pc_;
Thread* thread_;
#if defined(DART_DYNAMIC_MODULES)
bool is_interpreted_ = false;
#endif
// The iterators FrameSetIterator and StackFrameIterator set the private
// fields fp_ and sp_ when they return the respective frame objects.
friend class FrameSetIterator;
@@ -192,7 +222,9 @@ class ExitFrame : public StackFrame {
// dart code.
class EntryFrame : public StackFrame {
public:
bool IsValid() const { return StubCode::InInvocationStub(pc()); }
bool IsValid() const {
return StubCode::InInvocationStub(pc(), is_interpreted());
}
bool IsDartFrame(bool validate = true) const { return false; }
bool IsStubFrame() const { return false; }
bool IsEntryFrame() const { return true; }
@@ -261,9 +293,11 @@ class StackFrameIterator {
if (fp_ == 0) {
return false;
}
const uword pc =
*(reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize)));
return !StubCode::InInvocationStub(pc);
const uword pc = *(reinterpret_cast<uword*>(
sp_ +
((is_interpreted() ? kKBCSavedPcSlotFromSp : kSavedPcSlotFromSp) *
kWordSize)));
return !StubCode::InInvocationStub(pc, is_interpreted());
}
// Get next non entry/exit frame in the set (assumes a next frame exists).
@@ -272,6 +306,14 @@ class StackFrameIterator {
private:
explicit FrameSetIterator(Thread* thread)
: fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) {}
#if defined(DART_DYNAMIC_MODULES)
bool is_interpreted() const { return is_interpreted_; }
void CheckIfInterpreted(uword exit_marker);
#else
bool is_interpreted() const { return false; }
#endif
void Unpoison();
uword fp_;
@@ -280,6 +322,10 @@ class StackFrameIterator {
StackFrame stack_frame_; // Singleton frame returned by NextFrame().
Thread* thread_;
#if defined(DART_DYNAMIC_MODULES)
bool is_interpreted_ = false;
#endif
friend class StackFrameIterator;
DISALLOW_COPY_AND_ASSIGN(FrameSetIterator);
};
@@ -299,6 +345,8 @@ class StackFrameIterator {
void SetupLastExitFrameData();
void SetupNextExitFrameData();
void CheckInterpreterExitFrame(uword exit_marker);
bool validate_; // Validate each frame as we traverse the frames.
EntryFrame entry_; // Singleton entry frame returned by NextEntryFrame().
ExitFrame exit_; // Singleton exit frame returned by NextExitFrame().