diff --git a/runtime/tests/vm/dart/split_literals.dart b/runtime/tests/vm/dart/split_literals.dart deleted file mode 100644 index b71e9bd36c8..00000000000 --- a/runtime/tests/vm/dart/split_literals.dart +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -import "split_literals_deferred.dart" deferred as lib; - -class Box { - final contents; - const Box(this.contents); - String toString() => "Box($contents)"; -} - -main() async { - print("Root literal!"); - print(const ["Root literal in a list!"]); - print(const {"key": "Root literal in a map!"}); - print(const Box("Root literal in a box!")); - - await lib.loadLibrary(); - lib.foo(); -} diff --git a/runtime/tests/vm/dart/split_literals_deferred.dart b/runtime/tests/vm/dart/split_literals_deferred.dart deleted file mode 100644 index 015ae1dd88b..00000000000 --- a/runtime/tests/vm/dart/split_literals_deferred.dart +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -import "split_literals.dart"; - -void foo() { - print("Deferred literal!"); - print(const ["Deferred literal in a list!"]); - print(const {"key": "Deferred literal in a map!"}); - print(const Box("Deferred literal in a box!")); -} diff --git a/runtime/tests/vm/dart/split_literals_test.dart b/runtime/tests/vm/dart/split_literals_test.dart deleted file mode 100644 index 6cbc01b5c5f..00000000000 --- a/runtime/tests/vm/dart/split_literals_test.dart +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -import "dart:convert"; -import "dart:io"; - -import "package:expect/expect.dart"; -import "package:path/path.dart" as path; - -import "use_flag_test_helper.dart"; - -main(List args) async { - if (!isAOTRuntime) { - return; // Running in JIT: AOT binaries not available. - } - - if (Platform.isAndroid) { - return; // SDK tree not available on the test device. - } - - // These are the tools we need to be available to run on a given platform: - if (!File(platformDill).existsSync()) { - throw "Cannot run test as $platformDill does not exist"; - } - if (!await testExecutable(genSnapshot)) { - throw "Cannot run test as $genSnapshot not available"; - } - - sanitizedPartitioning(manifest) { - // Filter core libraries, relativize URIs, and sort to make the results less - // sensitive to compiler or test harness changes. - print(manifest); - var units = >[]; - for (var unit in manifest['loadingUnits']) { - var uris = []; - for (var uri in unit['libraries']) { - if (uri.startsWith("dart:")) continue; - uris.add(Uri.parse(uri).pathSegments.last); - } - uris.sort((a, b) => a.compareTo(b)); - units.add(uris); - } - units.sort((a, b) => a.first.compareTo(b.first)); - print(units); - return units; - } - - await withTempDir("split-literals-test", (String tempDir) async { - final source = - path.join(sdkDir, "runtime/tests/vm/dart_2/split_literals.dart"); - final dill = path.join(tempDir, "split_literals.dart.dill"); - final snapshot = path.join(tempDir, "split_literals.so"); - final manifest = path.join(tempDir, "split_literals.txt"); - final deferredSnapshot = snapshot + "-2.part.so"; - - // Compile source to kernel. - await run(genKernel, [ - "--aot", - "--platform=$platformDill", - "-o", - dill, - source, - ]); - - // Compile kernel to ELF. - await run(genSnapshot, [ - "--use_bare_instructions=false", //# object: ok - "--use_bare_instructions=true", //# bare: ok - "--snapshot-kind=app-aot-elf", - "--elf=$snapshot", - "--loading-unit-manifest=$manifest", - dill, - ]); - var manifestContent = jsonDecode(await new File(manifest).readAsString()); - Expect.equals(2, manifestContent["loadingUnits"].length); - // Note package:expect doesn't do deep equals on collections. - Expect.equals( - "[[split_literals.dart]," - " [split_literals_deferred.dart]]", - sanitizedPartitioning(manifestContent).toString()); - Expect.isTrue(await new File(deferredSnapshot).exists()); - - bool containsSubsequence(haystack, needle) { - outer: - for (var i = 0, n = haystack.length - needle.length; i < n; i++) { - for (var j = 0; j < needle.length; j++) { - if (haystack[i + j] != needle.codeUnitAt(j)) continue outer; - } - return true; - } - return false; - } - - var unit_1 = await new File(snapshot).readAsBytes(); - Expect.isTrue(containsSubsequence(unit_1, "Root literal!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a list!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a map!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a box!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a list!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a map!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a box!")); - - var unit_2 = await new File(deferredSnapshot).readAsBytes(); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a list!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a map!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a box!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a list!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a map!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a box!")); - }); -} diff --git a/runtime/tests/vm/dart_2/split_literals.dart b/runtime/tests/vm/dart_2/split_literals.dart deleted file mode 100644 index b71e9bd36c8..00000000000 --- a/runtime/tests/vm/dart_2/split_literals.dart +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -import "split_literals_deferred.dart" deferred as lib; - -class Box { - final contents; - const Box(this.contents); - String toString() => "Box($contents)"; -} - -main() async { - print("Root literal!"); - print(const ["Root literal in a list!"]); - print(const {"key": "Root literal in a map!"}); - print(const Box("Root literal in a box!")); - - await lib.loadLibrary(); - lib.foo(); -} diff --git a/runtime/tests/vm/dart_2/split_literals_deferred.dart b/runtime/tests/vm/dart_2/split_literals_deferred.dart deleted file mode 100644 index 015ae1dd88b..00000000000 --- a/runtime/tests/vm/dart_2/split_literals_deferred.dart +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -import "split_literals.dart"; - -void foo() { - print("Deferred literal!"); - print(const ["Deferred literal in a list!"]); - print(const {"key": "Deferred literal in a map!"}); - print(const Box("Deferred literal in a box!")); -} diff --git a/runtime/tests/vm/dart_2/split_literals_test.dart b/runtime/tests/vm/dart_2/split_literals_test.dart deleted file mode 100644 index 6cbc01b5c5f..00000000000 --- a/runtime/tests/vm/dart_2/split_literals_test.dart +++ /dev/null @@ -1,115 +0,0 @@ -// 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. - -import "dart:convert"; -import "dart:io"; - -import "package:expect/expect.dart"; -import "package:path/path.dart" as path; - -import "use_flag_test_helper.dart"; - -main(List args) async { - if (!isAOTRuntime) { - return; // Running in JIT: AOT binaries not available. - } - - if (Platform.isAndroid) { - return; // SDK tree not available on the test device. - } - - // These are the tools we need to be available to run on a given platform: - if (!File(platformDill).existsSync()) { - throw "Cannot run test as $platformDill does not exist"; - } - if (!await testExecutable(genSnapshot)) { - throw "Cannot run test as $genSnapshot not available"; - } - - sanitizedPartitioning(manifest) { - // Filter core libraries, relativize URIs, and sort to make the results less - // sensitive to compiler or test harness changes. - print(manifest); - var units = >[]; - for (var unit in manifest['loadingUnits']) { - var uris = []; - for (var uri in unit['libraries']) { - if (uri.startsWith("dart:")) continue; - uris.add(Uri.parse(uri).pathSegments.last); - } - uris.sort((a, b) => a.compareTo(b)); - units.add(uris); - } - units.sort((a, b) => a.first.compareTo(b.first)); - print(units); - return units; - } - - await withTempDir("split-literals-test", (String tempDir) async { - final source = - path.join(sdkDir, "runtime/tests/vm/dart_2/split_literals.dart"); - final dill = path.join(tempDir, "split_literals.dart.dill"); - final snapshot = path.join(tempDir, "split_literals.so"); - final manifest = path.join(tempDir, "split_literals.txt"); - final deferredSnapshot = snapshot + "-2.part.so"; - - // Compile source to kernel. - await run(genKernel, [ - "--aot", - "--platform=$platformDill", - "-o", - dill, - source, - ]); - - // Compile kernel to ELF. - await run(genSnapshot, [ - "--use_bare_instructions=false", //# object: ok - "--use_bare_instructions=true", //# bare: ok - "--snapshot-kind=app-aot-elf", - "--elf=$snapshot", - "--loading-unit-manifest=$manifest", - dill, - ]); - var manifestContent = jsonDecode(await new File(manifest).readAsString()); - Expect.equals(2, manifestContent["loadingUnits"].length); - // Note package:expect doesn't do deep equals on collections. - Expect.equals( - "[[split_literals.dart]," - " [split_literals_deferred.dart]]", - sanitizedPartitioning(manifestContent).toString()); - Expect.isTrue(await new File(deferredSnapshot).exists()); - - bool containsSubsequence(haystack, needle) { - outer: - for (var i = 0, n = haystack.length - needle.length; i < n; i++) { - for (var j = 0; j < needle.length; j++) { - if (haystack[i + j] != needle.codeUnitAt(j)) continue outer; - } - return true; - } - return false; - } - - var unit_1 = await new File(snapshot).readAsBytes(); - Expect.isTrue(containsSubsequence(unit_1, "Root literal!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a list!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a map!")); - Expect.isTrue(containsSubsequence(unit_1, "Root literal in a box!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a list!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a map!")); - Expect.isTrue(!containsSubsequence(unit_1, "Deferred literal in a box!")); - - var unit_2 = await new File(deferredSnapshot).readAsBytes(); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a list!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a map!")); - Expect.isTrue(!containsSubsequence(unit_2, "Root literal in a box!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a list!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a map!")); - Expect.isTrue(containsSubsequence(unit_2, "Deferred literal in a box!")); - }); -} diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index 12ec76e449c..ef22f900795 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -289,7 +289,7 @@ class ClassDeserializationCluster : public DeserializationCluster { ClassDeserializationCluster() : DeserializationCluster("Class") {} ~ClassDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { predefined_start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); intptr_t count = d->ReadUnsigned(); @@ -311,7 +311,7 @@ class ClassDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { ClassTable* table = d->isolate_group()->class_table(); for (intptr_t id = predefined_start_index_; id < predefined_stop_index_; @@ -464,7 +464,7 @@ class TypeArgumentsDeserializationCluster : public DeserializationCluster { : DeserializationCluster("TypeArguments") {} ~TypeArgumentsDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -476,13 +476,13 @@ class TypeArgumentsDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TypeArgumentsPtr type_args = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); Deserializer::InitializeHeader(type_args, kTypeArgumentsCid, TypeArguments::InstanceSize(length), - stamp_canonical); + is_canonical); type_args->untag()->length_ = Smi::New(length); type_args->untag()->hash_ = Smi::New(d->Read()); type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned()); @@ -494,15 +494,22 @@ class TypeArgumentsDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - Thread* thread = Thread::Current(); + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalTypeArgumentsSet table( + d->zone(), + d->isolate_group()->object_store()->canonical_type_arguments()); TypeArguments& type_arg = TypeArguments::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { type_arg ^= refs.At(i); - type_arg = type_arg.Canonicalize(thread, nullptr); - refs.SetAt(i, type_arg); + ASSERT(type_arg.IsCanonical()); + bool present = table.Insert(type_arg); + // Two recursive types with different topology (and hashes) may be + // equal. + ASSERT(!present || type_arg.IsRecursive()); } + d->isolate_group()->object_store()->set_canonical_type_arguments( + table.Release()); } } }; @@ -551,7 +558,7 @@ class PatchClassDeserializationCluster : public DeserializationCluster { PatchClassDeserializationCluster() : DeserializationCluster("PatchClass") {} ~PatchClassDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -562,8 +569,7 @@ class PatchClassDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { PatchClassPtr cls = static_cast(d->Ref(id)); Deserializer::InitializeHeader(cls, kPatchClassCid, @@ -661,7 +667,7 @@ class FunctionDeserializationCluster : public DeserializationCluster { FunctionDeserializationCluster() : DeserializationCluster("Function") {} ~FunctionDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -671,8 +677,7 @@ class FunctionDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { Snapshot::Kind kind = d->kind(); for (intptr_t id = start_index_; id < stop_index_; id++) { @@ -720,7 +725,7 @@ class FunctionDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { if (d->kind() == Snapshot::kFullAOT) { Function& func = Function::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { @@ -811,7 +816,7 @@ class ClosureDataDeserializationCluster : public DeserializationCluster { ClosureDataDeserializationCluster() : DeserializationCluster("ClosureData") {} ~ClosureDataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -822,8 +827,7 @@ class ClosureDataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ClosureDataPtr data = static_cast(d->Ref(id)); Deserializer::InitializeHeader(data, kClosureDataCid, @@ -893,7 +897,7 @@ class FfiTrampolineDataDeserializationCluster : public DeserializationCluster { : DeserializationCluster("FfiTrampolineData") {} ~FfiTrampolineDataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -904,8 +908,7 @@ class FfiTrampolineDataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { FfiTrampolineDataPtr data = static_cast(d->Ref(id)); Deserializer::InitializeHeader(data, kFfiTrampolineDataCid, @@ -1012,7 +1015,7 @@ class FieldDeserializationCluster : public DeserializationCluster { FieldDeserializationCluster() : DeserializationCluster("Field") {} ~FieldDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1022,8 +1025,7 @@ class FieldDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { Snapshot::Kind kind = d->kind(); for (intptr_t id = start_index_; id < stop_index_; id++) { @@ -1079,7 +1081,7 @@ class FieldDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { Field& field = Field::Handle(d->zone()); if (!IsolateGroup::Current()->use_field_guards()) { for (intptr_t i = start_index_; i < stop_index_; i++) { @@ -1155,7 +1157,7 @@ class ScriptDeserializationCluster : public DeserializationCluster { ScriptDeserializationCluster() : DeserializationCluster("Script") {} ~ScriptDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1165,8 +1167,7 @@ class ScriptDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ScriptPtr script = static_cast(d->Ref(id)); Deserializer::InitializeHeader(script, kScriptCid, @@ -1231,7 +1232,7 @@ class LibraryDeserializationCluster : public DeserializationCluster { LibraryDeserializationCluster() : DeserializationCluster("Library") {} ~LibraryDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1241,8 +1242,7 @@ class LibraryDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { LibraryPtr lib = static_cast(d->Ref(id)); Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize()); @@ -1304,7 +1304,7 @@ class NamespaceDeserializationCluster : public DeserializationCluster { NamespaceDeserializationCluster() : DeserializationCluster("Namespace") {} ~NamespaceDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1314,8 +1314,7 @@ class NamespaceDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { NamespacePtr ns = static_cast(d->Ref(id)); Deserializer::InitializeHeader(ns, kNamespaceCid, @@ -1371,7 +1370,7 @@ class KernelProgramInfoDeserializationCluster : public DeserializationCluster { : DeserializationCluster("KernelProgramInfo") {} ~KernelProgramInfoDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1382,8 +1381,7 @@ class KernelProgramInfoDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { KernelProgramInfoPtr info = static_cast(d->Ref(id)); Deserializer::InitializeHeader(info, kKernelProgramInfoCid, @@ -1393,7 +1391,7 @@ class KernelProgramInfoDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { Array& array = Array::Handle(d->zone()); KernelProgramInfo& info = KernelProgramInfo::Handle(d->zone()); for (intptr_t id = start_index_; id < stop_index_; id++) { @@ -1419,26 +1417,9 @@ class CodeSerializationCluster : public SerializationCluster { objects_.Add(code); } - if (s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions) { - if (FLAG_retain_function_objects) { - ObjectPoolPtr pool = code->untag()->object_pool_; - if ((pool != ObjectPool::null()) && s->InCurrentLoadingUnit(code)) { - const intptr_t length = pool->untag()->length_; - uint8_t* entry_bits = pool->untag()->entry_bits(); - for (intptr_t i = 0; i < length; i++) { - auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); - if (entry_type == ObjectPool::EntryType::kTaggedObject) { - s->Push(pool->untag()->data()[i].raw_obj_); - } - } - } - } - } else { - if (s->InCurrentLoadingUnit(code->untag()->object_pool_)) { - s->Push(code->untag()->object_pool_); - } + if (!(s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions)) { + s->Push(code->untag()->object_pool_); } - s->Push(code->untag()->owner_); s->Push(code->untag()->exception_handlers_); s->Push(code->untag()->pc_descriptors_); @@ -1550,6 +1531,20 @@ class CodeSerializationCluster : public SerializationCluster { } void WriteAlloc(Serializer* s) { + Sort(&objects_); + auto loading_units = s->loading_units(); + if (loading_units != nullptr) { + for (intptr_t i = LoadingUnit::kRootId + 1; i < loading_units->length(); + i++) { + auto unit_objects = loading_units->At(i)->deferred_objects(); + Sort(unit_objects); + for (intptr_t j = 0; j < unit_objects->length(); j++) { + deferred_objects_.Add(unit_objects->At(j)->ptr()); + } + } + } + s->PrepareInstructions(&objects_); + s->WriteCid(kCodeCid); const intptr_t count = objects_.length(); s->WriteUnsigned(count); @@ -1610,11 +1605,7 @@ class CodeSerializationCluster : public SerializationCluster { // No need to write object pool out if we are producing full AOT // snapshot with bare instructions. if (!(kind == Snapshot::kFullAOT && FLAG_use_bare_instructions)) { - if (s->InCurrentLoadingUnit(code->untag()->object_pool_)) { - WriteField(code, object_pool_); - } else { - WriteFieldValue(object_pool_, ObjectPool::null()); - } + WriteField(code, object_pool_); #if defined(DART_PRECOMPILER) } else if (FLAG_write_v8_snapshot_profile_to != nullptr && code->untag()->object_pool_ != ObjectPool::null()) { @@ -1695,8 +1686,7 @@ class CodeSerializationCluster : public SerializationCluster { s->Write(code->untag()->state_bits_); } - GrowableArray* objects() { return &objects_; } - GrowableArray* deferred_objects() { return &deferred_objects_; } + GrowableArray* discovered_objects() { return &objects_; } // Some code objects would have their owners dropped from the snapshot, // which makes it is impossible to recover program structure when @@ -1742,7 +1732,7 @@ class CodeDeserializationCluster : public DeserializationCluster { CodeDeserializationCluster() : DeserializationCluster("Code") {} ~CodeDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { PageSpace* old_space = d->heap()->old_space(); start_index_ = d->next_index(); const intptr_t count = d->ReadUnsigned(); @@ -1760,8 +1750,7 @@ class CodeDeserializationCluster : public DeserializationCluster { deferred_stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ReadFill(d, id, false); } @@ -1816,7 +1805,7 @@ class CodeDeserializationCluster : public DeserializationCluster { code->untag()->state_bits_ = d->Read(); } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { d->EndInstructions(refs, start_index_, stop_index_); #if !defined(PRODUCT) @@ -1864,17 +1853,12 @@ class ObjectPoolSerializationCluster : public SerializationCluster { ObjectPoolPtr pool = ObjectPool::RawCast(object); objects_.Add(pool); - if (s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions && - FLAG_retain_function_objects) { - // Treat pool as weak. - } else { - const intptr_t length = pool->untag()->length_; - uint8_t* entry_bits = pool->untag()->entry_bits(); - for (intptr_t i = 0; i < length; i++) { - auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); - if (entry_type == ObjectPool::EntryType::kTaggedObject) { - s->Push(pool->untag()->data()[i].raw_obj_); - } + const intptr_t length = pool->untag()->length_; + uint8_t* entry_bits = pool->untag()->entry_bits(); + for (intptr_t i = 0; i < length; i++) { + auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); + if (entry_type == ObjectPool::EntryType::kTaggedObject) { + s->Push(pool->untag()->data()[i].raw_obj_); } } } @@ -1893,9 +1877,6 @@ class ObjectPoolSerializationCluster : public SerializationCluster { } void WriteFill(Serializer* s) { - bool weak = s->kind() == Snapshot::kFullAOT && FLAG_use_bare_instructions && - FLAG_retain_function_objects; - const intptr_t count = objects_.length(); for (intptr_t i = 0; i < count; i++) { ObjectPoolPtr pool = objects_[i]; @@ -1916,12 +1897,7 @@ class ObjectPoolSerializationCluster : public SerializationCluster { s->WriteElementRef(StubCode::CallBootstrapNative().ptr(), j); break; } - if (weak && !s->HasRef(entry.raw_obj_)) { - // Any value will do, but null has the shortest id. - s->WriteElementRef(Object::null(), j); - } else { - s->WriteElementRef(entry.raw_obj_, j); - } + s->WriteElementRef(entry.raw_obj_, j); break; } case ObjectPool::EntryType::kImmediate: { @@ -1950,7 +1926,7 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster { ObjectPoolDeserializationCluster() : DeserializationCluster("ObjectPool") {} ~ObjectPoolDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -1962,10 +1938,7 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. - fill_position_ = d->position(); - + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id += 1) { const intptr_t length = d->ReadUnsigned(); ObjectPoolPtr pool = static_cast(d->Ref(id + 0)); @@ -1995,41 +1968,6 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster { } } } - - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - intptr_t restore_position = d->position(); - d->set_position(fill_position_); - - ObjectPool& pool = ObjectPool::Handle(); - Object& entry = Object::Handle(); - for (intptr_t id = start_index_; id < stop_index_; id += 1) { - pool ^= refs.At(id); - const intptr_t length = d->ReadUnsigned(); - for (intptr_t j = 0; j < length; j++) { - const uint8_t entry_bits = d->Read(); - switch (ObjectPool::TypeBits::decode(entry_bits)) { - case ObjectPool::EntryType::kTaggedObject: - entry = refs.At(d->ReadUnsigned()); - pool.SetObjectAt(j, entry); - break; - case ObjectPool::EntryType::kImmediate: - d->Read(); - break; - case ObjectPool::EntryType::kNativeFunction: { - // Read nothing. - break; - } - default: - UNREACHABLE(); - } - } - } - - d->set_position(restore_position); - } - - private: - intptr_t fill_position_ = 0; }; #if defined(DART_PRECOMPILER) @@ -2152,7 +2090,7 @@ class WeakSerializationReferenceDeserializationCluster : DeserializationCluster("WeakSerializationReference") {} ~WeakSerializationReferenceDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2166,8 +2104,7 @@ class WeakSerializationReferenceDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { auto const ref = static_cast(d->Ref(id)); Deserializer::InitializeHeader( @@ -2226,7 +2163,7 @@ class PcDescriptorsDeserializationCluster : public DeserializationCluster { : DeserializationCluster("PcDescriptors") {} ~PcDescriptorsDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2238,8 +2175,7 @@ class PcDescriptorsDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id += 1) { const intptr_t length = d->ReadUnsigned(); PcDescriptorsPtr desc = static_cast(d->Ref(id)); @@ -2321,7 +2257,7 @@ class RODataDeserializationCluster : public DeserializationCluster { : DeserializationCluster("ROData"), cid_(cid) {} ~RODataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); intptr_t count = d->ReadUnsigned(); uint32_t running_offset = 0; @@ -2332,25 +2268,21 @@ class RODataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { // No-op. } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize && IsStringClassId(cid_)) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && IsStringClassId(cid_) && + (d->isolate() != Dart::vm_isolate())) { CanonicalStringSet table( d->zone(), d->isolate_group()->object_store()->symbol_table()); String& str = String::Handle(d->zone()); - String& str2 = String::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { str ^= refs.At(i); - str2 ^= table.InsertOrGet(str); - if (str.ptr() == str2.ptr()) { - // str.SetCanonical(); - } else { - FATAL("Lost canonicalization race"); - refs.SetAt(i, str2); - } + ASSERT(str.IsCanonical()); + bool present = table.Insert(str); + ASSERT(!present); } d->isolate_group()->object_store()->set_symbol_table(table.Release()); } @@ -2417,7 +2349,7 @@ class ExceptionHandlersDeserializationCluster : public DeserializationCluster { : DeserializationCluster("ExceptionHandlers") {} ~ExceptionHandlersDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2429,8 +2361,7 @@ class ExceptionHandlersDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ExceptionHandlersPtr handlers = static_cast(d->Ref(id)); @@ -2506,7 +2437,7 @@ class ContextDeserializationCluster : public DeserializationCluster { ContextDeserializationCluster() : DeserializationCluster("Context") {} ~ContextDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2518,8 +2449,7 @@ class ContextDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ContextPtr context = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); @@ -2584,7 +2514,7 @@ class ContextScopeDeserializationCluster : public DeserializationCluster { : DeserializationCluster("ContextScope") {} ~ContextScopeDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2596,8 +2526,7 @@ class ContextScopeDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ContextScopePtr scope = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); @@ -2653,7 +2582,7 @@ class UnlinkedCallDeserializationCluster : public DeserializationCluster { : DeserializationCluster("UnlinkedCall") {} ~UnlinkedCallDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2664,8 +2593,7 @@ class UnlinkedCallDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { UnlinkedCallPtr unlinked = static_cast(d->Ref(id)); Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid, @@ -2722,7 +2650,7 @@ class ICDataDeserializationCluster : public DeserializationCluster { ICDataDeserializationCluster() : DeserializationCluster("ICData") {} ~ICDataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2732,8 +2660,7 @@ class ICDataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ICDataPtr ic = static_cast(d->Ref(id)); Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize()); @@ -2788,7 +2715,7 @@ class MegamorphicCacheDeserializationCluster : public DeserializationCluster { : DeserializationCluster("MegamorphicCache") {} ~MegamorphicCacheDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2799,8 +2726,7 @@ class MegamorphicCacheDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { MegamorphicCachePtr cache = static_cast(d->Ref(id)); Deserializer::InitializeHeader(cache, kMegamorphicCacheCid, @@ -2811,7 +2737,7 @@ class MegamorphicCacheDeserializationCluster : public DeserializationCluster { } #if defined(DART_PRECOMPILED_RUNTIME) - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { if (FLAG_use_bare_instructions) { // By default, every megamorphic call site will load the target // [Function] from the hash table and call indirectly via loading the @@ -2880,7 +2806,7 @@ class SubtypeTestCacheDeserializationCluster : public DeserializationCluster { : DeserializationCluster("SubtypeTestCache") {} ~SubtypeTestCacheDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2891,8 +2817,7 @@ class SubtypeTestCacheDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { SubtypeTestCachePtr cache = static_cast(d->Ref(id)); Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid, @@ -2944,7 +2869,7 @@ class LoadingUnitDeserializationCluster : public DeserializationCluster { LoadingUnitDeserializationCluster() : DeserializationCluster("LoadingUnit") {} ~LoadingUnitDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -2955,8 +2880,7 @@ class LoadingUnitDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { LoadingUnitPtr unit = static_cast(d->Ref(id)); Deserializer::InitializeHeader(unit, kLoadingUnitCid, @@ -3015,7 +2939,7 @@ class LanguageErrorDeserializationCluster : public DeserializationCluster { : DeserializationCluster("LanguageError") {} ~LanguageErrorDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3026,8 +2950,7 @@ class LanguageErrorDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { LanguageErrorPtr error = static_cast(d->Ref(id)); Deserializer::InitializeHeader(error, kLanguageErrorCid, @@ -3083,7 +3006,7 @@ class UnhandledExceptionDeserializationCluster : public DeserializationCluster { : DeserializationCluster("UnhandledException") {} ~UnhandledExceptionDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3094,8 +3017,7 @@ class UnhandledExceptionDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { UnhandledExceptionPtr exception = static_cast(d->Ref(id)); @@ -3204,35 +3126,13 @@ class InstanceSerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class AbstractInstanceDeserializationCluster : public DeserializationCluster { - protected: - explicit AbstractInstanceDeserializationCluster(const char* name) - : DeserializationCluster(name) {} - - public: - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - Thread* thread = Thread::Current(); - SafepointMutexLocker ml( - thread->isolate_group()->constant_canonicalization_mutex()); - Instance& instance = Instance::Handle(d->zone()); - for (intptr_t i = start_index_; i < stop_index_; i++) { - instance ^= refs.At(i); - instance = instance.CanonicalizeLocked(thread); - refs.SetAt(i, instance); - } - } - } -}; - -class InstanceDeserializationCluster - : public AbstractInstanceDeserializationCluster { +class InstanceDeserializationCluster : public DeserializationCluster { public: explicit InstanceDeserializationCluster(intptr_t cid) - : AbstractInstanceDeserializationCluster("Instance"), cid_(cid) {} + : DeserializationCluster("Instance"), cid_(cid) {} ~InstanceDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3246,7 +3146,7 @@ class InstanceDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2; intptr_t instance_size = Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize); @@ -3255,7 +3155,7 @@ class InstanceDeserializationCluster for (intptr_t id = start_index_; id < stop_index_; id++) { InstancePtr instance = static_cast(d->Ref(id)); Deserializer::InitializeHeader(instance, cid_, instance_size, - stamp_canonical); + is_canonical); intptr_t offset = Instance::NextFieldOffset(); while (offset < next_field_offset) { if (unboxed_fields_bitmap.Get(offset / kWordSize)) { @@ -3330,7 +3230,7 @@ class LibraryPrefixDeserializationCluster : public DeserializationCluster { : DeserializationCluster("LibraryPrefix") {} ~LibraryPrefixDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3341,8 +3241,7 @@ class LibraryPrefixDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { LibraryPrefixPtr prefix = static_cast(d->Ref(id)); Deserializer::InitializeHeader(prefix, kLibraryPrefixCid, @@ -3425,7 +3324,7 @@ class TypeDeserializationCluster : public DeserializationCluster { TypeDeserializationCluster() : DeserializationCluster("Type") {} ~TypeDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3435,11 +3334,11 @@ class TypeDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TypePtr type = static_cast(d->Ref(id)); Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(), - stamp_canonical); + is_canonical); ReadFromTo(type); const uint8_t combined = d->Read(); type->untag()->type_state_ = combined >> kNullabilityBitSize; @@ -3447,15 +3346,20 @@ class TypeDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - Thread* thread = Thread::Current(); - AbstractType& type = AbstractType::Handle(d->zone()); + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalTypeSet table( + d->zone(), d->isolate_group()->object_store()->canonical_types()); + Type& type = Type::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { type ^= refs.At(i); - type = type.Canonicalize(thread, nullptr); - refs.SetAt(i, type); + ASSERT(type.IsCanonical()); + bool present = table.Insert(type); + // Two recursive types with different topology (and hashes) may be + // equal. + ASSERT(!present || type.IsRecursive()); } + d->isolate_group()->object_store()->set_canonical_types(table.Release()); } Type& type = Type::Handle(d->zone()); @@ -3536,7 +3440,7 @@ class FunctionTypeDeserializationCluster : public DeserializationCluster { : DeserializationCluster("FunctionType") {} ~FunctionTypeDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3547,12 +3451,11 @@ class FunctionTypeDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { FunctionTypePtr type = static_cast(d->Ref(id)); - Deserializer::InitializeHeader(type, kFunctionTypeCid, - FunctionType::InstanceSize(), - stamp_canonical); + Deserializer::InitializeHeader( + type, kFunctionTypeCid, FunctionType::InstanceSize(), is_canonical); ReadFromTo(type); const uint8_t combined = d->Read(); type->untag()->type_state_ = combined >> kNullabilityBitSize; @@ -3561,15 +3464,22 @@ class FunctionTypeDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - Thread* thread = Thread::Current(); - AbstractType& type = AbstractType::Handle(d->zone()); + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalFunctionTypeSet table( + d->zone(), + d->isolate_group()->object_store()->canonical_function_types()); + FunctionType& type = FunctionType::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { type ^= refs.At(i); - type = type.Canonicalize(thread, nullptr); - refs.SetAt(i, type); + ASSERT(type.IsCanonical()); + bool present = table.Insert(type); + // Two recursive types with different topology (and hashes) may be + // equal. + ASSERT(!present || type.IsRecursive()); } + d->isolate_group()->object_store()->set_canonical_function_types( + table.Release()); } FunctionType& type = FunctionType::Handle(d->zone()); @@ -3632,7 +3542,7 @@ class TypeRefDeserializationCluster : public DeserializationCluster { TypeRefDeserializationCluster() : DeserializationCluster("TypeRef") {} ~TypeRefDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3642,16 +3552,16 @@ class TypeRefDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TypeRefPtr type = static_cast(d->Ref(id)); - Deserializer::InitializeHeader(type, kTypeRefCid, TypeRef::InstanceSize(), - stamp_canonical); + Deserializer::InitializeHeader(type, kTypeRefCid, + TypeRef::InstanceSize()); ReadFromTo(type); } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { TypeRef& type_ref = TypeRef::Handle(d->zone()); Code& stub = Code::Handle(d->zone()); @@ -3731,7 +3641,7 @@ class TypeParameterDeserializationCluster : public DeserializationCluster { : DeserializationCluster("TypeParameter") {} ~TypeParameterDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3742,12 +3652,11 @@ class TypeParameterDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TypeParameterPtr type = static_cast(d->Ref(id)); - Deserializer::InitializeHeader(type, kTypeParameterCid, - TypeParameter::InstanceSize(), - stamp_canonical); + Deserializer::InitializeHeader( + type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical); ReadFromTo(type); type->untag()->parameterized_class_id_ = d->Read(); type->untag()->base_ = d->Read(); @@ -3758,15 +3667,20 @@ class TypeParameterDeserializationCluster : public DeserializationCluster { } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - Thread* thread = Thread::Current(); + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalTypeParameterSet table( + d->zone(), + d->isolate_group()->object_store()->canonical_type_parameters()); TypeParameter& type_param = TypeParameter::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { type_param ^= refs.At(i); - type_param ^= type_param.Canonicalize(thread, nullptr); - refs.SetAt(i, type_param); + ASSERT(type_param.IsCanonical()); + bool present = table.Insert(type_param); + ASSERT(!present); } + d->isolate_group()->object_store()->set_canonical_type_parameters( + table.Release()); } TypeParameter& type_param = TypeParameter::Handle(d->zone()); @@ -3825,14 +3739,12 @@ class ClosureSerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class ClosureDeserializationCluster - : public AbstractInstanceDeserializationCluster { +class ClosureDeserializationCluster : public DeserializationCluster { public: - ClosureDeserializationCluster() - : AbstractInstanceDeserializationCluster("Closure") {} + ClosureDeserializationCluster() : DeserializationCluster("Closure") {} ~ClosureDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3842,11 +3754,11 @@ class ClosureDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ClosurePtr closure = static_cast(d->Ref(id)); Deserializer::InitializeHeader(closure, kClosureCid, - Closure::InstanceSize(), stamp_canonical); + Closure::InstanceSize(), is_canonical); ReadFromTo(closure); } } @@ -3899,7 +3811,7 @@ class MintDeserializationCluster : public DeserializationCluster { MintDeserializationCluster() : DeserializationCluster("int") {} ~MintDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { PageSpace* old_space = d->heap()->old_space(); start_index_ = d->next_index(); @@ -3912,7 +3824,7 @@ class MintDeserializationCluster : public DeserializationCluster { MintPtr mint = static_cast( AllocateUninitialized(old_space, Mint::InstanceSize())); Deserializer::InitializeHeader(mint, kMintCid, Mint::InstanceSize(), - stamp_canonical); + is_canonical); mint->untag()->value_ = value; d->AssignRef(mint); } @@ -3920,24 +3832,19 @@ class MintDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) {} + void ReadFill(Deserializer* d, bool is_canonical) {} - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { const Class& mint_cls = Class::Handle( - d->zone(), d->isolate_group()->object_store()->mint_class()); + d->zone(), IsolateGroup::Current()->object_store()->mint_class()); + mint_cls.set_constants(Object::null_array()); Object& number = Object::Handle(d->zone()); - Mint& number2 = Mint::Handle(d->zone()); for (intptr_t i = start_index_; i < stop_index_; i++) { number = refs.At(i); - if (!number.IsMint()) continue; - number2 = - mint_cls.LookupCanonicalMint(d->zone(), Mint::Cast(number).value()); - if (number2.IsNull()) { - number.SetCanonical(); + if (number.IsMint()) { + ASSERT(number.IsCanonical()); mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number)); - } else { - refs.SetAt(i, number2); } } } @@ -3984,7 +3891,7 @@ class DoubleDeserializationCluster : public DeserializationCluster { DoubleDeserializationCluster() : DeserializationCluster("double") {} ~DoubleDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -3994,35 +3901,14 @@ class DoubleDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { DoublePtr dbl = static_cast(d->Ref(id)); Deserializer::InitializeHeader(dbl, kDoubleCid, Double::InstanceSize(), - stamp_canonical); + is_canonical); dbl->untag()->value_ = d->Read(); } } - - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - const Class& cls = Class::Handle( - d->zone(), d->isolate_group()->object_store()->double_class()); - SafepointMutexLocker ml( - d->isolate_group()->constant_canonicalization_mutex()); - Double& dbl = Double::Handle(d->zone()); - Double& dbl2 = Double::Handle(d->zone()); - for (intptr_t i = start_index_; i < stop_index_; i++) { - dbl ^= refs.At(i); - dbl2 = cls.LookupCanonicalDouble(d->zone(), dbl.value()); - if (dbl2.IsNull()) { - dbl.SetCanonical(); - cls.InsertCanonicalDouble(d->zone(), dbl); - } else { - refs.SetAt(i, dbl2); - } - } - } - } }; #if !defined(DART_PRECOMPILED_RUNTIME) @@ -4069,7 +3955,7 @@ class GrowableObjectArrayDeserializationCluster : DeserializationCluster("GrowableObjectArray") {} ~GrowableObjectArrayDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4080,13 +3966,13 @@ class GrowableObjectArrayDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { GrowableObjectArrayPtr list = static_cast(d->Ref(id)); Deserializer::InitializeHeader(list, kGrowableObjectArrayCid, GrowableObjectArray::InstanceSize(), - stamp_canonical); + is_canonical); ReadFromTo(list); } } @@ -4142,7 +4028,7 @@ class TypedDataDeserializationCluster : public DeserializationCluster { : DeserializationCluster("TypedData"), cid_(cid) {} ~TypedDataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4155,17 +4041,15 @@ class TypedDataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { intptr_t element_size = TypedData::ElementSizeInBytes(cid_); for (intptr_t id = start_index_; id < stop_index_; id++) { TypedDataPtr data = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); const intptr_t length_in_bytes = length * element_size; - Deserializer::InitializeHeader(data, cid_, - TypedData::InstanceSize(length_in_bytes), - stamp_canonical); + Deserializer::InitializeHeader( + data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical); data->untag()->length_ = Smi::New(length); data->untag()->RecomputeDataField(); uint8_t* cdata = reinterpret_cast(data->untag()->data()); @@ -4222,7 +4106,7 @@ class TypedDataViewDeserializationCluster : public DeserializationCluster { : DeserializationCluster("TypedDataView"), cid_(cid) {} ~TypedDataViewDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4233,17 +4117,16 @@ class TypedDataViewDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TypedDataViewPtr view = static_cast(d->Ref(id)); - Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize()); + Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize(), + is_canonical); ReadFromTo(view); } } - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - ASSERT(!canonicalize); + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { auto& view = TypedDataView::Handle(d->zone()); for (intptr_t id = start_index_; id < stop_index_; id++) { view ^= refs.At(id); @@ -4303,7 +4186,7 @@ class ExternalTypedDataDeserializationCluster : public DeserializationCluster { : DeserializationCluster("ExternalTypedData"), cid_(cid) {} ~ExternalTypedDataDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4314,8 +4197,7 @@ class ExternalTypedDataDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_); for (intptr_t id = start_index_; id < stop_index_; id++) { @@ -4376,7 +4258,7 @@ class StackTraceDeserializationCluster : public DeserializationCluster { StackTraceDeserializationCluster() : DeserializationCluster("StackTrace") {} ~StackTraceDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4387,8 +4269,7 @@ class StackTraceDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { StackTracePtr trace = static_cast(d->Ref(id)); Deserializer::InitializeHeader(trace, kStackTraceCid, @@ -4442,7 +4323,7 @@ class RegExpDeserializationCluster : public DeserializationCluster { RegExpDeserializationCluster() : DeserializationCluster("RegExp") {} ~RegExpDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4452,8 +4333,7 @@ class RegExpDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { RegExpPtr regexp = static_cast(d->Ref(id)); Deserializer::InitializeHeader(regexp, kRegExpCid, @@ -4508,7 +4388,7 @@ class WeakPropertyDeserializationCluster : public DeserializationCluster { : DeserializationCluster("WeakProperty") {} ~WeakPropertyDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4519,8 +4399,7 @@ class WeakPropertyDeserializationCluster : public DeserializationCluster { stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { - ASSERT(!stamp_canonical); // Never canonical. + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { WeakPropertyPtr property = static_cast(d->Ref(id)); Deserializer::InitializeHeader(property, kWeakPropertyCid, @@ -4599,14 +4478,13 @@ class LinkedHashMapSerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class LinkedHashMapDeserializationCluster - : public AbstractInstanceDeserializationCluster { +class LinkedHashMapDeserializationCluster : public DeserializationCluster { public: LinkedHashMapDeserializationCluster() - : AbstractInstanceDeserializationCluster("LinkedHashMap") {} + : DeserializationCluster("LinkedHashMap") {} ~LinkedHashMapDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4617,14 +4495,13 @@ class LinkedHashMapDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { PageSpace* old_space = d->heap()->old_space(); for (intptr_t id = start_index_; id < stop_index_; id++) { LinkedHashMapPtr map = static_cast(d->Ref(id)); - Deserializer::InitializeHeader(map, kLinkedHashMapCid, - LinkedHashMap::InstanceSize(), - stamp_canonical); + Deserializer::InitializeHeader( + map, kLinkedHashMapCid, LinkedHashMap::InstanceSize(), is_canonical); map->untag()->type_arguments_ = static_cast(d->ReadRef()); @@ -4708,14 +4585,13 @@ class ArraySerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class ArrayDeserializationCluster - : public AbstractInstanceDeserializationCluster { +class ArrayDeserializationCluster : public DeserializationCluster { public: explicit ArrayDeserializationCluster(intptr_t cid) - : AbstractInstanceDeserializationCluster("Array"), cid_(cid) {} + : DeserializationCluster("Array"), cid_(cid) {} ~ArrayDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4727,12 +4603,12 @@ class ArrayDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { ArrayPtr array = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); Deserializer::InitializeHeader(array, cid_, Array::InstanceSize(length), - stamp_canonical); + is_canonical); array->untag()->type_arguments_ = static_cast(d->ReadRef()); array->untag()->length_ = Smi::New(length); @@ -4787,40 +4663,13 @@ class OneByteStringSerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class StringDeserializationCluster : public DeserializationCluster { - protected: - explicit StringDeserializationCluster(const char* name) - : DeserializationCluster(name) {} - - public: - void PostLoad(Deserializer* d, const Array& refs, bool canonicalize) { - if (canonicalize) { - CanonicalStringSet table( - d->zone(), d->isolate_group()->object_store()->symbol_table()); - String& str = String::Handle(d->zone()); - String& str2 = String::Handle(d->zone()); - for (intptr_t i = start_index_; i < stop_index_; i++) { - str ^= refs.At(i); - str2 ^= table.InsertOrGet(str); - if (str.ptr() == str2.ptr()) { - str.SetCanonical(); - } else { - refs.SetAt(i, str2); - } - } - d->isolate_group()->object_store()->set_symbol_table(table.Release()); - } - } -}; - -class OneByteStringDeserializationCluster - : public StringDeserializationCluster { +class OneByteStringDeserializationCluster : public DeserializationCluster { public: OneByteStringDeserializationCluster() - : StringDeserializationCluster("OneByteString") {} + : DeserializationCluster("OneByteString") {} ~OneByteStringDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4832,13 +4681,13 @@ class OneByteStringDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { OneByteStringPtr str = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); Deserializer::InitializeHeader(str, kOneByteStringCid, OneByteString::InstanceSize(length), - stamp_canonical); + is_canonical); str->untag()->length_ = Smi::New(length); StringHasher hasher; for (intptr_t j = 0; j < length; j++) { @@ -4849,6 +4698,21 @@ class OneByteStringDeserializationCluster String::SetCachedHash(str, hasher.Finalize()); } } + + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalStringSet table( + d->zone(), d->isolate_group()->object_store()->symbol_table()); + String& str = String::Handle(d->zone()); + for (intptr_t i = start_index_; i < stop_index_; i++) { + str ^= refs.At(i); + ASSERT(str.IsCanonical()); + bool present = table.Insert(str); + ASSERT(!present); + } + d->isolate_group()->object_store()->set_symbol_table(table.Release()); + } + } }; #if !defined(DART_PRECOMPILED_RUNTIME) @@ -4893,14 +4757,13 @@ class TwoByteStringSerializationCluster : public SerializationCluster { }; #endif // !DART_PRECOMPILED_RUNTIME -class TwoByteStringDeserializationCluster - : public StringDeserializationCluster { +class TwoByteStringDeserializationCluster : public DeserializationCluster { public: TwoByteStringDeserializationCluster() - : StringDeserializationCluster("TwoByteString") {} + : DeserializationCluster("TwoByteString") {} ~TwoByteStringDeserializationCluster() {} - void ReadAlloc(Deserializer* d, bool stamp_canonical) { + void ReadAlloc(Deserializer* d, bool is_canonical) { start_index_ = d->next_index(); PageSpace* old_space = d->heap()->old_space(); const intptr_t count = d->ReadUnsigned(); @@ -4912,13 +4775,13 @@ class TwoByteStringDeserializationCluster stop_index_ = d->next_index(); } - void ReadFill(Deserializer* d, bool stamp_canonical) { + void ReadFill(Deserializer* d, bool is_canonical) { for (intptr_t id = start_index_; id < stop_index_; id++) { TwoByteStringPtr str = static_cast(d->Ref(id)); const intptr_t length = d->ReadUnsigned(); Deserializer::InitializeHeader(str, kTwoByteStringCid, TwoByteString::InstanceSize(length), - stamp_canonical); + is_canonical); str->untag()->length_ = Smi::New(length); StringHasher hasher; for (intptr_t j = 0; j < length; j++) { @@ -4930,6 +4793,21 @@ class TwoByteStringDeserializationCluster String::SetCachedHash(str, hasher.Finalize()); } } + + void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) { + if (is_canonical && (d->isolate() != Dart::vm_isolate())) { + CanonicalStringSet table( + d->zone(), d->isolate_group()->object_store()->symbol_table()); + String& str = String::Handle(d->zone()); + for (intptr_t i = start_index_; i < stop_index_; i++) { + str ^= refs.At(i); + ASSERT(str.IsCanonical()); + bool present = table.Insert(str); + ASSERT(!present); + } + d->isolate_group()->object_store()->set_symbol_table(table.Release()); + } + } }; #if !defined(DART_PRECOMPILED_RUNTIME) @@ -5309,26 +5187,16 @@ class UnitSerializationRoots : public SerializationRoots { const Object* deferred_object = (*unit_->deferred_objects())[i]; ASSERT(deferred_object->IsCode()); CodePtr code = static_cast(deferred_object->ptr()); - if (FLAG_use_bare_instructions) { - if (FLAG_retain_function_objects) { - ObjectPoolPtr pool = code->untag()->object_pool_; - if (pool != ObjectPool::null()) { - const intptr_t length = pool->untag()->length_; - uint8_t* entry_bits = pool->untag()->entry_bits(); - for (intptr_t i = 0; i < length; i++) { - auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); - if (entry_type == ObjectPool::EntryType::kTaggedObject) { - s->Push(pool->untag()->data()[i].raw_obj_); - } - } - } - } - } else { - s->Push(code->untag()->object_pool_); - } s->Push(code->untag()->compressed_stackmaps_); s->Push(code->untag()->code_source_map_); } + { + GrowableArray raw_codes(num_deferred_objects); + for (intptr_t i = 0; i < num_deferred_objects; i++) { + raw_codes.Add((*unit_->deferred_objects())[i]->ptr()); + } + s->PrepareInstructions(&raw_codes); + } } void WriteRoots(Serializer* s) { @@ -5348,33 +5216,9 @@ class UnitSerializationRoots : public SerializationRoots { ASSERT(s->RefId(code) == (start_index + i)); s->WriteInstructions(code->untag()->instructions_, code->untag()->unchecked_offset_, code, false); - if (!FLAG_use_bare_instructions) { - s->WriteRootRef(code->untag()->object_pool_, "deferred-code"); - } s->WriteRootRef(code->untag()->compressed_stackmaps_, "deferred-code"); s->WriteRootRef(code->untag()->code_source_map_, "deferred-code"); } - - if (FLAG_use_bare_instructions && FLAG_retain_function_objects) { - ObjectPoolPtr pool = - s->isolate_group()->object_store()->global_object_pool(); - const intptr_t length = pool->untag()->length_; - uint8_t* entry_bits = pool->untag()->entry_bits(); - intptr_t last_write = 0; - for (intptr_t i = 0; i < length; i++) { - auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); - if (entry_type == ObjectPool::EntryType::kTaggedObject) { - if (s->IsWritten(pool->untag()->data()[i].raw_obj_)) { - intptr_t skip = i - last_write; - s->WriteUnsigned(skip); - s->WriteRootRef(pool->untag()->data()[i].raw_obj_, - "deferred-literal"); - last_write = i; - } - } - } - s->WriteUnsigned(length - last_write); - } #endif } @@ -5410,29 +5254,12 @@ class UnitDeserializationRoots : public DeserializationRoots { ASSERT(unchecked_entry_point != 0); func->untag()->unchecked_entry_point_ = unchecked_entry_point; } - if (!FLAG_use_bare_instructions) { - code->untag()->object_pool_ = static_cast(d->ReadRef()); - } code->untag()->compressed_stackmaps_ = static_cast(d->ReadRef()); code->untag()->code_source_map_ = static_cast(d->ReadRef()); } - if (FLAG_use_bare_instructions && FLAG_retain_function_objects) { - ObjectPoolPtr pool = - d->isolate_group()->object_store()->global_object_pool(); - const intptr_t length = pool->untag()->length_; - uint8_t* entry_bits = pool->untag()->entry_bits(); - for (intptr_t i = d->ReadUnsigned(); i < length; i += d->ReadUnsigned()) { - auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]); - ASSERT(entry_type == ObjectPool::EntryType::kTaggedObject); - // The existing entry will usually be null, but it might also be an - // equivalent object that was duplicated in another loading unit. - pool->untag()->data()[i].raw_obj_ = d->ReadRef(); - } - } - // Reinitialize the dispatch table by rereading the table's serialization // in the root snapshot. IsolateGroup* group = d->thread()->isolate()->group(); @@ -5845,9 +5672,6 @@ bool Serializer::InCurrentLoadingUnit(ObjectPtr obj, bool record) { // TODO(41974): Are these always type testing stubs? unit_id = LoadingUnit::kRootId; } - if (unit_id == LoadingUnit::kRootId) { - return true; - } if (unit_id != current_loading_unit_id_) { if (record) { (*loading_units_)[unit_id]->AddDeferredObject(static_cast(obj)); @@ -5858,58 +5682,11 @@ bool Serializer::InCurrentLoadingUnit(ObjectPtr obj, bool record) { } #if !defined(DART_PRECOMPILED_RUNTIME) -void Serializer::PrepareInstructions() { - if (!Snapshot::IncludesCode(kind())) return; - - CodeSerializationCluster* cluster = - static_cast(clusters_by_cid_[kCodeCid]); - - // Code objects that have identical/duplicate instructions must be adjacent in - // the order that Code objects are written because the encoding of the - // reference from the Code to the Instructions assumes monotonically - // increasing offsets as part of a delta encoding. Also the code order table - // that allows for mapping return addresses back to Code objects depends on - // this sorting. - if (cluster != nullptr) { - CodeSerializationCluster::Sort(cluster->objects()); - } - if ((loading_units_ != nullptr) && - (current_loading_unit_id_ == LoadingUnit::kRootId)) { - for (intptr_t i = LoadingUnit::kRootId + 1; i < loading_units_->length(); - i++) { - auto unit_objects = loading_units_->At(i)->deferred_objects(); - CodeSerializationCluster::Sort(unit_objects); - for (intptr_t j = 0; j < unit_objects->length(); j++) { - cluster->deferred_objects()->Add(unit_objects->At(j)->ptr()); - } - } - } - +void Serializer::PrepareInstructions(GrowableArray* code_objects) { #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) if ((kind() == Snapshot::kFullAOT) && FLAG_use_bare_instructions) { - // Group the code objects whose instructions are not being deferred in this - // snapshot unit in the order they will be written: first the code objects - // encountered for this first time in this unit being written by the - // CodeSerializationCluster, then code object previously deferred whose - // instructions are now written by UnitSerializationRoots. This order needs - // to be known to finalize bare-instructions-mode's PC-relative calls. - GrowableArray code_objects; - if (cluster != nullptr) { - auto in = cluster->objects(); - for (intptr_t i = 0; i < in->length(); i++) { - code_objects.Add(in->At(i)); - } - } - if (loading_units_ != nullptr) { - auto in = - loading_units_->At(current_loading_unit_id_)->deferred_objects(); - for (intptr_t i = 0; i < in->length(); i++) { - code_objects.Add(in->At(i)->ptr()); - } - } - GrowableArray writer_commands; - RelocateCodeObjects(vm_, &code_objects, &writer_commands); + RelocateCodeObjects(vm_, code_objects, &writer_commands); image_writer_->PrepareForSerialization(&writer_commands); } #endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) @@ -6117,22 +5894,6 @@ ZoneGrowableArray* Serializer::Serialize(SerializationRoots* roots) { } GrowableArray canonical_clusters; - // The order that PostLoad runs matters for some classes. Explicitly place - // these clusters first, then add the rest ordered by class id. -#define ADD_NEXT(cid) \ - if (canonical_clusters_by_cid_[cid] != nullptr) { \ - canonical_clusters.Add(canonical_clusters_by_cid_[cid]); \ - canonical_clusters_by_cid_[cid] = nullptr; \ - } - ADD_NEXT(kOneByteStringCid) - ADD_NEXT(kTwoByteStringCid) - ADD_NEXT(kMintCid) - ADD_NEXT(kDoubleCid) - ADD_NEXT(kTypeParameterCid) - ADD_NEXT(kTypeCid) - ADD_NEXT(kTypeArgumentsCid) - ADD_NEXT(kClosureCid) -#undef ADD_NEXT for (intptr_t cid = 0; cid < num_cids_; cid++) { if (canonical_clusters_by_cid_[cid] != nullptr) { canonical_clusters.Add(canonical_clusters_by_cid_[cid]); @@ -6159,8 +5920,6 @@ ZoneGrowableArray* Serializer::Serialize(SerializationRoots* roots) { } #endif - PrepareInstructions(); - intptr_t num_objects = num_base_objects_ + num_written_objects_; #if defined(ARCH_IS_64_BIT) if (!Utils::IsInt(32, num_objects)) { @@ -6278,7 +6037,8 @@ void Serializer::WriteDispatchTable(const Array& entries) { ASSERT(code_cluster != nullptr); // Reference IDs in a cluster are allocated sequentially, so we can use the // first code object's reference ID to calculate the cluster index. - const intptr_t first_code_id = RefId(code_cluster->objects()->At(0)); + const intptr_t first_code_id = + RefId(code_cluster->discovered_objects()->At(0)); // The first object in the code cluster must have its reference ID allocated. ASSERT(IsAllocatedReference(first_code_id)); @@ -6968,17 +6728,18 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects_); { - TIMELINE_DURATION(thread(), Isolate, "PostLoad"); + TIMELINE_DURATION(thread(), Isolate, "ReadFill"); for (intptr_t i = 0; i < num_canonical_clusters_; i++) { - bool stamp_canonical = isolate() == Dart::vm_isolate(); - canonical_clusters_[i]->ReadFill(this, stamp_canonical); + TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name()); + canonical_clusters_[i]->ReadFill(this, /*is_canonical*/ true); #if defined(DEBUG) int32_t section_marker = Read(); ASSERT(section_marker == kSectionMarker); #endif } for (intptr_t i = 0; i < num_clusters_; i++) { - clusters_[i]->ReadFill(this, /*stamp_canonical*/ false); + TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name()); + clusters_[i]->ReadFill(this, /*is_canonical*/ false); #if defined(DEBUG) int32_t section_marker = Read(); ASSERT(section_marker == kSectionMarker); @@ -6999,22 +6760,26 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { roots->PostLoad(this, refs); #if defined(DEBUG) - isolate()->ValidateClassTable(); - if (isolate() != Dart::vm_isolate()) { - isolate_group()->heap()->Verify(); + Isolate* isolate = thread()->isolate(); + isolate->ValidateClassTable(); + if (isolate != Dart::vm_isolate()) { + isolate->group()->heap()->Verify(); } #endif + // TODO(rmacnak): When splitting literals, load clusters requiring + // canonicalization first, canonicalize and update the ref array, the load + // the remaining clusters to avoid a full heap walk to update references to + // the losers of any canonicalization races. { TIMELINE_DURATION(thread(), Isolate, "PostLoad"); for (intptr_t i = 0; i < num_canonical_clusters_; i++) { TIMELINE_DURATION(thread(), Isolate, canonical_clusters_[i]->name()); - bool canonicalize = isolate() != Dart::vm_isolate(); - canonical_clusters_[i]->PostLoad(this, refs, canonicalize); + canonical_clusters_[i]->PostLoad(this, refs, /*is_canonical*/ true); } for (intptr_t i = 0; i < num_clusters_; i++) { TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name()); - clusters_[i]->PostLoad(this, refs, /*canonicalize*/ false); + clusters_[i]->PostLoad(this, refs, /*is_canonical*/ false); } } } diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h index d35b83a49d6..ac72aedccb2 100644 --- a/runtime/vm/clustered_snapshot.h +++ b/runtime/vm/clustered_snapshot.h @@ -116,20 +116,16 @@ class DeserializationCluster : public ZoneAllocated { // Allocate memory for all objects in the cluster and write their addresses // into the ref array. Do not touch this memory. - virtual void ReadAlloc(Deserializer* deserializer, bool stamp_canonical) = 0; + virtual void ReadAlloc(Deserializer* deserializer, bool is_canonical) = 0; // Initialize the cluster's objects. Do not touch the memory of other objects. - virtual void ReadFill(Deserializer* deserializer, bool stamp_canonical) = 0; + virtual void ReadFill(Deserializer* deserializer, bool is_canonical) = 0; // Complete any action that requires the full graph to be deserialized, such // as rehashing. virtual void PostLoad(Deserializer* deserializer, const Array& refs, - bool canonicalize) { - if (canonicalize) { - FATAL1("%s needs canonicalization but doesn't define PostLoad", name()); - } - } + bool is_canonical) {} const char* name() const { return name_; } @@ -351,7 +347,7 @@ class Serializer : public ThreadStackResource { Write(cid); } - void PrepareInstructions(); + void PrepareInstructions(GrowableArray* codes); void WriteInstructions(InstructionsPtr instr, uint32_t unchecked_offset, CodePtr code, @@ -384,7 +380,6 @@ class Serializer : public ThreadStackResource { void set_loading_units(GrowableArray* units) { loading_units_ = units; } - intptr_t current_loading_unit_id() { return current_loading_unit_id_; } void set_current_loading_unit_id(intptr_t id) { current_loading_unit_id_ = id; } @@ -419,13 +414,6 @@ class Serializer : public ThreadStackResource { FATAL("Missing ref"); } - bool HasRef(ObjectPtr object) const { - return heap_->GetObjectId(object) != kUnreachableReference; - } - bool IsWritten(ObjectPtr object) const { - return heap_->GetObjectId(object) > num_base_objects_; - } - private: const char* ReadOnlyObjectType(intptr_t cid); @@ -585,8 +573,6 @@ class Deserializer : public ThreadStackResource { uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); } - intptr_t position() const { return stream_.Position(); } - void set_position(intptr_t p) { stream_.SetPosition(p); } const uint8_t* CurrentBufferAddress() const { return stream_.AddressOfCurrentPosition(); } diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc index ff5ea612a40..f19bbbd62e5 100644 --- a/runtime/vm/compiler/relocation.cc +++ b/runtime/vm/compiler/relocation.cc @@ -71,15 +71,8 @@ void CodeRelocator::Relocate(bool is_vm_isolate) { // We're guaranteed to have all calls resolved, since // * backwards calls are resolved eagerly // * forward calls are resolved once the target is written - if (!all_unresolved_calls_.IsEmpty()) { - for (auto call : all_unresolved_calls_) { - OS::PrintErr("Unresolved call to %s from %s\n", - Object::Handle(call->callee).ToCString(), - Object::Handle(call->caller).ToCString()); - } - } - RELEASE_ASSERT(all_unresolved_calls_.IsEmpty()); - RELEASE_ASSERT(unresolved_calls_by_destination_.IsEmpty()); + ASSERT(all_unresolved_calls_.IsEmpty()); + ASSERT(unresolved_calls_by_destination_.IsEmpty()); // Any trampolines we created must be patched with the right offsets. auto it = trampolines_by_destination_.GetIterator(); diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 969444401fa..5bdddc8a3a6 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -86,7 +86,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 8; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 48; + 52; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word Class_super_type_offset = 44; @@ -611,7 +611,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 16; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 96; + 104; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word Class_super_type_offset = 88; @@ -1140,7 +1140,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 8; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 48; + 52; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word Class_super_type_offset = 44; @@ -1662,7 +1662,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 16; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 96; + 104; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word Class_super_type_offset = 88; @@ -2194,7 +2194,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 8; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 48; + 52; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word Class_super_type_offset = 44; @@ -2713,7 +2713,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 16; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 96; + 104; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word Class_super_type_offset = 88; @@ -3236,7 +3236,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 8; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 48; + 52; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word Class_super_type_offset = 44; @@ -3752,7 +3752,7 @@ static constexpr dart::compiler::target::word Array_length_offset = 16; static constexpr dart::compiler::target::word Array_tags_offset = 0; static constexpr dart::compiler::target::word Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word Class_declaration_type_offset = - 96; + 104; static constexpr dart::compiler::target::word Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word Class_super_type_offset = 88; @@ -4280,7 +4280,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 48; + AOT_Class_declaration_type_offset = 52; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 44; @@ -4864,7 +4864,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 96; + AOT_Class_declaration_type_offset = 104; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88; @@ -5454,7 +5454,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 96; + AOT_Class_declaration_type_offset = 104; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88; @@ -6043,7 +6043,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 4; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 48; + AOT_Class_declaration_type_offset = 52; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 88; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 44; @@ -6620,7 +6620,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 96; + AOT_Class_declaration_type_offset = 104; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88; @@ -7203,7 +7203,7 @@ static constexpr dart::compiler::target::word AOT_Array_tags_offset = 0; static constexpr dart::compiler::target::word AOT_Array_type_arguments_offset = 8; static constexpr dart::compiler::target::word - AOT_Class_declaration_type_offset = 96; + AOT_Class_declaration_type_offset = 104; static constexpr dart::compiler::target::word AOT_Class_num_type_arguments_offset = 164; static constexpr dart::compiler::target::word AOT_Class_super_type_offset = 88; diff --git a/runtime/vm/compiler/type_testing_stubs_arm.cc b/runtime/vm/compiler/type_testing_stubs_arm.cc index ccd9d361e36..ed1ace2230c 100644 --- a/runtime/vm/compiler/type_testing_stubs_arm.cc +++ b/runtime/vm/compiler/type_testing_stubs_arm.cc @@ -20,8 +20,16 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStub( const Type& type, const Class& type_class) { BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class); - __ Branch(compiler::Address( - THR, compiler::target::Thread::slow_type_test_entry_point_offset())); + if (!compiler::IsSameObject( + compiler::NullObject(), + compiler::CastHandle(slow_type_test_stub))) { + __ GenerateUnRelocatedPcRelativeTailCall(); + unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall( + __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true)); + } else { + __ Branch(compiler::Address( + THR, compiler::target::Thread::slow_type_test_entry_point_offset())); + } } } // namespace dart diff --git a/runtime/vm/compiler/type_testing_stubs_arm64.cc b/runtime/vm/compiler/type_testing_stubs_arm64.cc index 850b198fa7f..0540b01efd6 100644 --- a/runtime/vm/compiler/type_testing_stubs_arm64.cc +++ b/runtime/vm/compiler/type_testing_stubs_arm64.cc @@ -20,11 +20,19 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStub( const Type& type, const Class& type_class) { BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class); - __ ldr( - TMP, - compiler::Address( - THR, compiler::target::Thread::slow_type_test_entry_point_offset())); - __ br(TMP); + if (!compiler::IsSameObject( + compiler::NullObject(), + compiler::CastHandle(slow_type_test_stub))) { + __ GenerateUnRelocatedPcRelativeTailCall(); + unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall( + __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true)); + } else { + __ ldr(TMP, + compiler::Address( + THR, + compiler::target::Thread::slow_type_test_entry_point_offset())); + __ br(TMP); + } } } // namespace dart diff --git a/runtime/vm/compiler/type_testing_stubs_x64.cc b/runtime/vm/compiler/type_testing_stubs_x64.cc index 7722ceeee63..f7a974cff60 100644 --- a/runtime/vm/compiler/type_testing_stubs_x64.cc +++ b/runtime/vm/compiler/type_testing_stubs_x64.cc @@ -20,8 +20,16 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStub( const Type& type, const Class& type_class) { BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class); - __ jmp(compiler::Address( - THR, compiler::target::Thread::slow_type_test_entry_point_offset())); + if (!compiler::IsSameObject( + compiler::NullObject(), + compiler::CastHandle(slow_type_test_stub))) { + __ GenerateUnRelocatedPcRelativeTailCall(); + unresolved_calls->Add(new compiler::UnresolvedPcRelativeCall( + __ CodeSize(), slow_type_test_stub, /*is_tail_call=*/true)); + } else { + __ jmp(compiler::Address( + THR, compiler::target::Thread::slow_type_test_entry_point_offset())); + } } } // namespace dart diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index fae18dfad9e..d98aa2d4274 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -20212,11 +20212,9 @@ AbstractTypePtr Type::Canonicalize(Thread* thread, TrailPtr trail) const { } } ASSERT(this->Equals(type)); - // TODO(rmacnak): Revisit immediately returning type after to changes to - // recanonicalization on load for literal splitting. - if (type.IsCanonical()) { - return type.ptr(); - } + ASSERT(type.IsCanonical()); + ASSERT(type.IsOld()); + return type.ptr(); } Type& type = Type::Handle(zone); diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc index b8e3de13338..90829798d28 100644 --- a/runtime/vm/program_visitor.cc +++ b/runtime/vm/program_visitor.cc @@ -1371,15 +1371,9 @@ class AssignLoadingUnitsCodeVisitor : public CodeVisitor { MergeAssignment(obj_, id); obj_ = code.compressed_stackmaps(); MergeAssignment(obj_, id); - if (!FLAG_use_bare_instructions) { - obj_ = code.object_pool(); - MergeAssignment(obj_, id); - } } void MergeAssignment(const Object& obj, intptr_t id) { - if (obj.IsNull()) return; - intptr_t old_id = heap_->GetLoadingUnit(obj_.ptr()); if (old_id == WeakTable::kNoValue) { heap_->SetLoadingUnit(obj_.ptr(), id); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 8a02e590c2b..d209ad2b8da 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -28,8 +28,8 @@ // * Target architecture // * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT) // -// That is, fields in UntaggedObject and its subclasses should only be included or -// excluded conditionally based on these factors. Otherwise, the generated +// That is, fields in UntaggedObject and its subclasses should only be included +// or excluded conditionally based on these factors. Otherwise, the generated // offsets can be wrong (which should be caught by offset checking in dart.cc). // // TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis. @@ -819,6 +819,8 @@ class UntaggedClass : public UntaggedObject { POINTER_FIELD(LibraryPtr, library) POINTER_FIELD(TypeArgumentsPtr, type_parameters) // Array of TypeParameter. POINTER_FIELD(AbstractTypePtr, super_type) + POINTER_FIELD(ArrayPtr, + constants) // Canonicalized const instances of this class. POINTER_FIELD(TypePtr, declaration_type) // Declaration type for this class. POINTER_FIELD(ArrayPtr, invocation_dispatcher_cache) // Cache for dispatcher functions. @@ -828,9 +830,7 @@ class UntaggedClass : public UntaggedObject { direct_implementors) // Array of Class. POINTER_FIELD(GrowableObjectArrayPtr, direct_subclasses) // Array of Class. POINTER_FIELD(ArrayPtr, dependent_code) // CHA optimized codes. - POINTER_FIELD(ArrayPtr, - constants) // Canonicalized const instances of this class. - VISIT_TO(ObjectPtr, constants) + VISIT_TO(ObjectPtr, dependent_code) ObjectPtr* to_snapshot(Snapshot::Kind kind) { switch (kind) { case Snapshot::kFullAOT: @@ -1642,8 +1642,6 @@ class UntaggedObjectPool : public UntaggedObject { friend class Object; friend class CodeSerializationCluster; - friend class UnitSerializationRoots; - friend class UnitDeserializationRoots; }; class UntaggedInstructions : public UntaggedObject {