mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +00:00
[vm] Support --use_table_dispatch when splitting snapshots.
When reading a secondary snapshot, re-run the dispatch table initialization found in the root snapshot. Since each loading unit's contribution to the dispatch table is scattered, it would take more snapshot size to try to serialize their contributions separately. We'll revisit this when we can defer Class, Function and Code, which will prevent the root snapshot from referencing all Codes. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Iefd2b98647b96ae59a7efe92897538f5cf8c2426 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/158923 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
41953c8835
commit
56a4d7c5f8
|
@ -705,19 +705,13 @@ class PrecompilerCompilerConfiguration extends CompilerConfiguration
|
|||
if (_configuration.useElf) ...[
|
||||
"--snapshot-kind=app-aot-elf",
|
||||
"--elf=$tempDir/out.aotsnapshot",
|
||||
// Only splitting with a ELF to avoid having to setup compilation of
|
||||
// multiple assembly files in the test harness.
|
||||
"--loading-unit-manifest=$tempDir/ignored.json",
|
||||
] else ...[
|
||||
"--snapshot-kind=app-aot-assembly",
|
||||
"--assembly=$tempDir/out.S",
|
||||
],
|
||||
// Only splitting with a ELF to avoid having to setup compilation of
|
||||
// multiple assembly files in the test harness. Only splitting tests of
|
||||
// deferred imports because splitting currently requires disable bare
|
||||
// instructions mode, and we want to continue testing bare instructions
|
||||
// mode.
|
||||
if (_configuration.useElf && arguments.last.contains("deferred")) ...[
|
||||
"--loading-unit-manifest=$tempDir/ignored.json",
|
||||
"--use-table-dispatch=false",
|
||||
],
|
||||
if (_isAndroid && _isArm) '--no-sim-use-hardfp',
|
||||
if (_configuration.isMinified) '--obfuscate',
|
||||
// The SIMARM precompiler assumes support for integer division, but the
|
||||
|
|
14
runtime/tests/vm/dart/deferred_loading_call_modes_test.dart
Normal file
14
runtime/tests/vm/dart/deferred_loading_call_modes_test.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--use_bare_instructions=false
|
||||
// VMOptions=--use_bare_instructions=true --use_table_dispatch=false
|
||||
// VMOptions=--use_bare_instructions=true --use_table_dispatch=true
|
||||
|
||||
import "splay_test.dart" deferred as splay; // Some non-trivial code.
|
||||
|
||||
main() async {
|
||||
await splay.loadLibrary();
|
||||
splay.main();
|
||||
}
|
|
@ -79,7 +79,6 @@ main(List<String> args) async {
|
|||
// Compile kernel to ELF.
|
||||
await run(genSnapshot, <String>[
|
||||
"--snapshot-kind=app-aot-elf",
|
||||
"--use-table-dispatch=false",
|
||||
"--elf=$snapshot1",
|
||||
"--loading-unit-manifest=$manifest1",
|
||||
dill1,
|
||||
|
@ -95,7 +94,6 @@ main(List<String> args) async {
|
|||
|
||||
await run(genSnapshot, <String>[
|
||||
"--snapshot-kind=app-aot-elf",
|
||||
"--use-table-dispatch=false",
|
||||
"--elf=$snapshot2",
|
||||
"--loading-unit-manifest=$manifest2",
|
||||
dill2,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--use_bare_instructions=false
|
||||
// VMOptions=--use_bare_instructions=true --use_table_dispatch=false
|
||||
// VMOptions=--use_bare_instructions=true --use_table_dispatch=true
|
||||
|
||||
import "splay_test.dart" deferred as splay; // Some non-trivial code.
|
||||
|
||||
main() async {
|
||||
await splay.loadLibrary();
|
||||
splay.main();
|
||||
}
|
|
@ -79,7 +79,6 @@ main(List<String> args) async {
|
|||
// Compile kernel to ELF.
|
||||
await run(genSnapshot, <String>[
|
||||
"--snapshot-kind=app-aot-elf",
|
||||
"--use-table-dispatch=false",
|
||||
"--elf=$snapshot1",
|
||||
"--loading-unit-manifest=$manifest1",
|
||||
dill1,
|
||||
|
@ -95,7 +94,6 @@ main(List<String> args) async {
|
|||
|
||||
await run(genSnapshot, <String>[
|
||||
"--snapshot-kind=app-aot-elf",
|
||||
"--use-table-dispatch=false",
|
||||
"--elf=$snapshot2",
|
||||
"--loading-unit-manifest=$manifest2",
|
||||
dill2,
|
||||
|
|
|
@ -6206,15 +6206,16 @@ DeserializationCluster* Deserializer::ReadCluster() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void Deserializer::ReadDispatchTable() {
|
||||
void Deserializer::ReadDispatchTable(ReadStream* stream) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
const intptr_t length = ReadUnsigned();
|
||||
const uint8_t* table_snapshot_start = stream->AddressOfCurrentPosition();
|
||||
const intptr_t length = stream->ReadUnsigned();
|
||||
if (length == 0) return;
|
||||
|
||||
// Not all Code objects may be in the code_order_table when instructions can
|
||||
// be deduplicated. Thus, we serialize the reference ID of the first code
|
||||
// object, from which we can get the reference ID for any code object.
|
||||
const intptr_t first_code_id = ReadUnsigned();
|
||||
const intptr_t first_code_id = stream->ReadUnsigned();
|
||||
|
||||
auto const I = isolate();
|
||||
auto code = I->object_store()->dispatch_table_null_error_stub();
|
||||
|
@ -6233,7 +6234,7 @@ void Deserializer::ReadDispatchTable() {
|
|||
repeat_count--;
|
||||
continue;
|
||||
}
|
||||
auto const encoded = Read<intptr_t>();
|
||||
auto const encoded = stream->Read<intptr_t>();
|
||||
if (encoded == 0) {
|
||||
value = null_entry;
|
||||
} else if (encoded < 0) {
|
||||
|
@ -6254,6 +6255,10 @@ void Deserializer::ReadDispatchTable() {
|
|||
ASSERT(repeat_count == 0);
|
||||
|
||||
I->group()->set_dispatch_table(table);
|
||||
intptr_t table_snapshot_size =
|
||||
stream->AddressOfCurrentPosition() - table_snapshot_start;
|
||||
I->group()->set_dispatch_table_snapshot(table_snapshot_start);
|
||||
I->group()->set_dispatch_table_snapshot_size(table_snapshot_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -6674,7 +6679,7 @@ void Deserializer::ReadProgramSnapshot(ObjectStore* object_store) {
|
|||
}
|
||||
|
||||
// Deserialize dispatch table (when applicable)
|
||||
ReadDispatchTable();
|
||||
ReadDispatchTable(&stream_);
|
||||
|
||||
#if defined(DEBUG)
|
||||
int32_t section_marker = Read<int32_t>();
|
||||
|
@ -6758,6 +6763,15 @@ ApiErrorPtr Deserializer::ReadUnitSnapshot(const LoadingUnit& unit) {
|
|||
code->ptr()->code_source_map_ = static_cast<CodeSourceMapPtr>(ReadRef());
|
||||
}
|
||||
|
||||
// Reinitialize the dispatch table by rereading the table's serialization
|
||||
// in the root snapshot.
|
||||
IsolateGroup* group = thread()->isolate()->group();
|
||||
if (group->dispatch_table_snapshot() != nullptr) {
|
||||
ReadStream stream(group->dispatch_table_snapshot(),
|
||||
group->dispatch_table_snapshot_size());
|
||||
ReadDispatchTable(&stream);
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
int32_t section_marker = Read<int32_t>();
|
||||
ASSERT(section_marker == kSectionMarker);
|
||||
|
|
|
@ -704,7 +704,7 @@ class Deserializer : public ThreadStackResource {
|
|||
|
||||
DeserializationCluster* ReadCluster();
|
||||
|
||||
void ReadDispatchTable();
|
||||
void ReadDispatchTable(ReadStream* stream);
|
||||
|
||||
intptr_t next_index() const { return next_ref_index_; }
|
||||
Heap* heap() const { return heap_; }
|
||||
|
|
|
@ -6805,11 +6805,6 @@ DART_EXPORT Dart_Handle Dart_CreateAppAOTSnapshotAsAssemblies(
|
|||
return Api::NewError(
|
||||
"This VM was built without support for AOT compilation.");
|
||||
#else
|
||||
if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
|
||||
return Api::NewError(
|
||||
"Splitting is not compatible with --use_table_dispatch.");
|
||||
}
|
||||
|
||||
DARTSCOPE(Thread::Current());
|
||||
API_TIMELINE_DURATION(T);
|
||||
CHECK_NULL(next_callback);
|
||||
|
@ -6887,11 +6882,6 @@ Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback,
|
|||
return Api::NewError(
|
||||
"This VM was built without support for AOT compilation.");
|
||||
#else
|
||||
if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
|
||||
return Api::NewError(
|
||||
"Splitting is not compatible with --use_table_dispatch.");
|
||||
}
|
||||
|
||||
DARTSCOPE(Thread::Current());
|
||||
API_TIMELINE_DURATION(T);
|
||||
CHECK_NULL(next_callback);
|
||||
|
|
|
@ -380,6 +380,18 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
|||
void set_dispatch_table(DispatchTable* table) {
|
||||
dispatch_table_.reset(table);
|
||||
}
|
||||
const uint8_t* dispatch_table_snapshot() const {
|
||||
return dispatch_table_snapshot_;
|
||||
}
|
||||
void set_dispatch_table_snapshot(const uint8_t* snapshot) {
|
||||
dispatch_table_snapshot_ = snapshot;
|
||||
}
|
||||
intptr_t dispatch_table_snapshot_size() const {
|
||||
return dispatch_table_snapshot_size_;
|
||||
}
|
||||
void set_dispatch_table_snapshot_size(intptr_t size) {
|
||||
dispatch_table_snapshot_size_ = size;
|
||||
}
|
||||
|
||||
SharedClassTable* shared_class_table() const {
|
||||
return shared_class_table_.get();
|
||||
|
@ -672,6 +684,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
|||
std::unique_ptr<StoreBuffer> store_buffer_;
|
||||
std::unique_ptr<Heap> heap_;
|
||||
std::unique_ptr<DispatchTable> dispatch_table_;
|
||||
const uint8_t* dispatch_table_snapshot_ = nullptr;
|
||||
intptr_t dispatch_table_snapshot_size_ = 0;
|
||||
ArrayPtr saved_unlinked_calls_;
|
||||
std::shared_ptr<FieldTable> saved_initial_field_table_;
|
||||
uint32_t isolate_group_flags_ = 0;
|
||||
|
|
Loading…
Reference in a new issue