Skip to content

Commit 8fbca8b

Browse files
alexmarkovCommit Queue
authored and
Commit Queue
committed
[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 <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent a09fbf8 commit 8fbca8b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+14493
-3307
lines changed

runtime/BUILD.gn

+4
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ config("dart_config") {
172172
defines += [ "SUPPORT_PERFETTO" ]
173173
}
174174

175+
if (dart_dynamic_modules) {
176+
defines += [ "DART_DYNAMIC_MODULES" ]
177+
}
178+
175179
if (is_fuchsia) {
176180
lib_dirs = [ "${fuchsia_arch_root}/lib" ]
177181

runtime/lib/errors.cc

+17-13
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,25 @@ static ScriptPtr FindScript(DartFrameIterator* iterator) {
3131
ASSERT(!assert_error_class.IsNull());
3232
bool hit_assertion_error = false;
3333
for (; stack_frame != nullptr; stack_frame = iterator->NextFrame()) {
34-
code = stack_frame->LookupDartCode();
35-
if (code.is_optimized()) {
36-
InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
37-
while (!inlined_iterator.Done()) {
38-
func = inlined_iterator.function();
39-
if (hit_assertion_error) {
40-
return func.script();
34+
if (stack_frame->is_interpreted()) {
35+
func = stack_frame->LookupDartFunction();
36+
} else {
37+
code = stack_frame->LookupDartCode();
38+
if (code.is_optimized()) {
39+
InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
40+
while (!inlined_iterator.Done()) {
41+
func = inlined_iterator.function();
42+
if (hit_assertion_error) {
43+
return func.script();
44+
}
45+
ASSERT(!hit_assertion_error);
46+
hit_assertion_error = (func.Owner() == assert_error_class.ptr());
47+
inlined_iterator.Advance();
4148
}
42-
ASSERT(!hit_assertion_error);
43-
hit_assertion_error = (func.Owner() == assert_error_class.ptr());
44-
inlined_iterator.Advance();
49+
continue;
50+
} else {
51+
func = code.function();
4552
}
46-
continue;
47-
} else {
48-
func = code.function();
4953
}
5054
ASSERT(!func.IsNull());
5155
if (hit_assertion_error) {

runtime/lib/object.cc

+56
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "vm/bootstrap_natives.h"
66

77
#include "lib/invocation_mirror.h"
8+
#include "vm/bytecode_reader.h"
89
#include "vm/code_patcher.h"
910
#include "vm/dart_entry.h"
1011
#include "vm/exceptions.h"
@@ -560,6 +561,61 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
560561
return Object::null();
561562
}
562563

564+
DEFINE_NATIVE_ENTRY(Internal_loadDynamicModule, 0, 1) {
565+
#if defined(DART_DYNAMIC_MODULES)
566+
GET_NON_NULL_NATIVE_ARGUMENT(TypedData, module_bytes,
567+
arguments->NativeArgAt(0));
568+
569+
const intptr_t length = module_bytes.LengthInBytes();
570+
uint8_t* data = reinterpret_cast<uint8_t*>(::malloc(length));
571+
if (data == nullptr) {
572+
const auto& exception = Instance::Handle(
573+
zone, thread->isolate_group()->object_store()->out_of_memory());
574+
Exceptions::Throw(thread, exception);
575+
}
576+
{
577+
NoSafepointScope no_safepoint;
578+
// The memory does not overlap.
579+
memcpy(data, module_bytes.DataAddr(0), length); // NOLINT
580+
}
581+
const ExternalTypedData& typed_data = ExternalTypedData::Handle(
582+
zone,
583+
ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, data, length));
584+
auto& function = Function::Handle();
585+
{
586+
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
587+
bytecode::BytecodeLoader loader(thread, typed_data);
588+
function = loader.LoadBytecode();
589+
}
590+
591+
if (function.IsNull()) {
592+
return Object::null();
593+
}
594+
ASSERT(function.is_static());
595+
ASSERT(function.is_declared_in_bytecode());
596+
auto& result = Object::Handle(zone);
597+
if (function.NumParameters() == 0) {
598+
result = DartEntry::InvokeFunction(function, Object::empty_array());
599+
} else {
600+
ASSERT(function.NumParameters() == 1);
601+
// <String>[]
602+
const auto& arg0 = Array::Handle(
603+
zone, Array::New(0, Type::Handle(zone, Type::StringType())));
604+
const auto& args = Array::Handle(zone, Array::New(1));
605+
args.SetAt(0, arg0);
606+
result = DartEntry::InvokeFunction(function, args);
607+
}
608+
if (result.IsError()) {
609+
Exceptions::PropagateError(Error::Cast(result));
610+
}
611+
return result.ptr();
612+
#else
613+
Exceptions::ThrowUnsupportedError(
614+
"Loading of dynamic modules is not supported.");
615+
return Object::null();
616+
#endif // defined(DART_DYNAMIC_MODULES)
617+
}
618+
563619
DEFINE_NATIVE_ENTRY(InvocationMirror_unpackTypeArguments, 0, 2) {
564620
const TypeArguments& type_arguments =
565621
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));

runtime/lib/stacktrace.cc

+20-5
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ static StackTracePtr CurrentStackTrace(Thread* thread,
4646
// Collect the frames.
4747
StackTraceUtils::CollectFrames(thread, skip_frames,
4848
[&](const StackTraceUtils::Frame& frame) {
49-
code_array.Add(frame.code);
49+
if (!frame.bytecode.IsNull()) {
50+
code_array.Add(frame.bytecode);
51+
} else {
52+
code_array.Add(frame.code);
53+
}
5054
pc_offset_array.Add(frame.pc_offset);
5155
});
5256

@@ -72,6 +76,7 @@ static void AppendFrames(const GrowableObjectArray& code_list,
7276
StackFrame* frame = frames.NextFrame();
7377
ASSERT(frame != nullptr); // We expect to find a dart invocation frame.
7478
Code& code = Code::Handle(zone);
79+
Bytecode& bytecode = Bytecode::Handle(zone);
7580
for (; frame != nullptr; frame = frames.NextFrame()) {
7681
if (!frame->IsDartFrame()) {
7782
continue;
@@ -81,10 +86,20 @@ static void AppendFrames(const GrowableObjectArray& code_list,
8186
continue;
8287
}
8388

84-
code = frame->LookupDartCode();
85-
const intptr_t pc_offset = frame->pc() - code.PayloadStart();
86-
code_list.Add(code);
87-
pc_offset_list->Add(pc_offset);
89+
if (frame->is_interpreted()) {
90+
bytecode = frame->LookupDartBytecode();
91+
if (bytecode.function() == Function::null()) {
92+
continue;
93+
}
94+
const intptr_t pc_offset = frame->pc() - bytecode.PayloadStart();
95+
code_list.Add(bytecode);
96+
pc_offset_list->Add(pc_offset);
97+
} else {
98+
code = frame->LookupDartCode();
99+
const intptr_t pc_offset = frame->pc() - code.PayloadStart();
100+
code_list.Add(code);
101+
pc_offset_list->Add(pc_offset);
102+
}
88103
}
89104
}
90105

runtime/runtime_args.gni

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ declare_args() {
7474
# being built on platforms which have a problem linking in the Perfetto
7575
# library.
7676
dart_support_perfetto = true
77+
78+
# Whether to support dynamic loading and interpretation of Dart bytecode.
79+
dart_dynamic_modules = false
7780
}
7881

7982
declare_args() {

runtime/vm/app_snapshot.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -1702,7 +1702,7 @@ class FunctionSerializationCluster : public SerializationCluster {
17021702
} else if (kind == Snapshot::kFullJIT) {
17031703
NOT_IN_PRECOMPILED(s->Push(func->untag()->unoptimized_code()));
17041704
s->Push(func->untag()->code());
1705-
s->Push(func->untag()->ic_data_array());
1705+
s->Push(func->untag()->ic_data_array_or_bytecode());
17061706
}
17071707
if (kind != Snapshot::kFullAOT) {
17081708
NOT_IN_PRECOMPILED(s->Push(func->untag()->positional_parameter_names()));
@@ -1737,7 +1737,7 @@ class FunctionSerializationCluster : public SerializationCluster {
17371737
} else if (s->kind() == Snapshot::kFullJIT) {
17381738
NOT_IN_PRECOMPILED(WriteCompressedField(func, unoptimized_code));
17391739
WriteCompressedField(func, code);
1740-
WriteCompressedField(func, ic_data_array);
1740+
WriteCompressedField(func, ic_data_array_or_bytecode);
17411741
}
17421742

17431743
if (kind != Snapshot::kFullAOT) {
@@ -1917,7 +1917,7 @@ class FunctionDeserializationCluster : public DeserializationCluster {
19171917
if (kind == Snapshot::kFullJIT) {
19181918
func->untag()->unoptimized_code_ = static_cast<CodePtr>(d.ReadRef());
19191919
func->untag()->code_ = static_cast<CodePtr>(d.ReadRef());
1920-
func->untag()->ic_data_array_ = static_cast<ArrayPtr>(d.ReadRef());
1920+
func->untag()->ic_data_array_or_bytecode_ = d.ReadRef();
19211921
}
19221922
#endif
19231923

runtime/vm/bootstrap_natives.h

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ namespace dart {
268268
V(Internal_extractTypeArguments, 2) \
269269
V(Internal_prependTypeArguments, 4) \
270270
V(Internal_boundsCheckForPartialInstantiation, 2) \
271+
V(Internal_loadDynamicModule, 1) \
271272
V(Internal_allocateOneByteString, 1) \
272273
V(Internal_allocateTwoByteString, 1) \
273274
V(Internal_writeIntoOneByteString, 3) \

0 commit comments

Comments
 (0)