[vm,dyn_modules] Hook interpreter to the standalone VM

When dynamic modules are enabled, standalone VM can now run bytecode
binaries directly. Also, if --interpreter flag is specified, Dart
source is compiled to bytecode and interpreter is used to run it.

This will allow us to test VM service capabilities including
debugging and hot reload against the interpreter.

TEST=manual

Change-Id: Ibb5a67f4844485c4ed90b8a7568dc42fa552fcac
Cq-Include-Trybots: luci.dart.try:vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-linux-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/436421
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov
2025-06-24 05:59:21 -07:00
committed by Commit Queue
parent 0ba978160e
commit 05c2f3b0b1
15 changed files with 257 additions and 30 deletions
+50
View File
@@ -13,6 +13,7 @@
#include "platform/assert.h"
#include "platform/unicode.h"
#include "vm/app_snapshot.h"
#include "vm/bytecode_reader.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart.h"
@@ -1939,6 +1940,14 @@ DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
(buffer[3] == 0xef);
}
DART_EXPORT bool Dart_IsBytecode(const uint8_t* buffer, intptr_t buffer_size) {
if (buffer_size < 4) {
return false;
}
return (buffer[0] == 0x33) && (buffer[1] == 0x43) && (buffer[2] == 0x42) &&
(buffer[3] == 0x44);
}
DART_EXPORT char* Dart_IsolateMakeRunnable(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
API_TIMELINE_DURATION(Thread::Current());
@@ -5473,6 +5482,47 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_LoadScriptFromBytecode(const uint8_t* buffer,
intptr_t buffer_size) {
#if defined(DART_DYNAMIC_MODULES)
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
StackZone zone(T);
IsolateGroup* IG = T->isolate_group();
Library& library = Library::Handle(Z, IG->object_store()->root_library());
if (!library.IsNull()) {
const String& library_url = String::Handle(Z, library.url());
return Api::NewError("%s: A script has already been loaded from '%s'.",
CURRENT_FUNC, library_url.ToCString());
}
CHECK_CALLBACK_STATE(T);
// NOTE: We do not attach a finalizer for this object, because the embedder
// will free it once the isolate group has shutdown.
const auto& typed_data = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
SafepointWriteRwLocker ml(T, IG->program_lock());
bytecode::BytecodeLoader loader(T, typed_data);
const Function& function = Function::Handle(loader.LoadBytecode());
if (function.IsNull()) {
return Api::NewError(
"Invoked Dart programs must have a 'main' function defined:\n"
"https://dart.dev/to/main-function");
}
library ^= Class::Handle(function.Owner()).library();
IG->object_store()->set_root_library(library);
return Api::NewHandle(T, library.ptr());
#else
return Api::NewError(
"%s: Cannot load bytecode as dynamic modules are disabled.",
CURRENT_FUNC);
#endif // defined(DART_DYNAMIC_MODULES)
}
DART_EXPORT Dart_Handle Dart_RootLibrary() {
Thread* thread = Thread::Current();
IsolateGroup* isolate_group = thread->isolate_group();