[vm] Remove the VM isolate.
The former contents of the VM isolate are now included into each isolate group. This makes each isolate group's heap independent, and in particular allows each heap to be allocated to a separate pointer cage (not done in this CL). The duplicated stubs that allowed PC relative calls are removed, since the originals can now be the target of PC relative calls. The bootstrapping needing to load an AppJIT or AppAOT snapshot is reduced to allocating the oddballs. The code is entirely dropped in the AOT runtime, but the JIT runtime still has it to allow for flags to affect the compilation of the stub code. Further refactoring might be able to remove this for the JIT runtime too, with only gen_snapshot knowing how to bootstrap. Class serialization no longer distinguishes predefined classes. The page containing null is marked as never-evacuate. null, false and true must not move because the compiler relies on their low bits having certain patterns for some optimizations. (Previously, the entire VM isolate heap never moved.) Compaction is disabled for IA32. Due to register pressure, some stub calls must not use a scratch register and embed the address of Code. The page containing the call-through-safepoint stub is frozen when running with --write-protect-code and the stub is created at runtime (instead of loaded from an AppJIT or AppAOT snapshot). This stub must remain executable even during a safepoint, as a foreign call might during return during a safepoint and only block after the stub directs it to the runtime. The snapshot symbols are renamed to kDartSnapshotData and kDartSnapshotText. There is no need to distinguish the VM isolate's snapshot, and snaphots are per isolate group not per isolate. Aliases with the old names are added to ease migration. Some global flags that were automatically set based on the VM isolate's snapshot are now isolate group flags and automatically set by the isolate group's snapshot. TEST=ci Change-Id: Iee82016057d609112e9b021d178fc3d4d18b5044 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/500621 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com> SLSA-Policy-Verified: SLSA Policy Verification Service <devtools-gerritcodereview-exitgate@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
ca9c12f1b6
commit
d36adbacaf
@@ -703,11 +703,10 @@ trace to find the place to insert the appropriate support.
|
||||
if self.get_option(['-o', '--output']):
|
||||
self.outputs.append(self.rebase(self.optarg))
|
||||
elif self.get_option([
|
||||
'--vm_snapshot_data',
|
||||
'--vm_snapshot_instructions',
|
||||
'--isolate_snapshot_data',
|
||||
'--isolate_snapshot_instructions',
|
||||
'--snapshot_data',
|
||||
'--snapshot_text',
|
||||
'--elf',
|
||||
'--macho',
|
||||
'--ffi_callback_stub',
|
||||
]):
|
||||
self.outputs.append(self.rebase(self.optarg))
|
||||
|
||||
@@ -152,10 +152,6 @@ extension ComputedOffsets on VMOffsets {
|
||||
// Symbol names used in Dart snapshots.
|
||||
|
||||
const String snapshotBuildIdAsmSymbol = "_kDartSnapshotBuildId";
|
||||
const String vmSnapshotDataAsmSymbol = "_kDartVmSnapshotData";
|
||||
const String vmSnapshotInstructionsAsmSymbol = "_kDartVmSnapshotInstructions";
|
||||
const String vmSnapshotBssAsmSymbol = "_kDartVmSnapshotBss";
|
||||
const String isolateSnapshotDataAsmSymbol = "_kDartIsolateSnapshotData";
|
||||
const String isolateSnapshotInstructionsAsmSymbol =
|
||||
"_kDartIsolateSnapshotInstructions";
|
||||
const String isolateSnapshotBssAsmSymbol = "_kDartIsolateSnapshotBss";
|
||||
const String snapshotDataAsmSymbol = "_kDartSnapshotData";
|
||||
const String snapshotTextAsmSymbol = "_kDartSnapshotText";
|
||||
const String snapshotBssAsmSymbol = "_kDartSnapshotBss";
|
||||
|
||||
@@ -894,35 +894,35 @@ final class Arm64VMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get ObjectStore_int_type_offset => 0x168;
|
||||
@override
|
||||
int get ObjectStore_record_field_names_offset => 0x430;
|
||||
int get ObjectStore_record_field_names_offset => 0x440;
|
||||
@override
|
||||
int get ObjectStore_string_type_offset => 0x1e0;
|
||||
@override
|
||||
int get ObjectStore_type_type_offset => 0x140;
|
||||
@override
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x530;
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x540;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_offset => 0x480;
|
||||
int get ObjectStore_suspend_state_await_offset => 0x490;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x488;
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x498;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c8;
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4d8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x478;
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x488;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4a0;
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4b0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b8;
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4c8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x490;
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x4a0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x498;
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x4a8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4b0;
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4c0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4c0;
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4d0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a8;
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4b8;
|
||||
@override
|
||||
int get OneByteString_data_offset => 0x10;
|
||||
@override
|
||||
@@ -1372,7 +1372,7 @@ final class Arm64VMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get Capability_InstanceSize => 0x10;
|
||||
@override
|
||||
int get Class_InstanceSize => 0xc8;
|
||||
int get Class_InstanceSize => 0xd8;
|
||||
@override
|
||||
int get ClosureData_InstanceSize => 0x28;
|
||||
@override
|
||||
@@ -1857,35 +1857,35 @@ final class Arm64ProductVMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get ObjectStore_int_type_offset => 0x168;
|
||||
@override
|
||||
int get ObjectStore_record_field_names_offset => 0x430;
|
||||
int get ObjectStore_record_field_names_offset => 0x440;
|
||||
@override
|
||||
int get ObjectStore_string_type_offset => 0x1e0;
|
||||
@override
|
||||
int get ObjectStore_type_type_offset => 0x140;
|
||||
@override
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x530;
|
||||
int get ObjectStore_ffi_callback_code_offset => 0x540;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_offset => 0x480;
|
||||
int get ObjectStore_suspend_state_await_offset => 0x490;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x488;
|
||||
int get ObjectStore_suspend_state_await_with_type_check_offset => 0x498;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4c8;
|
||||
int get ObjectStore_suspend_state_handle_exception_offset => 0x4d8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x478;
|
||||
int get ObjectStore_suspend_state_init_async_offset => 0x488;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4a0;
|
||||
int get ObjectStore_suspend_state_init_async_star_offset => 0x4b0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4b8;
|
||||
int get ObjectStore_suspend_state_init_sync_star_offset => 0x4c8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x490;
|
||||
int get ObjectStore_suspend_state_return_async_offset => 0x4a0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x498;
|
||||
int get ObjectStore_suspend_state_return_async_not_future_offset => 0x4a8;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4b0;
|
||||
int get ObjectStore_suspend_state_return_async_star_offset => 0x4c0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4c0;
|
||||
int get ObjectStore_suspend_state_suspend_sync_star_at_start_offset => 0x4d0;
|
||||
@override
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4a8;
|
||||
int get ObjectStore_suspend_state_yield_async_star_offset => 0x4b8;
|
||||
@override
|
||||
int get OneByteString_data_offset => 0x10;
|
||||
@override
|
||||
@@ -2333,7 +2333,7 @@ final class Arm64ProductVMOffsets extends VMOffsets {
|
||||
@override
|
||||
int get Capability_InstanceSize => 0x10;
|
||||
@override
|
||||
int get Class_InstanceSize => 0xc0;
|
||||
int get Class_InstanceSize => 0xd0;
|
||||
@override
|
||||
int get ClosureData_InstanceSize => 0x28;
|
||||
@override
|
||||
|
||||
@@ -162,8 +162,14 @@ final class MachoImageWriter extends ImageWriter {
|
||||
|
||||
MachoImageWriter(this.targetCPU, this.libraryName) {
|
||||
header = Header(this);
|
||||
symbolTable.addSymbol(isolateSnapshotInstructionsAsmSymbol, textSection, 0);
|
||||
symbolTable.addSymbol(isolateSnapshotDataAsmSymbol, constSection, 0);
|
||||
symbolTable.addSymbol(snapshotTextAsmSymbol, textSection, 0);
|
||||
symbolTable.addSymbol(snapshotDataAsmSymbol, constSection, 0);
|
||||
|
||||
// TRANSITION
|
||||
symbolTable.addSymbol("_kDartVmSnapshotInstructions", textSection, 0);
|
||||
symbolTable.addSymbol("_kDartIsolateSnapshotInstructions", textSection, 0);
|
||||
symbolTable.addSymbol("_kDartVmSnapshotData", constSection, 0);
|
||||
symbolTable.addSymbol("_kDartIsolateSnapshotData", constSection, 0);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -26,7 +26,7 @@ import 'package:native_compiler/runtime/vm_defs.dart';
|
||||
|
||||
/// Kinds of Dart snapshots.
|
||||
/// Should match Snapshot::Kind enum in runtime/vm/snapshot.h.
|
||||
enum SnapshotKind { full, fullCore, fullJIT, fullAOT, module, none, invalid }
|
||||
enum SnapshotKind { full, fullJIT, fullAOT, module, invalid }
|
||||
|
||||
/// Dart snapshot constants.
|
||||
class Snapshot {
|
||||
|
||||
@@ -258,10 +258,6 @@ void find(ArgResults options) {
|
||||
}
|
||||
vmStart = address;
|
||||
}
|
||||
if (vmStart == null) {
|
||||
return usageError('no VM start address found, one must be specified '
|
||||
'with --vm_start');
|
||||
}
|
||||
|
||||
var isolateStart = dwarf.isolateStartAddress();
|
||||
if (options['isolate_start'] != null) {
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
// 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.
|
||||
|
||||
export 'src/constants.dart'
|
||||
show
|
||||
isolateDataSymbolName,
|
||||
isolateSymbolName,
|
||||
vmDataSymbolName,
|
||||
vmSymbolName;
|
||||
export 'src/constants.dart' show dataSymbolName, textSymbolName;
|
||||
export 'src/elf.dart'
|
||||
show
|
||||
DynamicTable,
|
||||
|
||||
@@ -9,17 +9,23 @@ const int buildIdNoteType = 3;
|
||||
// The name of a build ID note.
|
||||
const String buildIdNoteName = 'GNU';
|
||||
|
||||
// The dynamic symbol name for the VM instructions section.
|
||||
const String vmSymbolName = '_kDartVmSnapshotInstructions';
|
||||
|
||||
// The dynamic symbol name for the VM data section.
|
||||
const String vmDataSymbolName = '_kDartVmSnapshotData';
|
||||
|
||||
// The dynamic symbol name for the isolate instructions section.
|
||||
const String isolateSymbolName = '_kDartIsolateSnapshotInstructions';
|
||||
const String textSymbolName = '_kDartSnapshotText';
|
||||
|
||||
// The dynamic symbol name for the isolate data section.
|
||||
const String isolateDataSymbolName = '_kDartIsolateSnapshotData';
|
||||
const String dataSymbolName = '_kDartSnapshotData';
|
||||
|
||||
// The ID for the root loading unit.
|
||||
const int rootLoadingUnitId = 1;
|
||||
|
||||
// The dynamic symbol name for the VM instructions section.
|
||||
const String oldVmSymbolName = '_kDartVmSnapshotInstructions';
|
||||
|
||||
// The dynamic symbol name for the VM data section.
|
||||
const String oldVmDataSymbolName = '_kDartVmSnapshotData';
|
||||
|
||||
// The dynamic symbol name for the isolate instructions section.
|
||||
const String oldIsolateSymbolName = '_kDartIsolateSnapshotInstructions';
|
||||
|
||||
// The dynamic symbol name for the isolate data section.
|
||||
const String oldIsolateDataSymbolName = '_kDartIsolateSnapshotData';
|
||||
|
||||
@@ -119,7 +119,7 @@ class StackTraceHeader {
|
||||
int? get isolateStart => _isolateStart;
|
||||
int? get isolateDsoBase => _isolateDsoBase;
|
||||
|
||||
static StackTraceHeader fromStarts(int isolateStart, int vmStart,
|
||||
static StackTraceHeader fromStarts(int isolateStart, int? vmStart,
|
||||
{String? architecture}) =>
|
||||
StackTraceHeader()
|
||||
.._isolateStart = isolateStart
|
||||
@@ -375,9 +375,11 @@ class StackTraceHeader {
|
||||
}
|
||||
if (offset == null) return null;
|
||||
switch (symbolString) {
|
||||
case constants.vmSymbolName:
|
||||
case constants.oldVmSymbolName:
|
||||
return (InstructionsSection.vm, offset);
|
||||
case constants.isolateSymbolName:
|
||||
case constants.oldIsolateSymbolName:
|
||||
return (InstructionsSection.isolate, offset);
|
||||
case constants.dataSymbolName:
|
||||
return (InstructionsSection.isolate, offset);
|
||||
default:
|
||||
break;
|
||||
@@ -420,9 +422,11 @@ PCOffset? tryParseSymbolOffset(String s,
|
||||
/// - The path to the snapshot, if it was loaded as a dynamic library,
|
||||
/// otherwise the string `"<unknown>"`.
|
||||
const _symbolOffsetREString = r'(?<symbol>' +
|
||||
constants.vmSymbolName +
|
||||
constants.textSymbolName +
|
||||
r'|' +
|
||||
constants.isolateSymbolName +
|
||||
constants.oldVmSymbolName +
|
||||
r'|' +
|
||||
constants.oldIsolateSymbolName +
|
||||
r')\+(?<offset>(?:0x)?[\da-f]+)';
|
||||
final _symbolOffsetRE = RegExp(_symbolOffsetREString);
|
||||
final _traceLineRE = RegExp(r'\s*#(\d+) abs (?<absolute>[\da-f]+)'
|
||||
|
||||
@@ -1283,11 +1283,12 @@ class Elf extends DwarfContainer {
|
||||
}
|
||||
|
||||
@override
|
||||
int? get vmStartAddress => dynamicSymbolFor(constants.vmSymbolName)?.value;
|
||||
int? get vmStartAddress => dynamicSymbolFor(constants.oldVmSymbolName)?.value;
|
||||
|
||||
@override
|
||||
int? get isolateStartAddress =>
|
||||
dynamicSymbolFor(constants.isolateSymbolName)?.value;
|
||||
dynamicSymbolFor(constants.textSymbolName)?.value ??
|
||||
dynamicSymbolFor(constants.oldIsolateSymbolName)?.value;
|
||||
|
||||
@override
|
||||
String? get buildId {
|
||||
|
||||
@@ -835,11 +835,12 @@ class MachO extends DwarfContainer {
|
||||
_dwarfSegment?.sections['__debug_info']?.shrink(containerReader);
|
||||
|
||||
@override
|
||||
int? get vmStartAddress => _symbolTable[constants.vmSymbolName]?.value;
|
||||
int? get vmStartAddress => _symbolTable[constants.oldVmSymbolName]?.value;
|
||||
|
||||
@override
|
||||
int? get isolateStartAddress =>
|
||||
_symbolTable[constants.isolateSymbolName]?.value;
|
||||
_symbolTable[constants.textSymbolName]?.value ??
|
||||
_symbolTable[constants.oldIsolateSymbolName]?.value;
|
||||
|
||||
@override
|
||||
String? get buildId =>
|
||||
|
||||
@@ -19,6 +19,8 @@ var tests = <IsolateTest>[
|
||||
|
||||
final classRef = entry.classRef!;
|
||||
print(classRef);
|
||||
if (classRef.name == 'Sentinel') continue;
|
||||
if (classRef.name == 'Null') continue;
|
||||
final instanceSet =
|
||||
await service.getInstances(isolateRef.id!, classRef.id!, 10);
|
||||
for (var instance in instanceSet.instances!) {
|
||||
|
||||
@@ -119,9 +119,6 @@ _TestClass? takeWeakUnreachableTarget() {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point') // Prevent obfuscation
|
||||
bool getTrue() => true;
|
||||
|
||||
Future<InstanceRef> invoke(String selector) async {
|
||||
return await rootService.invoke(
|
||||
isolateId,
|
||||
@@ -234,19 +231,6 @@ final tests = <IsolateTest>[
|
||||
final elements = result.elements!;
|
||||
expect(elements.length, 0);
|
||||
},
|
||||
|
||||
// object store
|
||||
(VmService service, IsolateRef isolateRef) async {
|
||||
final target = await invoke('getTrue');
|
||||
final result = await service.getRetainingPath(isolateId, target.id!, 100);
|
||||
expect(
|
||||
result.gcRootType == 'isolate_object store' ||
|
||||
result.gcRootType == 'class table',
|
||||
true,
|
||||
);
|
||||
final elements = result.elements!;
|
||||
expect(elements.length, 0);
|
||||
},
|
||||
];
|
||||
|
||||
void main([args = const <String>[]]) async => runIsolateTests(
|
||||
|
||||
@@ -82,7 +82,11 @@ ProgramInfo toProgramInfo(List<SymbolInfo> symbols,
|
||||
|
||||
// Handle stubs specially.
|
||||
if (libraryUri == null) {
|
||||
assert(sym.name.isStub);
|
||||
// The UnknownDartCode stub mostly pretends to be function code. This
|
||||
// seems to have originally been for the profiler to deal with collected
|
||||
// code. Is this still worthwhile?
|
||||
assert(
|
||||
sym.name.isStub || sym.name.raw == '[Unoptimized] <optimized out>');
|
||||
final node = program.makeNode(
|
||||
name: scrubbed, parent: program.stubs, type: NodeType.functionNode);
|
||||
assert(node.size == null || sym.name.isTypeTestingStub);
|
||||
|
||||
+22
-50
@@ -620,32 +620,22 @@ dart_io("common_embedder_dart_io_product") {
|
||||
extra_deps = [ ":libdart_builtin_product" ]
|
||||
}
|
||||
|
||||
gen_snapshot_action("generate_snapshot_bin") {
|
||||
gen_snapshot_action("core_snapshot_bin") {
|
||||
deps = [ "../vm:vm_platform_stripped" ]
|
||||
vm_snapshot_data = "$target_gen_dir/vm_snapshot_data.bin"
|
||||
vm_snapshot_instructions = "$target_gen_dir/vm_snapshot_instructions.bin"
|
||||
isolate_snapshot_data = "$target_gen_dir/isolate_snapshot_data.bin"
|
||||
isolate_snapshot_instructions =
|
||||
"$target_gen_dir/isolate_snapshot_instructions.bin"
|
||||
snapshot_data = "$target_gen_dir/core_snapshot_data.bin"
|
||||
snapshot_text = "$target_gen_dir/core_snapshot_text.bin"
|
||||
|
||||
platform_dill = "$root_out_dir/vm_platform_stripped.dill"
|
||||
inputs = [ platform_dill ]
|
||||
outputs = [
|
||||
vm_snapshot_data,
|
||||
vm_snapshot_instructions,
|
||||
isolate_snapshot_data,
|
||||
isolate_snapshot_instructions,
|
||||
snapshot_data,
|
||||
snapshot_text,
|
||||
]
|
||||
args = [
|
||||
"--deterministic",
|
||||
"--snapshot_kind=core",
|
||||
"--vm_snapshot_data=" + rebase_path(vm_snapshot_data, root_build_dir),
|
||||
"--vm_snapshot_instructions=" +
|
||||
rebase_path(vm_snapshot_instructions, root_build_dir),
|
||||
"--isolate_snapshot_data=" +
|
||||
rebase_path(isolate_snapshot_data, root_build_dir),
|
||||
"--isolate_snapshot_instructions=" +
|
||||
rebase_path(isolate_snapshot_instructions, root_build_dir),
|
||||
"--snapshot_data=" + rebase_path(snapshot_data, root_build_dir),
|
||||
"--snapshot_text=" + rebase_path(snapshot_text, root_build_dir),
|
||||
rebase_path(platform_dill, root_build_dir),
|
||||
]
|
||||
}
|
||||
@@ -758,31 +748,17 @@ template("bin_to_linkable") {
|
||||
}
|
||||
}
|
||||
|
||||
bin_to_linkable("vm_snapshot_data_linkable") {
|
||||
deps = [ ":generate_snapshot_bin" ]
|
||||
input = "$target_gen_dir/vm_snapshot_data.bin"
|
||||
symbol = "kDartVmSnapshotData"
|
||||
bin_to_linkable("core_snapshot_data_linkable") {
|
||||
deps = [ ":core_snapshot_bin" ]
|
||||
input = "$target_gen_dir/core_snapshot_data.bin"
|
||||
symbol = "kDartCoreSnapshotData"
|
||||
executable = false
|
||||
}
|
||||
|
||||
bin_to_linkable("vm_snapshot_instructions_linkable") {
|
||||
deps = [ ":generate_snapshot_bin" ]
|
||||
input = "$target_gen_dir/vm_snapshot_instructions.bin"
|
||||
symbol = "kDartVmSnapshotInstructions"
|
||||
executable = true
|
||||
}
|
||||
|
||||
bin_to_linkable("isolate_snapshot_data_linkable") {
|
||||
deps = [ ":generate_snapshot_bin" ]
|
||||
input = "$target_gen_dir/isolate_snapshot_data.bin"
|
||||
symbol = "kDartCoreIsolateSnapshotData"
|
||||
executable = false
|
||||
}
|
||||
|
||||
bin_to_linkable("isolate_snapshot_instructions_linkable") {
|
||||
deps = [ ":generate_snapshot_bin" ]
|
||||
input = "$target_gen_dir/isolate_snapshot_instructions.bin"
|
||||
symbol = "kDartCoreIsolateSnapshotInstructions"
|
||||
bin_to_linkable("core_snapshot_text_linkable") {
|
||||
deps = [ ":core_snapshot_bin" ]
|
||||
input = "$target_gen_dir/core_snapshot_text.bin"
|
||||
symbol = "kDartCoreSnapshotText"
|
||||
executable = true
|
||||
}
|
||||
|
||||
@@ -815,18 +791,14 @@ bin_to_linkable("icudtl_linkable") {
|
||||
executable = false
|
||||
}
|
||||
|
||||
source_set("dart_snapshot_cc") {
|
||||
source_set("core_snapshot_cc") {
|
||||
visibility = [ ":*" ]
|
||||
deps = [
|
||||
":isolate_snapshot_data_linkable",
|
||||
":isolate_snapshot_instructions_linkable",
|
||||
":vm_snapshot_data_linkable",
|
||||
":vm_snapshot_instructions_linkable",
|
||||
":core_snapshot_data_linkable",
|
||||
":core_snapshot_text_linkable",
|
||||
]
|
||||
sources = get_target_outputs(":isolate_snapshot_data_linkable") +
|
||||
get_target_outputs(":isolate_snapshot_instructions_linkable") +
|
||||
get_target_outputs(":vm_snapshot_data_linkable") +
|
||||
get_target_outputs(":vm_snapshot_instructions_linkable")
|
||||
sources = get_target_outputs(":core_snapshot_data_linkable") +
|
||||
get_target_outputs(":core_snapshot_text_linkable")
|
||||
}
|
||||
|
||||
source_set("dart_kernel_platform_cc") {
|
||||
@@ -966,7 +938,7 @@ template("dart_executable") {
|
||||
|
||||
dart_executable("dartvm") {
|
||||
extra_deps = [
|
||||
":dart_snapshot_cc",
|
||||
":core_snapshot_cc",
|
||||
"..:libdart_jit",
|
||||
"../platform:libdart_platform_jit",
|
||||
]
|
||||
@@ -1219,9 +1191,9 @@ executable("run_vm_tests") {
|
||||
|
||||
deps = [
|
||||
":common_embedder_dart_io",
|
||||
":core_snapshot_cc",
|
||||
":crashpad",
|
||||
":dart_kernel_platform_cc",
|
||||
":dart_snapshot_cc",
|
||||
":run_vm_tests_set",
|
||||
"..:libdart_precompiler_testing",
|
||||
"//third_party/boringssl", # for secure_socket_utils_test
|
||||
|
||||
@@ -60,10 +60,8 @@ static void PrintUsage() {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
const uint8_t* vm_snapshot_data = nullptr;
|
||||
const uint8_t* vm_snapshot_instructions = nullptr;
|
||||
const uint8_t* vm_isolate_data = nullptr;
|
||||
const uint8_t* vm_isolate_instructions = nullptr;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
|
||||
// Parse out the command line arguments. Returns -1 if the arguments
|
||||
// are incorrect, 0 otherwise.
|
||||
@@ -168,21 +166,18 @@ int RunAnalyzer(int argc, char** argv) {
|
||||
const char* script_name = nullptr;
|
||||
script_name = inputs.GetArgument(0);
|
||||
|
||||
auto* const app_snapshot = Snapshot::TryReadAppSnapshot(
|
||||
script_name, /*force_load_from_memory=*/true);
|
||||
std::unique_ptr<AppSnapshot> app_snapshot(Snapshot::TryReadAppSnapshot(
|
||||
script_name, /*force_load_from_memory=*/true));
|
||||
if (app_snapshot == nullptr) {
|
||||
Syslog::PrintErr("Cannot load snapshot file.\n");
|
||||
return kErrorExitCode;
|
||||
}
|
||||
app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
|
||||
&vm_isolate_data, &vm_isolate_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
|
||||
// Begin initialization
|
||||
Dart_InitializeParams init_params = {};
|
||||
memset(&init_params, 0, sizeof(init_params));
|
||||
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
init_params.vm_snapshot_data = vm_snapshot_data;
|
||||
init_params.vm_snapshot_instructions = vm_snapshot_instructions;
|
||||
|
||||
init_params.file_open = DartUtils::OpenFile;
|
||||
init_params.file_read = DartUtils::ReadFile;
|
||||
@@ -203,8 +198,8 @@ int RunAnalyzer(int argc, char** argv) {
|
||||
Dart_IsolateFlags isolate_flags;
|
||||
Dart_IsolateFlagsInitialize(&isolate_flags);
|
||||
|
||||
Dart_CreateIsolateGroup(nullptr, nullptr, vm_isolate_data,
|
||||
vm_isolate_instructions, &isolate_flags,
|
||||
Dart_CreateIsolateGroup(/*script_uri=*/nullptr, /*name=*/nullptr,
|
||||
snapshot_data, snapshot_text, &isolate_flags,
|
||||
isolate_group_data.get(),
|
||||
/*isolate_data=*/nullptr, &error);
|
||||
|
||||
@@ -215,8 +210,7 @@ int RunAnalyzer(int argc, char** argv) {
|
||||
}
|
||||
|
||||
dart::snapshot_analyzer::Dart_SnapshotAnalyzerInformation info = {
|
||||
vm_snapshot_data, vm_snapshot_instructions, vm_isolate_data,
|
||||
vm_isolate_instructions};
|
||||
snapshot_data, snapshot_text};
|
||||
|
||||
char* out = nullptr;
|
||||
intptr_t out_len = 0;
|
||||
@@ -230,8 +224,6 @@ int RunAnalyzer(int argc, char** argv) {
|
||||
|
||||
Dart_ExitScope();
|
||||
Dart_ShutdownIsolate();
|
||||
// Delete the returned AppSnapshot to avoid leaks.
|
||||
delete app_snapshot;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
+27
-35
@@ -108,8 +108,7 @@ typedef void (*Dart_ThreadDisableProfilingType)();
|
||||
typedef void (*Dart_ThreadEnableProfilingType)();
|
||||
typedef void (*Dart_AddSymbolsType)(const char*, void*, intptr_t);
|
||||
typedef void (*Dart_ExitIsolateType)();
|
||||
typedef Dart_Handle (
|
||||
*Dart_CreateSnapshotType)(uint8_t**, intptr_t*, uint8_t**, intptr_t*, bool);
|
||||
typedef Dart_Handle (*Dart_CreateSnapshotType)(uint8_t**, intptr_t*);
|
||||
typedef bool (*Dart_IsKernelType)(const uint8_t*, intptr_t);
|
||||
typedef bool (*Dart_IsBytecodeType)(const uint8_t*, intptr_t);
|
||||
typedef char* (*Dart_IsolateMakeRunnableType)(Dart_Isolate);
|
||||
@@ -1543,18 +1542,17 @@ bool Dart_IsVMFlagSet(const char* flag_name) {
|
||||
return Dart_IsVMFlagSetFn(flag_name);
|
||||
}
|
||||
|
||||
Dart_Isolate Dart_CreateIsolateGroup(
|
||||
const char* script_uri,
|
||||
const char* name,
|
||||
const uint8_t* isolate_snapshot_data,
|
||||
const uint8_t* isolate_snapshot_instructions,
|
||||
Dart_IsolateFlags* flags,
|
||||
void* isolate_group_data,
|
||||
void* isolate_data,
|
||||
char** error) {
|
||||
return Dart_CreateIsolateGroupFn(script_uri, name, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, isolate_data, error);
|
||||
Dart_Isolate Dart_CreateIsolateGroup(const char* script_uri,
|
||||
const char* name,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text,
|
||||
Dart_IsolateFlags* flags,
|
||||
void* isolate_group_data,
|
||||
void* isolate_data,
|
||||
char** error) {
|
||||
return Dart_CreateIsolateGroupFn(script_uri, name, snapshot_data,
|
||||
snapshot_text, flags, isolate_group_data,
|
||||
isolate_data, error);
|
||||
}
|
||||
|
||||
Dart_Isolate Dart_CreateIsolateInGroup(
|
||||
@@ -1698,14 +1696,9 @@ void Dart_ExitIsolate() {
|
||||
Dart_ExitIsolateFn();
|
||||
}
|
||||
|
||||
Dart_Handle Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
|
||||
intptr_t* vm_snapshot_data_size,
|
||||
uint8_t** isolate_snapshot_data_buffer,
|
||||
intptr_t* isolate_snapshot_data_size,
|
||||
bool is_core) {
|
||||
return Dart_CreateSnapshotFn(vm_snapshot_data_buffer, vm_snapshot_data_size,
|
||||
isolate_snapshot_data_buffer,
|
||||
isolate_snapshot_data_size, is_core);
|
||||
Dart_Handle Dart_CreateSnapshot(uint8_t** snapshot_data_buffer,
|
||||
intptr_t* snapshot_data_size) {
|
||||
return Dart_CreateSnapshotFn(snapshot_data_buffer, snapshot_data_size);
|
||||
}
|
||||
|
||||
bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
|
||||
@@ -2447,9 +2440,9 @@ Dart_Handle Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler) {
|
||||
|
||||
Dart_Handle Dart_DeferredLoadComplete(intptr_t loading_unit_id,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions) {
|
||||
const uint8_t* snapshot_text) {
|
||||
return Dart_DeferredLoadCompleteFn(loading_unit_id, snapshot_data,
|
||||
snapshot_instructions);
|
||||
snapshot_text);
|
||||
}
|
||||
|
||||
Dart_Handle Dart_DeferredLoadCompleteError(intptr_t loading_unit_id,
|
||||
@@ -2470,8 +2463,8 @@ Dart_Handle Dart_LoadScriptFromBytecode(const uint8_t* kernel_buffer,
|
||||
}
|
||||
|
||||
Dart_Handle Dart_LoadModuleSnapshot(const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions) {
|
||||
return Dart_LoadModuleSnapshotFn(snapshot_data, snapshot_instructions);
|
||||
const uint8_t* snapshot_text) {
|
||||
return Dart_LoadModuleSnapshotFn(snapshot_data, snapshot_text);
|
||||
}
|
||||
|
||||
Dart_Handle Dart_RootLibrary() {
|
||||
@@ -2610,12 +2603,12 @@ bool Dart_DetectNullSafety(const char* script_uri,
|
||||
const char* package_config,
|
||||
const char* original_working_directory,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size) {
|
||||
return Dart_DetectNullSafetyFn(
|
||||
script_uri, package_config, original_working_directory, snapshot_data,
|
||||
snapshot_instructions, kernel_buffer, kernel_buffer_size);
|
||||
snapshot_text, kernel_buffer, kernel_buffer_size);
|
||||
}
|
||||
|
||||
bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
|
||||
@@ -2715,14 +2708,13 @@ Dart_Handle Dart_SortClasses() {
|
||||
return Dart_SortClassesFn();
|
||||
}
|
||||
|
||||
Dart_Handle Dart_CreateAppJITSnapshotAsBlobs(
|
||||
uint8_t** isolate_snapshot_data_buffer,
|
||||
intptr_t* isolate_snapshot_data_size,
|
||||
uint8_t** isolate_snapshot_instructions_buffer,
|
||||
intptr_t* isolate_snapshot_instructions_size) {
|
||||
Dart_Handle Dart_CreateAppJITSnapshotAsBlobs(uint8_t** snapshot_data_buffer,
|
||||
intptr_t* snapshot_data_size,
|
||||
uint8_t** snapshot_text_buffer,
|
||||
intptr_t* snapshot_text_size) {
|
||||
return Dart_CreateAppJITSnapshotAsBlobsFn(
|
||||
isolate_snapshot_data_buffer, isolate_snapshot_data_size,
|
||||
isolate_snapshot_instructions_buffer, isolate_snapshot_instructions_size);
|
||||
snapshot_data_buffer, snapshot_data_size, snapshot_text_buffer,
|
||||
snapshot_text_size);
|
||||
}
|
||||
|
||||
Dart_Handle Dart_GetObfuscationMap(uint8_t** buffer, intptr_t* buffer_length) {
|
||||
|
||||
+11
-19
@@ -51,10 +51,8 @@ namespace bin {
|
||||
/**
|
||||
* Global state used to control and store generation of application snapshots.
|
||||
*/
|
||||
static const uint8_t* ignore_vm_snapshot_data = nullptr;
|
||||
static const uint8_t* ignore_vm_snapshot_instructions = nullptr;
|
||||
static const uint8_t* app_isolate_snapshot_data = nullptr;
|
||||
static const uint8_t* app_isolate_snapshot_instructions = nullptr;
|
||||
static const uint8_t* app_snapshot_data = nullptr;
|
||||
static const uint8_t* app_snapshot_text = nullptr;
|
||||
|
||||
#define SAVE_ERROR_AND_RETURN(result) \
|
||||
if (Dart_IsError(result)) { \
|
||||
@@ -239,11 +237,11 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
intptr_t kernel_buffer_size = 0;
|
||||
AppSnapshot* app_snapshot = nullptr;
|
||||
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
if (is_dartdev_isolate) {
|
||||
isolate_snapshot_data = app_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
|
||||
snapshot_data = app_snapshot_data;
|
||||
snapshot_text = app_snapshot_text;
|
||||
} else {
|
||||
// AOT: All isolates need to be run from AOT compiled snapshots.
|
||||
app_snapshot = Snapshot::TryReadAppSnapshot(
|
||||
@@ -256,9 +254,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
}
|
||||
|
||||
bool isolate_run_app_snapshot = true;
|
||||
@@ -275,9 +271,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
|
||||
IsolateData* isolate_data = nullptr;
|
||||
isolate_data = new IsolateData(isolate_group_data);
|
||||
isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, isolate_data, error);
|
||||
isolate =
|
||||
Dart_CreateIsolateGroup(script_uri, name, snapshot_data, snapshot_text,
|
||||
flags, isolate_group_data, isolate_data, error);
|
||||
Dart_Isolate created_isolate = nullptr;
|
||||
if (isolate == nullptr) {
|
||||
delete isolate_data;
|
||||
@@ -1086,9 +1082,7 @@ void main(int argc, char** argv) {
|
||||
FreeConvertedArgs(argc, argv, argv_converted);
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&app_isolate_snapshot_data, &app_isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&app_snapshot_data, &app_snapshot_text);
|
||||
|
||||
vm_options.AddArgument("--precompilation");
|
||||
|
||||
@@ -1117,8 +1111,6 @@ void main(int argc, char** argv) {
|
||||
Dart_InitializeParams init_params;
|
||||
memset(&init_params, 0, sizeof(init_params));
|
||||
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
init_params.vm_snapshot_data = ignore_vm_snapshot_data;
|
||||
init_params.vm_snapshot_instructions = ignore_vm_snapshot_instructions;
|
||||
init_params.create_group = CreateIsolateGroupAndSetup;
|
||||
init_params.initialize_isolate = OnIsolateInitialize;
|
||||
init_params.shutdown_isolate = OnIsolateShutdown;
|
||||
|
||||
+27
-48
@@ -52,10 +52,8 @@ class LoadedElf {
|
||||
/// sections corresponding to non-null output parameters in the BSS segment.
|
||||
///
|
||||
/// On failure, the error may be retrieved by 'error()'.
|
||||
bool ResolveSymbols(const uint8_t** vm_data,
|
||||
const uint8_t** vm_instrs,
|
||||
const uint8_t** isolate_data,
|
||||
const uint8_t** isolate_instrs);
|
||||
bool ResolveSymbols(const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
|
||||
const char* error() { return error_; }
|
||||
|
||||
@@ -362,10 +360,7 @@ bool LoadedElf::ReadSections() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadedElf::ResolveSymbols(const uint8_t** vm_data,
|
||||
const uint8_t** vm_instrs,
|
||||
const uint8_t** isolate_data,
|
||||
const uint8_t** isolate_instrs) {
|
||||
bool LoadedElf::ResolveSymbols(const uint8_t** data, const uint8_t** text) {
|
||||
if (error_ != nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -376,14 +371,10 @@ bool LoadedElf::ResolveSymbols(const uint8_t** vm_data,
|
||||
const char* name = dynamic_string_table_ + sym.name;
|
||||
const uint8_t** output = nullptr;
|
||||
|
||||
if (strcmp(name, kVmSnapshotDataAsmSymbol) == 0) {
|
||||
output = vm_data;
|
||||
} else if (strcmp(name, kVmSnapshotInstructionsAsmSymbol) == 0) {
|
||||
output = vm_instrs;
|
||||
} else if (strcmp(name, kIsolateSnapshotDataAsmSymbol) == 0) {
|
||||
output = isolate_data;
|
||||
} else if (strcmp(name, kIsolateSnapshotInstructionsAsmSymbol) == 0) {
|
||||
output = isolate_instrs;
|
||||
if (strcmp(name, kSnapshotDataAsmSymbol) == 0) {
|
||||
output = data;
|
||||
} else if (strcmp(name, kSnapshotTextAsmSymbol) == 0) {
|
||||
output = text;
|
||||
}
|
||||
|
||||
if (output != nullptr) {
|
||||
@@ -391,10 +382,10 @@ bool LoadedElf::ResolveSymbols(const uint8_t** vm_data,
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_ERROR(isolate_data == nullptr || *isolate_data != nullptr,
|
||||
"Could not find isolate snapshot data.");
|
||||
CHECK_ERROR(isolate_instrs == nullptr || *isolate_instrs != nullptr,
|
||||
"Could not find isolate instructions.");
|
||||
CHECK_ERROR(data == nullptr || *data != nullptr,
|
||||
"Could not find snapshot data.");
|
||||
CHECK_ERROR(text == nullptr || *text != nullptr,
|
||||
"Could not find snapshot text.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -425,20 +416,16 @@ using namespace dart::bin::elf; // NOLINT
|
||||
using Mappable = dart::bin::Mappable;
|
||||
|
||||
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd2(int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(Mappable::FromFD(fd));
|
||||
std::unique_ptr<LoadedElf> elf(
|
||||
new LoadedElf(std::move(mappable), file_offset));
|
||||
|
||||
if (!elf->Load() ||
|
||||
!elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!elf->Load() || !elf->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = elf->error();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -447,13 +434,11 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
|
||||
}
|
||||
#endif
|
||||
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF2(const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(Mappable::FromPath(filename));
|
||||
if (mappable == nullptr) {
|
||||
*error = "Couldn't open file.";
|
||||
@@ -462,9 +447,7 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
|
||||
std::unique_ptr<LoadedElf> elf(
|
||||
new LoadedElf(std::move(mappable), file_offset));
|
||||
|
||||
if (!elf->Load() ||
|
||||
!elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!elf->Load() || !elf->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = elf->error();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -472,14 +455,12 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
|
||||
return reinterpret_cast<Dart_LoadedElf*>(elf.release());
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory(
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory2(
|
||||
const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(
|
||||
Mappable::FromMemory(snapshot, snapshot_size));
|
||||
if (mappable == nullptr) {
|
||||
@@ -489,9 +470,7 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory(
|
||||
std::unique_ptr<LoadedElf> elf(
|
||||
new LoadedElf(std::move(mappable), /*elf_data_offset=*/0));
|
||||
|
||||
if (!elf->Load() ||
|
||||
!elf->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!elf->Load() || !elf->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = elf->error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+52
-25
@@ -19,41 +19,68 @@ typedef struct {
|
||||
/// `file_offset` may be non-zero to read an ELF object embedded inside another
|
||||
/// type of file.
|
||||
///
|
||||
/// Look up the Dart snapshot symbols "_kVmSnapshotData",
|
||||
/// "_kVmSnapshotInstructions", "_kVmIsolateData" and "_kVmIsolateInstructions"
|
||||
/// into the respectively named out-parameters.
|
||||
/// Look up the Dart snapshot symbols `_kDartSnapshotData` and
|
||||
/// `_kDartSnapshotText` into the respectively named out-parameters.
|
||||
///
|
||||
/// Dart_LoadELF_Fd takes ownership of the file descriptor. Dart_LoadELF_Memory
|
||||
/// does not take ownership of the memory, but borrows it for the duration of
|
||||
/// the call. The memory can be release as soon as Dart_LoadELF_Memory returns.
|
||||
#if defined(__Fuchsia__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd2(int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadELF_Fd2(fd, file_offset, error, snapshot_data, snapshot_text);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Please see documentation for Dart_LoadElf_Fd.
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF2(const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedElf* Dart_LoadELF(const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadELF2(filename, file_offset, error, snapshot_data,
|
||||
snapshot_text);
|
||||
}
|
||||
|
||||
/// Please see documentation for Dart_LoadElf_Fd.
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory(
|
||||
const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory2(const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedElf* Dart_LoadELF_Memory(const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadELF_Memory2(snapshot, snapshot_size, error, snapshot_data,
|
||||
snapshot_text);
|
||||
}
|
||||
|
||||
/// Unloads an ELF object loaded through Dart_LoadELF{_Fd, _Memory}.
|
||||
///
|
||||
|
||||
+92
-67
@@ -67,7 +67,7 @@ static bool ProcessEnvironmentOption(const char* arg,
|
||||
// The core snapshot to use when creating isolates. Normally nullptr, but loaded
|
||||
// from a file when creating AppJIT snapshots.
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* isolate_snapshot_text = nullptr;
|
||||
|
||||
// Global state that indicates whether a snapshot is to be created and
|
||||
// if so which file to write the snapshot into. The ordering of this list must
|
||||
@@ -109,7 +109,8 @@ static const char* const kSnapshotKindNames[] = {
|
||||
V(vm_snapshot_instructions, vm_snapshot_instructions_filename) \
|
||||
V(isolate_snapshot_data, isolate_snapshot_data_filename) \
|
||||
V(isolate_snapshot_instructions, isolate_snapshot_instructions_filename) \
|
||||
V(blobs_container_filename, blobs_container_filename) \
|
||||
V(snapshot_data, snapshot_data_filename) \
|
||||
V(snapshot_text, snapshot_text_filename) \
|
||||
V(assembly, assembly_filename) \
|
||||
V(elf, elf_filename) \
|
||||
V(macho, macho_filename) \
|
||||
@@ -162,8 +163,8 @@ static void PrintUsage() {
|
||||
" \n"
|
||||
"To create a core snapshot: \n"
|
||||
"--snapshot_kind=core \n"
|
||||
"--vm_snapshot_data=<output-file> \n"
|
||||
"--isolate_snapshot_data=<output-file> \n"
|
||||
"--snapshot_data=<output-file> \n"
|
||||
"--snapshot_text=<output-file> \n"
|
||||
"<dart-kernel-file> \n"
|
||||
" \n"
|
||||
"To create an AOT application snapshot as assembly suitable for compilation \n"
|
||||
@@ -253,25 +254,26 @@ static int ParseArguments(int argc,
|
||||
|
||||
switch (snapshot_kind) {
|
||||
case kCore: {
|
||||
if ((vm_snapshot_data_filename == nullptr) ||
|
||||
if ((snapshot_data_filename == nullptr) &&
|
||||
(isolate_snapshot_data_filename == nullptr)) {
|
||||
Syslog::PrintErr(
|
||||
"Building a core snapshot requires specifying output files for "
|
||||
"--vm_snapshot_data and --isolate_snapshot_data.\n\n");
|
||||
"--snapshot_data and --snapshot_text.\n\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kApp:
|
||||
case kAppJIT: {
|
||||
if ((load_vm_snapshot_data_filename == nullptr) ||
|
||||
(isolate_snapshot_data_filename == nullptr) ||
|
||||
(isolate_snapshot_instructions_filename == nullptr)) {
|
||||
if (((snapshot_data_filename == nullptr) &&
|
||||
(isolate_snapshot_data_filename == nullptr)) ||
|
||||
((snapshot_text_filename == nullptr) &&
|
||||
(isolate_snapshot_instructions_filename == nullptr))) {
|
||||
Syslog::PrintErr(
|
||||
"Building an app JIT snapshot requires specifying input files for "
|
||||
"--load_vm_snapshot_data and --load_vm_snapshot_instructions, an "
|
||||
" output file for --isolate_snapshot_data, and an output "
|
||||
"file for --isolate_snapshot_instructions.\n\n");
|
||||
" output file for --snapshot_data, and an output "
|
||||
"file for --snapshot_text.\n\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
@@ -424,36 +426,46 @@ static void MaybeLoadCode() {
|
||||
|
||||
static void CreateAndWriteCoreSnapshot() {
|
||||
ASSERT(snapshot_kind == kCore);
|
||||
ASSERT(vm_snapshot_data_filename != nullptr);
|
||||
ASSERT(isolate_snapshot_data_filename != nullptr);
|
||||
#if 0
|
||||
// TRANSITION
|
||||
ASSERT(snapshot_data_filename != nullptr);
|
||||
ASSERT(snapshot_text_filename != nullptr);
|
||||
#endif
|
||||
|
||||
Dart_Handle result;
|
||||
uint8_t* vm_snapshot_data_buffer = nullptr;
|
||||
intptr_t vm_snapshot_data_size = 0;
|
||||
uint8_t* isolate_snapshot_data_buffer = nullptr;
|
||||
intptr_t isolate_snapshot_data_size = 0;
|
||||
uint8_t* snapshot_data_buffer = nullptr;
|
||||
intptr_t snapshot_data_size = 0;
|
||||
|
||||
// First create a snapshot.
|
||||
result = Dart_CreateSnapshot(&vm_snapshot_data_buffer, &vm_snapshot_data_size,
|
||||
&isolate_snapshot_data_buffer,
|
||||
&isolate_snapshot_data_size,
|
||||
/*is_core=*/true);
|
||||
result = Dart_CreateSnapshot(&snapshot_data_buffer, &snapshot_data_size);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
// Now write the vm isolate and isolate snapshots out to the
|
||||
// specified file and exit.
|
||||
WriteFile(vm_snapshot_data_filename, vm_snapshot_data_buffer,
|
||||
vm_snapshot_data_size);
|
||||
if (snapshot_data_filename != nullptr) {
|
||||
WriteFile(snapshot_data_filename, snapshot_data_buffer, snapshot_data_size);
|
||||
}
|
||||
if (snapshot_text_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(snapshot_text_filename, nullptr, 0);
|
||||
}
|
||||
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (vm_snapshot_data_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(vm_snapshot_data_filename, nullptr, 0);
|
||||
}
|
||||
if (vm_snapshot_instructions_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(vm_snapshot_instructions_filename, nullptr, 0);
|
||||
}
|
||||
WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
|
||||
isolate_snapshot_data_size);
|
||||
if (isolate_snapshot_data_filename != nullptr) {
|
||||
WriteFile(isolate_snapshot_data_filename, snapshot_data_buffer,
|
||||
snapshot_data_size);
|
||||
}
|
||||
if (isolate_snapshot_instructions_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(isolate_snapshot_instructions_filename, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::unique_ptr<MappedMemory> MapFile(const char* filename,
|
||||
@@ -482,46 +494,71 @@ static std::unique_ptr<MappedMemory> MapFile(const char* filename,
|
||||
|
||||
static void CreateAndWriteAppSnapshot() {
|
||||
ASSERT(snapshot_kind == kApp);
|
||||
ASSERT(isolate_snapshot_data_filename != nullptr);
|
||||
ASSERT(snapshot_data_filename != nullptr);
|
||||
|
||||
Dart_Handle result;
|
||||
uint8_t* isolate_snapshot_data_buffer = nullptr;
|
||||
intptr_t isolate_snapshot_data_size = 0;
|
||||
uint8_t* snapshot_data_buffer = nullptr;
|
||||
intptr_t snapshot_data_size = 0;
|
||||
|
||||
result = Dart_CreateSnapshot(nullptr, nullptr, &isolate_snapshot_data_buffer,
|
||||
&isolate_snapshot_data_size, /*is_core=*/false);
|
||||
result = Dart_CreateSnapshot(&snapshot_data_buffer, &snapshot_data_size);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
|
||||
isolate_snapshot_data_size);
|
||||
if (snapshot_data_filename != nullptr) {
|
||||
WriteFile(snapshot_data_filename, snapshot_data_buffer, snapshot_data_size);
|
||||
}
|
||||
if (snapshot_text_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(snapshot_text_filename, nullptr, 0);
|
||||
}
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (isolate_snapshot_data_filename != nullptr) {
|
||||
WriteFile(isolate_snapshot_data_filename, snapshot_data_buffer,
|
||||
snapshot_data_size);
|
||||
}
|
||||
if (isolate_snapshot_instructions_filename != nullptr) {
|
||||
// Create empty file for the convenience of build systems.
|
||||
WriteFile(isolate_snapshot_instructions_filename, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void CreateAndWriteAppJITSnapshot() {
|
||||
ASSERT(snapshot_kind == kAppJIT);
|
||||
ASSERT(isolate_snapshot_data_filename != nullptr);
|
||||
ASSERT(isolate_snapshot_instructions_filename != nullptr);
|
||||
|
||||
#if 0
|
||||
// TRANSITION
|
||||
ASSERT(snapshot_data_filename != nullptr);
|
||||
ASSERT(snapshot_text_filename != nullptr);
|
||||
#endif
|
||||
Dart_Handle result;
|
||||
uint8_t* isolate_snapshot_data_buffer = nullptr;
|
||||
intptr_t isolate_snapshot_data_size = 0;
|
||||
uint8_t* isolate_snapshot_instructions_buffer = nullptr;
|
||||
intptr_t isolate_snapshot_instructions_size = 0;
|
||||
uint8_t* snapshot_data_buffer = nullptr;
|
||||
intptr_t snapshot_data_size = 0;
|
||||
uint8_t* snapshot_text_buffer = nullptr;
|
||||
intptr_t snapshot_text_size = 0;
|
||||
|
||||
result = Dart_CreateAppJITSnapshotAsBlobs(
|
||||
&isolate_snapshot_data_buffer, &isolate_snapshot_data_size,
|
||||
&isolate_snapshot_instructions_buffer,
|
||||
&isolate_snapshot_instructions_size);
|
||||
&snapshot_data_buffer, &snapshot_data_size, &snapshot_text_buffer,
|
||||
&snapshot_text_size);
|
||||
CHECK_RESULT(result);
|
||||
|
||||
WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
|
||||
isolate_snapshot_data_size);
|
||||
WriteFile(isolate_snapshot_instructions_filename,
|
||||
isolate_snapshot_instructions_buffer,
|
||||
isolate_snapshot_instructions_size);
|
||||
if (snapshot_data_filename != nullptr) {
|
||||
WriteFile(snapshot_data_filename, snapshot_data_buffer, snapshot_data_size);
|
||||
}
|
||||
if (snapshot_text_filename != nullptr) {
|
||||
WriteFile(snapshot_text_filename, snapshot_text_buffer, snapshot_text_size);
|
||||
}
|
||||
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (isolate_snapshot_data_filename != nullptr) {
|
||||
WriteFile(isolate_snapshot_data_filename, snapshot_data_buffer,
|
||||
snapshot_data_size);
|
||||
}
|
||||
if (isolate_snapshot_instructions_filename != nullptr) {
|
||||
WriteFile(isolate_snapshot_instructions_filename, snapshot_text_buffer,
|
||||
snapshot_text_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void StreamingWriteCallback(void* callback_data,
|
||||
@@ -791,8 +828,8 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) {
|
||||
loading_kernel_failed = (isolate == nullptr);
|
||||
} else {
|
||||
isolate = Dart_CreateIsolateGroup(nullptr, nullptr, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions,
|
||||
&isolate_flags, isolate_group_data.get(),
|
||||
isolate_snapshot_text, &isolate_flags,
|
||||
isolate_group_data.get(),
|
||||
/*isolate_data=*/nullptr, &error);
|
||||
}
|
||||
if (isolate == nullptr) {
|
||||
@@ -939,29 +976,17 @@ int main(int argc, char** argv) {
|
||||
init_params.entropy_source = DartUtils::EntropySource;
|
||||
init_params.start_kernel_isolate = false;
|
||||
|
||||
std::unique_ptr<MappedMemory> mapped_vm_snapshot_data;
|
||||
std::unique_ptr<MappedMemory> mapped_vm_snapshot_instructions;
|
||||
std::unique_ptr<MappedMemory> mapped_isolate_snapshot_data;
|
||||
std::unique_ptr<MappedMemory> mapped_isolate_snapshot_instructions;
|
||||
if (load_vm_snapshot_data_filename != nullptr) {
|
||||
mapped_vm_snapshot_data =
|
||||
MapFile(load_vm_snapshot_data_filename, File::kReadOnly,
|
||||
&init_params.vm_snapshot_data);
|
||||
}
|
||||
if (load_vm_snapshot_instructions_filename != nullptr) {
|
||||
mapped_vm_snapshot_instructions =
|
||||
MapFile(load_vm_snapshot_instructions_filename, File::kReadExecute,
|
||||
&init_params.vm_snapshot_instructions);
|
||||
}
|
||||
std::unique_ptr<MappedMemory> mapped_isolate_snapshot_text;
|
||||
if (load_isolate_snapshot_data_filename != nullptr) {
|
||||
mapped_isolate_snapshot_data =
|
||||
MapFile(load_isolate_snapshot_data_filename, File::kReadOnly,
|
||||
&isolate_snapshot_data);
|
||||
}
|
||||
if (load_isolate_snapshot_instructions_filename != nullptr) {
|
||||
mapped_isolate_snapshot_instructions =
|
||||
mapped_isolate_snapshot_text =
|
||||
MapFile(load_isolate_snapshot_instructions_filename, File::kReadExecute,
|
||||
&isolate_snapshot_instructions);
|
||||
&isolate_snapshot_text);
|
||||
}
|
||||
|
||||
error = Dart_Initialize(&init_params);
|
||||
|
||||
@@ -147,15 +147,11 @@ Dart_Handle Loader::DeferredLoadHandler(intptr_t loading_unit_id) {
|
||||
Dart_Handle result;
|
||||
if (loading_unit_snapshot != nullptr) {
|
||||
isolate_group_data->AddLoadedSnapshot(loading_unit_snapshot);
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
loading_unit_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
result = Dart_DeferredLoadComplete(loading_unit_id, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions);
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
loading_unit_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
result = Dart_DeferredLoadComplete(loading_unit_id, snapshot_data,
|
||||
snapshot_text);
|
||||
if (Dart_IsApiError(result)) {
|
||||
result =
|
||||
Dart_DeferredLoadCompleteError(loading_unit_id, Dart_GetError(result),
|
||||
|
||||
+24
-44
@@ -100,10 +100,8 @@ class LoadedMachODylib {
|
||||
/// sections corresponding to non-null output parameters in the BSS segment.
|
||||
///
|
||||
/// On failure, the error may be retrieved by 'error()'.
|
||||
bool ResolveSymbols(const uint8_t** vm_data,
|
||||
const uint8_t** vm_instrs,
|
||||
const uint8_t** isolate_data,
|
||||
const uint8_t** isolate_instrs);
|
||||
bool ResolveSymbols(const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
|
||||
const char* error() { return error_; }
|
||||
|
||||
@@ -473,10 +471,8 @@ bool LoadedMachODylib::ReadDynamicSymbolTable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadedMachODylib::ResolveSymbols(const uint8_t** vm_data,
|
||||
const uint8_t** vm_instrs,
|
||||
const uint8_t** isolate_data,
|
||||
const uint8_t** isolate_instrs) {
|
||||
bool LoadedMachODylib::ResolveSymbols(const uint8_t** data,
|
||||
const uint8_t** text) {
|
||||
if (error_ != nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -486,14 +482,10 @@ bool LoadedMachODylib::ResolveSymbols(const uint8_t** vm_data,
|
||||
const char* name = string_table_ + sym.n_idx;
|
||||
const uint8_t** output = nullptr;
|
||||
|
||||
if (strcmp(name, kVmSnapshotDataAsmSymbol) == 0) {
|
||||
output = vm_data;
|
||||
} else if (strcmp(name, kVmSnapshotInstructionsAsmSymbol) == 0) {
|
||||
output = vm_instrs;
|
||||
} else if (strcmp(name, kIsolateSnapshotDataAsmSymbol) == 0) {
|
||||
output = isolate_data;
|
||||
} else if (strcmp(name, kIsolateSnapshotInstructionsAsmSymbol) == 0) {
|
||||
output = isolate_instrs;
|
||||
if (strcmp(name, kSnapshotDataAsmSymbol) == 0) {
|
||||
output = data;
|
||||
} else if (strcmp(name, kSnapshotTextAsmSymbol) == 0) {
|
||||
output = text;
|
||||
}
|
||||
|
||||
if (output != nullptr) {
|
||||
@@ -501,10 +493,10 @@ bool LoadedMachODylib::ResolveSymbols(const uint8_t** vm_data,
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_ERROR(isolate_data == nullptr || *isolate_data != nullptr,
|
||||
"Could not find isolate snapshot data.");
|
||||
CHECK_ERROR(isolate_instrs == nullptr || *isolate_instrs != nullptr,
|
||||
"Could not find isolate instructions.");
|
||||
CHECK_ERROR(data == nullptr || *data != nullptr,
|
||||
"Could not find snapshot data.");
|
||||
CHECK_ERROR(text == nullptr || *text != nullptr,
|
||||
"Could not find snapshot text.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -536,21 +528,17 @@ using namespace dart::bin::mach_o; // NOLINT
|
||||
using Mappable = dart::bin::Mappable;
|
||||
|
||||
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd2(
|
||||
int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(Mappable::FromFD(fd));
|
||||
std::unique_ptr<LoadedMachODylib> macho(
|
||||
new LoadedMachODylib(std::move(mappable), file_offset));
|
||||
|
||||
if (!macho->Load() ||
|
||||
!macho->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!macho->Load() || !macho->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = macho->error();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -559,14 +547,12 @@ DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd(
|
||||
}
|
||||
#endif
|
||||
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib2(
|
||||
const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(Mappable::FromPath(filename));
|
||||
if (mappable == nullptr) {
|
||||
*error = "Couldn't open file.";
|
||||
@@ -575,9 +561,7 @@ DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib(
|
||||
std::unique_ptr<LoadedMachODylib> macho(
|
||||
new LoadedMachODylib(std::move(mappable), file_offset));
|
||||
|
||||
if (!macho->Load() ||
|
||||
!macho->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!macho->Load() || !macho->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = macho->error();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -585,14 +569,12 @@ DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib(
|
||||
return reinterpret_cast<Dart_LoadedMachODylib*>(macho.release());
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory2(
|
||||
const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs) {
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
std::unique_ptr<Mappable> mappable(
|
||||
Mappable::FromMemory(snapshot, snapshot_size));
|
||||
if (mappable == nullptr) {
|
||||
@@ -602,9 +584,7 @@ DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory(
|
||||
std::unique_ptr<LoadedMachODylib> macho(
|
||||
new LoadedMachODylib(std::move(mappable), /*macho_data_offset=*/0));
|
||||
|
||||
if (!macho->Load() ||
|
||||
!macho->ResolveSymbols(vm_snapshot_data, vm_snapshot_instrs,
|
||||
vm_isolate_data, vm_isolate_instrs)) {
|
||||
if (!macho->Load() || !macho->ResolveSymbols(snapshot_data, snapshot_text)) {
|
||||
*error = macho->error();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+48
-15
@@ -28,35 +28,68 @@ typedef struct {
|
||||
/// borrows it for the duration of the call. The memory can be release as soon
|
||||
// as Dart_LoadAOTSnapshot_Memory returns.
|
||||
#if defined(__Fuchsia__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd2(
|
||||
int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedMachODylib* Dart_LoadMachODylib_Fd(
|
||||
int fd,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadMachODylib_Fd2(fd, file_offset, error, snapshot_data,
|
||||
snapshot_text);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Please see documentation for Dart_LoadMachODylib_Fd.
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib2(
|
||||
const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedMachODylib* Dart_LoadMachODylib(
|
||||
const char* filename,
|
||||
uint64_t file_offset,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadMachODylib2(filename, file_offset, error, snapshot_data,
|
||||
snapshot_text);
|
||||
}
|
||||
|
||||
/// Please see documentation for Dart_LoadMachODylib_Fd.
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory(
|
||||
DART_EXPORT Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory2(
|
||||
const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_snapshot_data,
|
||||
const uint8_t** vm_snapshot_instrs,
|
||||
const uint8_t** vm_isolate_data,
|
||||
const uint8_t** vm_isolate_instrs);
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text);
|
||||
inline Dart_LoadedMachODylib* Dart_LoadMachODylib_Memory(
|
||||
const uint8_t* snapshot,
|
||||
uint64_t snapshot_size,
|
||||
const char** error,
|
||||
const uint8_t** vm_data,
|
||||
const uint8_t** vm_text,
|
||||
const uint8_t** snapshot_data,
|
||||
const uint8_t** snapshot_text) {
|
||||
*vm_data = nullptr;
|
||||
*vm_text = nullptr;
|
||||
return Dart_LoadMachODylib_Memory2(snapshot, snapshot_size, error,
|
||||
snapshot_data, snapshot_text);
|
||||
}
|
||||
|
||||
/// Unloads an MachO dynamic library object loaded through
|
||||
/// Dart_LoadMachODylib{_Fd, _Memory}.
|
||||
|
||||
+44
-75
@@ -41,21 +41,16 @@
|
||||
#include "platform/utils.h"
|
||||
|
||||
extern "C" {
|
||||
extern const uint8_t kDartVmSnapshotData[];
|
||||
extern const uint8_t kDartVmSnapshotInstructions[];
|
||||
extern const uint8_t kDartCoreIsolateSnapshotData[];
|
||||
extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
|
||||
extern const uint8_t kDartCoreSnapshotData[];
|
||||
extern const uint8_t kDartCoreSnapshotText[];
|
||||
}
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
// Snapshot pieces we link in a snapshot.
|
||||
const uint8_t* vm_snapshot_data = kDartVmSnapshotData;
|
||||
const uint8_t* vm_snapshot_instructions = kDartVmSnapshotInstructions;
|
||||
const uint8_t* core_isolate_snapshot_data = kDartCoreIsolateSnapshotData;
|
||||
const uint8_t* core_isolate_snapshot_instructions =
|
||||
kDartCoreIsolateSnapshotInstructions;
|
||||
const uint8_t* core_snapshot_data = kDartCoreSnapshotData;
|
||||
const uint8_t* core_snapshot_text = kDartCoreSnapshotText;
|
||||
|
||||
/**
|
||||
* Global state used to control and store generation of application snapshots.
|
||||
@@ -68,8 +63,8 @@ const uint8_t* core_isolate_snapshot_instructions =
|
||||
*/
|
||||
static bool vm_run_app_snapshot = false;
|
||||
static char* app_script_uri = nullptr;
|
||||
static const uint8_t* app_isolate_snapshot_data = nullptr;
|
||||
static const uint8_t* app_isolate_snapshot_instructions = nullptr;
|
||||
static const uint8_t* app_snapshot_data = nullptr;
|
||||
static const uint8_t* app_snapshot_text = nullptr;
|
||||
static bool kernel_isolate_is_running = false;
|
||||
|
||||
static Dart_Isolate main_isolate = nullptr;
|
||||
@@ -396,14 +391,10 @@ static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
|
||||
return nullptr;
|
||||
}
|
||||
isolate_group_data->AddLoadedSnapshot(snapshot);
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_instructions = nullptr;
|
||||
snapshot->SetBuffers(&ignore_vm_snapshot_data,
|
||||
&ignore_vm_snapshot_instructions, &snapshot_data,
|
||||
&snapshot_instructions);
|
||||
result = Dart_LoadModuleSnapshot(snapshot_data, snapshot_instructions);
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
result = Dart_LoadModuleSnapshot(snapshot_data, snapshot_text);
|
||||
CHECK_RESULT(result);
|
||||
}
|
||||
|
||||
@@ -477,22 +468,17 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
|
||||
kernel_snapshot_uri, /*force_load_from_memory=*/false,
|
||||
/*decode_uri=*/false)) != nullptr) &&
|
||||
app_snapshot->IsJIT()) {
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
isolate_run_app_snapshot = true;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
isolate_group_data = new IsolateGroupData(
|
||||
uri, /*asset_resolution_base=*/nullptr, packages_config, app_snapshot,
|
||||
isolate_run_app_snapshot);
|
||||
isolate_data = new IsolateData(isolate_group_data);
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
|
||||
isolate_snapshot_data, isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, isolate_data, error);
|
||||
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, snapshot_data,
|
||||
snapshot_text, flags, isolate_group_data, isolate_data, error);
|
||||
}
|
||||
if (isolate == nullptr) {
|
||||
// Clear error from app snapshot and re-trying from kernel file.
|
||||
@@ -545,8 +531,8 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
packages_config, nullptr, false);
|
||||
ASSERT(flags != nullptr);
|
||||
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
if (Options::experimental_vm_service()) {
|
||||
@@ -560,33 +546,29 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
if (app_snapshot == nullptr) {
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
} else {
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
// AOT: The service isolate is included in any AOT snapshot in non-PRODUCT
|
||||
// mode - so we launch the vm-service from the main app AOT snapshot.
|
||||
isolate_snapshot_data = app_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
|
||||
snapshot_data = app_snapshot_data;
|
||||
snapshot_text = app_snapshot_text;
|
||||
#else
|
||||
// JIT: Service isolate uses the core libraries snapshot.
|
||||
// Set flag to load and retain the vmservice library.
|
||||
flags->load_vmservice_library = true;
|
||||
flags->null_safety = true; // Service isolate runs in sound null safe mode.
|
||||
isolate_snapshot_data = core_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = core_isolate_snapshot_instructions;
|
||||
snapshot_data = core_snapshot_data;
|
||||
snapshot_text = core_snapshot_text;
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
}
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags, isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
isolate = Dart_CreateIsolateGroup(script_uri, DART_VM_SERVICE_ISOLATE_NAME,
|
||||
snapshot_data, snapshot_text, flags,
|
||||
isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
if (isolate == nullptr) {
|
||||
delete isolate_group_data;
|
||||
return nullptr;
|
||||
@@ -650,11 +632,11 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
AppSnapshot* app_snapshot = nullptr;
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
if (is_main_isolate) {
|
||||
isolate_snapshot_data = app_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
|
||||
snapshot_data = app_snapshot_data;
|
||||
snapshot_text = app_snapshot_text;
|
||||
} else {
|
||||
// AOT: All isolates need to be run from AOT compiled snapshots.
|
||||
const bool kForceLoadFromMemory = false;
|
||||
@@ -668,11 +650,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
}
|
||||
|
||||
bool isolate_run_app_snapshot = true;
|
||||
@@ -680,15 +658,14 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
// JIT: Main isolate starts from the app snapshot, if any. Other isolates
|
||||
// use the core libraries snapshot.
|
||||
bool isolate_run_app_snapshot = false;
|
||||
const uint8_t* isolate_snapshot_data = core_isolate_snapshot_data;
|
||||
const uint8_t* isolate_snapshot_instructions =
|
||||
core_isolate_snapshot_instructions;
|
||||
if ((app_isolate_snapshot_data != nullptr) &&
|
||||
const uint8_t* snapshot_data = core_snapshot_data;
|
||||
const uint8_t* snapshot_text = core_snapshot_text;
|
||||
if ((app_snapshot_data != nullptr) &&
|
||||
(is_main_isolate || ((app_script_uri != nullptr) &&
|
||||
(strcmp(script_uri, app_script_uri) == 0)))) {
|
||||
isolate_run_app_snapshot = true;
|
||||
isolate_snapshot_data = app_isolate_snapshot_data;
|
||||
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
|
||||
snapshot_data = app_snapshot_data;
|
||||
snapshot_text = app_snapshot_text;
|
||||
} else if (!is_main_isolate) {
|
||||
app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
|
||||
if (app_snapshot != nullptr && app_snapshot->IsJITorAOT()) {
|
||||
@@ -701,11 +678,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
return nullptr;
|
||||
}
|
||||
isolate_run_app_snapshot = true;
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +702,7 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
|
||||
IsolateData* isolate_data = nullptr;
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (!isolate_run_app_snapshot && (isolate_snapshot_data == nullptr)) {
|
||||
if (!isolate_run_app_snapshot && (snapshot_data == nullptr)) {
|
||||
const uint8_t* platform_kernel_buffer = nullptr;
|
||||
intptr_t platform_kernel_buffer_size = 0;
|
||||
dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size);
|
||||
@@ -755,15 +728,15 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
|
||||
flags, isolate_group_data, isolate_data, error);
|
||||
} else {
|
||||
isolate_data = new IsolateData(isolate_group_data);
|
||||
isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, isolate_data, error);
|
||||
isolate =
|
||||
Dart_CreateIsolateGroup(script_uri, name, snapshot_data, snapshot_text,
|
||||
flags, isolate_group_data, isolate_data, error);
|
||||
}
|
||||
#else
|
||||
isolate_data = new IsolateData(isolate_group_data);
|
||||
isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, isolate_data, error);
|
||||
isolate =
|
||||
Dart_CreateIsolateGroup(script_uri, name, snapshot_data, snapshot_text,
|
||||
flags, isolate_group_data, isolate_data, error);
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
Dart_Isolate created_isolate = nullptr;
|
||||
@@ -1288,9 +1261,7 @@ void main(int argc, char** argv) {
|
||||
Platform::Exit(kErrorExitCode);
|
||||
}
|
||||
vm_run_app_snapshot = true;
|
||||
app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
|
||||
&app_isolate_snapshot_data,
|
||||
&app_isolate_snapshot_instructions);
|
||||
app_snapshot->SetBuffers(&app_snapshot_data, &app_snapshot_text);
|
||||
} else if (app_snapshot == nullptr && Dart_IsPrecompiledRuntime()) {
|
||||
Syslog::PrintErr(
|
||||
"%s is not an AOT snapshot,"
|
||||
@@ -1367,8 +1338,6 @@ void main(int argc, char** argv) {
|
||||
Dart_InitializeParams init_params;
|
||||
memset(&init_params, 0, sizeof(init_params));
|
||||
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
init_params.vm_snapshot_data = vm_snapshot_data;
|
||||
init_params.vm_snapshot_instructions = vm_snapshot_instructions;
|
||||
init_params.create_group = CreateIsolateGroupAndSetup;
|
||||
init_params.initialize_isolate = OnIsolateInitialize;
|
||||
init_params.shutdown_isolate = OnIsolateShutdown;
|
||||
|
||||
+18
-34
@@ -22,21 +22,16 @@
|
||||
#include "vm/unit_test.h"
|
||||
|
||||
extern "C" {
|
||||
extern const uint8_t kDartVmSnapshotData[];
|
||||
extern const uint8_t kDartVmSnapshotInstructions[];
|
||||
extern const uint8_t kDartCoreIsolateSnapshotData[];
|
||||
extern const uint8_t kDartCoreIsolateSnapshotInstructions[];
|
||||
extern const uint8_t kDartCoreSnapshotData[];
|
||||
extern const uint8_t kDartCoreSnapshotText[];
|
||||
}
|
||||
|
||||
// TODO(iposva, asiva): This is a placeholder for the real unittest framework.
|
||||
namespace dart {
|
||||
|
||||
// Snapshot pieces when we link in a snapshot.
|
||||
const uint8_t* bin::vm_snapshot_data = kDartVmSnapshotData;
|
||||
const uint8_t* bin::vm_snapshot_instructions = kDartVmSnapshotInstructions;
|
||||
const uint8_t* bin::core_isolate_snapshot_data = kDartCoreIsolateSnapshotData;
|
||||
const uint8_t* bin::core_isolate_snapshot_instructions =
|
||||
kDartCoreIsolateSnapshotInstructions;
|
||||
const uint8_t* bin::core_snapshot_data = kDartCoreSnapshotData;
|
||||
const uint8_t* bin::core_snapshot_text = kDartCoreSnapshotText;
|
||||
|
||||
// Only run tests that match the filter string. The default does not match any
|
||||
// tests.
|
||||
@@ -134,8 +129,8 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
#if defined(EXPERIMENTAL_VM_SERVICE)
|
||||
if (is_exp_service_test) {
|
||||
ASSERT(!is_service_test);
|
||||
const uint8_t* isolate_snapshot_data = nullptr;
|
||||
const uint8_t* isolate_snapshot_instructions = nullptr;
|
||||
const uint8_t* snapshot_data = nullptr;
|
||||
const uint8_t* snapshot_text = nullptr;
|
||||
|
||||
bin::VmService::enable_experimental_vm_service = true;
|
||||
auto [app_snapshot, script_name] = bin::Snapshot::TryReadSDKSnapshot(
|
||||
@@ -143,15 +138,11 @@ static Dart_Isolate CreateAndSetupServiceIsolate(const char* script_uri,
|
||||
if (app_snapshot == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
|
||||
isolate_snapshot_instructions, flags, isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
isolate = Dart_CreateIsolateGroup(script_uri, DART_VM_SERVICE_ISOLATE_NAME,
|
||||
snapshot_data, snapshot_text, flags,
|
||||
isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
}
|
||||
#endif // defined(EXPERIMENTAL_VM_SERVICE)
|
||||
|
||||
@@ -239,20 +230,16 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
|
||||
bin::AppSnapshot* app_snapshot =
|
||||
bin::Snapshot::TryReadAppSnapshot(script_uri);
|
||||
ASSERT(app_snapshot != nullptr);
|
||||
const uint8_t* ignore_vm_snapshot_data;
|
||||
const uint8_t* ignore_vm_snapshot_instructions;
|
||||
const uint8_t* isolate_snapshot_data;
|
||||
const uint8_t* isolate_snapshot_instructions;
|
||||
app_snapshot->SetBuffers(
|
||||
&ignore_vm_snapshot_data, &ignore_vm_snapshot_instructions,
|
||||
&isolate_snapshot_data, &isolate_snapshot_instructions);
|
||||
const uint8_t* snapshot_data;
|
||||
const uint8_t* snapshot_text;
|
||||
app_snapshot->SetBuffers(&snapshot_data, &snapshot_text);
|
||||
isolate_group_data = new bin::IsolateGroupData(
|
||||
script_uri, /*asset_resolution_base=*/nullptr, packages_config,
|
||||
app_snapshot, app_snapshot != nullptr);
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
|
||||
isolate_snapshot_data, isolate_snapshot_instructions, flags,
|
||||
isolate_group_data, /*isolate_data=*/nullptr, error);
|
||||
isolate = Dart_CreateIsolateGroup(DART_KERNEL_ISOLATE_NAME,
|
||||
DART_KERNEL_ISOLATE_NAME, snapshot_data,
|
||||
snapshot_text, flags, isolate_group_data,
|
||||
/*isolate_data=*/nullptr, error);
|
||||
if (*error != nullptr) {
|
||||
OS::PrintErr("Error creating isolate group: %s\n", *error);
|
||||
free(*error);
|
||||
@@ -425,7 +412,6 @@ static int Main(int argc, const char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
TesterState::vm_snapshot_data = dart::bin::vm_snapshot_data;
|
||||
TesterState::create_callback = CreateIsolateAndSetup;
|
||||
TesterState::group_cleanup_callback = CleanupIsolateGroup;
|
||||
TesterState::argv = dart_argv;
|
||||
@@ -434,8 +420,6 @@ static int Main(int argc, const char** argv) {
|
||||
Dart_InitializeParams init_params;
|
||||
memset(&init_params, 0, sizeof(init_params));
|
||||
init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
init_params.vm_snapshot_data = dart::bin::vm_snapshot_data;
|
||||
init_params.vm_snapshot_instructions = dart::bin::vm_snapshot_instructions;
|
||||
init_params.create_group = CreateIsolateAndSetup;
|
||||
init_params.cleanup_group = CleanupIsolateGroup;
|
||||
init_params.file_open = dart::bin::DartUtils::OpenFile;
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
const uint8_t* kDartVmSnapshotData = nullptr;
|
||||
const uint8_t* kDartVmSnapshotInstructions = nullptr;
|
||||
const uint8_t* kDartCoreIsolateSnapshotData = nullptr;
|
||||
const uint8_t* kDartCoreIsolateSnapshotInstructions = nullptr;
|
||||
const uint8_t* kDartCoreSnapshotData = nullptr;
|
||||
const uint8_t* kDartCoreSnapshotText = nullptr;
|
||||
}
|
||||
|
||||
+90
-182
@@ -51,10 +51,8 @@ class DummySnapshot : public AppSnapshot {
|
||||
|
||||
~DummySnapshot() {}
|
||||
|
||||
void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
void SetBuffers(const uint8_t** snapshot_data_buffer,
|
||||
const uint8_t** snapshot_text_buffer) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
@@ -63,50 +61,28 @@ class DummySnapshot : public AppSnapshot {
|
||||
|
||||
class MappedAppSnapshot : public AppSnapshot {
|
||||
public:
|
||||
MappedAppSnapshot(MappedMemory* vm_snapshot_data,
|
||||
MappedMemory* vm_snapshot_instructions,
|
||||
MappedMemory* isolate_snapshot_data,
|
||||
MappedMemory* isolate_snapshot_instructions)
|
||||
MappedAppSnapshot(MappedMemory* snapshot_data, MappedMemory* snapshot_text)
|
||||
: AppSnapshot(DartUtils::kAppJITMagicNumber),
|
||||
vm_data_mapping_(vm_snapshot_data),
|
||||
vm_instructions_mapping_(vm_snapshot_instructions),
|
||||
isolate_data_mapping_(isolate_snapshot_data),
|
||||
isolate_instructions_mapping_(isolate_snapshot_instructions) {}
|
||||
data_mapping_(snapshot_data),
|
||||
text_mapping_(snapshot_text) {}
|
||||
|
||||
~MappedAppSnapshot() {
|
||||
delete vm_data_mapping_;
|
||||
delete vm_instructions_mapping_;
|
||||
delete isolate_data_mapping_;
|
||||
delete isolate_instructions_mapping_;
|
||||
delete data_mapping_;
|
||||
delete text_mapping_;
|
||||
}
|
||||
|
||||
void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
if (vm_data_mapping_ != nullptr) {
|
||||
*vm_data_buffer =
|
||||
reinterpret_cast<const uint8_t*>(vm_data_mapping_->address());
|
||||
void SetBuffers(const uint8_t** data_buffer, const uint8_t** text_buffer) {
|
||||
if (data_mapping_ != nullptr) {
|
||||
*data_buffer = reinterpret_cast<const uint8_t*>(data_mapping_->address());
|
||||
}
|
||||
if (vm_instructions_mapping_ != nullptr) {
|
||||
*vm_instructions_buffer =
|
||||
reinterpret_cast<const uint8_t*>(vm_instructions_mapping_->address());
|
||||
}
|
||||
if (isolate_data_mapping_ != nullptr) {
|
||||
*isolate_data_buffer =
|
||||
reinterpret_cast<const uint8_t*>(isolate_data_mapping_->address());
|
||||
}
|
||||
if (isolate_instructions_mapping_ != nullptr) {
|
||||
*isolate_instructions_buffer = reinterpret_cast<const uint8_t*>(
|
||||
isolate_instructions_mapping_->address());
|
||||
if (text_mapping_ != nullptr) {
|
||||
*text_buffer = reinterpret_cast<const uint8_t*>(text_mapping_->address());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MappedMemory* vm_data_mapping_;
|
||||
MappedMemory* vm_instructions_mapping_;
|
||||
MappedMemory* isolate_data_mapping_;
|
||||
MappedMemory* isolate_instructions_mapping_;
|
||||
MappedMemory* data_mapping_;
|
||||
MappedMemory* text_mapping_;
|
||||
};
|
||||
|
||||
static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name,
|
||||
@@ -150,8 +126,8 @@ static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name,
|
||||
}
|
||||
}
|
||||
|
||||
auto app_snapshot = new MappedAppSnapshot(
|
||||
nullptr, nullptr, isolate_data_mapping, isolate_instr_mapping);
|
||||
auto app_snapshot =
|
||||
new MappedAppSnapshot(isolate_data_mapping, isolate_instr_mapping);
|
||||
return app_snapshot;
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -180,35 +156,24 @@ class DylibAppSnapshot : public AppSnapshot {
|
||||
public:
|
||||
DylibAppSnapshot(DartUtils::MagicNumber magic_number,
|
||||
void* library,
|
||||
const uint8_t* vm_snapshot_data,
|
||||
const uint8_t* vm_snapshot_instructions,
|
||||
const uint8_t* isolate_snapshot_data,
|
||||
const uint8_t* isolate_snapshot_instructions)
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text)
|
||||
: AppSnapshot(magic_number),
|
||||
library_(library),
|
||||
vm_snapshot_data_(vm_snapshot_data),
|
||||
vm_snapshot_instructions_(vm_snapshot_instructions),
|
||||
isolate_snapshot_data_(isolate_snapshot_data),
|
||||
isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
|
||||
snapshot_data_(snapshot_data),
|
||||
snapshot_text_(snapshot_text) {}
|
||||
|
||||
~DylibAppSnapshot() { Utils::UnloadDynamicLibrary(library_); }
|
||||
|
||||
void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
*vm_data_buffer = vm_snapshot_data_;
|
||||
*vm_instructions_buffer = vm_snapshot_instructions_;
|
||||
*isolate_data_buffer = isolate_snapshot_data_;
|
||||
*isolate_instructions_buffer = isolate_snapshot_instructions_;
|
||||
void SetBuffers(const uint8_t** data_buffer, const uint8_t** text_buffer) {
|
||||
*data_buffer = snapshot_data_;
|
||||
*text_buffer = snapshot_text_;
|
||||
}
|
||||
|
||||
private:
|
||||
void* library_;
|
||||
const uint8_t* vm_snapshot_data_;
|
||||
const uint8_t* vm_snapshot_instructions_;
|
||||
const uint8_t* isolate_snapshot_data_;
|
||||
const uint8_t* isolate_snapshot_instructions_;
|
||||
const uint8_t* snapshot_data_;
|
||||
const uint8_t* snapshot_text_;
|
||||
};
|
||||
|
||||
static AppSnapshot* TryReadAppSnapshotDynamicLibrary(
|
||||
@@ -255,31 +220,20 @@ static AppSnapshot* TryReadAppSnapshotDynamicLibrary(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const uint8_t* vm_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kVmSnapshotDataCSymbol));
|
||||
|
||||
const uint8_t* vm_instructions_buffer =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kVmSnapshotInstructionsCSymbol));
|
||||
|
||||
const uint8_t* isolate_data_buffer =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kIsolateSnapshotDataCSymbol));
|
||||
if (isolate_data_buffer == nullptr) {
|
||||
FATAL("Failed to resolve symbol '%s'\n", kIsolateSnapshotDataCSymbol);
|
||||
const uint8_t* snapshot_data_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kSnapshotDataCSymbol));
|
||||
if (snapshot_data_buffer == nullptr) {
|
||||
FATAL("Failed to resolve symbol '%s'\n", kSnapshotDataCSymbol);
|
||||
}
|
||||
|
||||
const uint8_t* isolate_instructions_buffer =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kIsolateSnapshotInstructionsCSymbol));
|
||||
if (isolate_instructions_buffer == nullptr) {
|
||||
FATAL("Failed to resolve symbol '%s'\n",
|
||||
kIsolateSnapshotInstructionsCSymbol);
|
||||
const uint8_t* snapshot_text_buffer = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kSnapshotTextCSymbol));
|
||||
if (snapshot_text_buffer == nullptr) {
|
||||
FATAL("Failed to resolve symbol '%s'\n", kSnapshotTextCSymbol);
|
||||
}
|
||||
|
||||
return new DylibAppSnapshot(magic_number, library, vm_data_buffer,
|
||||
vm_instructions_buffer, isolate_data_buffer,
|
||||
isolate_instructions_buffer);
|
||||
return new DylibAppSnapshot(magic_number, library, snapshot_data_buffer,
|
||||
snapshot_text_buffer);
|
||||
#endif // defined(DART_INCLUDE_SIMULATOR)
|
||||
}
|
||||
|
||||
@@ -287,35 +241,24 @@ static AppSnapshot* TryReadAppSnapshotDynamicLibrary(
|
||||
class ElfAppSnapshot : public AppSnapshot {
|
||||
public:
|
||||
ElfAppSnapshot(Dart_LoadedElf* elf,
|
||||
const uint8_t* vm_snapshot_data,
|
||||
const uint8_t* vm_snapshot_instructions,
|
||||
const uint8_t* isolate_snapshot_data,
|
||||
const uint8_t* isolate_snapshot_instructions)
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text)
|
||||
: AppSnapshot{DartUtils::kAotELFMagicNumber},
|
||||
elf_(elf),
|
||||
vm_snapshot_data_(vm_snapshot_data),
|
||||
vm_snapshot_instructions_(vm_snapshot_instructions),
|
||||
isolate_snapshot_data_(isolate_snapshot_data),
|
||||
isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
|
||||
snapshot_data_(snapshot_data),
|
||||
snapshot_text_(snapshot_text) {}
|
||||
|
||||
virtual ~ElfAppSnapshot() { Dart_UnloadELF(elf_); }
|
||||
|
||||
void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
*vm_data_buffer = vm_snapshot_data_;
|
||||
*vm_instructions_buffer = vm_snapshot_instructions_;
|
||||
*isolate_data_buffer = isolate_snapshot_data_;
|
||||
*isolate_instructions_buffer = isolate_snapshot_instructions_;
|
||||
void SetBuffers(const uint8_t** data_buffer, const uint8_t** text_buffer) {
|
||||
*data_buffer = snapshot_data_;
|
||||
*text_buffer = snapshot_text_;
|
||||
}
|
||||
|
||||
private:
|
||||
Dart_LoadedElf* elf_;
|
||||
const uint8_t* vm_snapshot_data_;
|
||||
const uint8_t* vm_snapshot_instructions_;
|
||||
const uint8_t* isolate_snapshot_data_;
|
||||
const uint8_t* isolate_snapshot_instructions_;
|
||||
const uint8_t* snapshot_data_;
|
||||
const uint8_t* snapshot_text_;
|
||||
};
|
||||
|
||||
static AppSnapshot* TryReadAppSnapshotElf(const char* script_name,
|
||||
@@ -335,9 +278,8 @@ static AppSnapshot* TryReadAppSnapshotElf(const char* script_name,
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
const uint8_t *vm_data_buffer = nullptr, *vm_instructions_buffer = nullptr,
|
||||
*isolate_data_buffer = nullptr,
|
||||
*isolate_instructions_buffer = nullptr;
|
||||
const uint8_t* snapshot_data_buffer = nullptr;
|
||||
const uint8_t* snapshot_text_buffer = nullptr;
|
||||
Dart_LoadedElf* handle = nullptr;
|
||||
const char* error = nullptr;
|
||||
if (force_load_from_memory) {
|
||||
@@ -349,58 +291,43 @@ static AppSnapshot* TryReadAppSnapshotElf(const char* script_name,
|
||||
if (memory == nullptr) return nullptr;
|
||||
const uint8_t* address =
|
||||
reinterpret_cast<const uint8_t*>(memory->address());
|
||||
handle =
|
||||
Dart_LoadELF_Memory(address + file_offset, file->Length(), &error,
|
||||
&vm_data_buffer, &vm_instructions_buffer,
|
||||
&isolate_data_buffer, &isolate_instructions_buffer);
|
||||
handle = Dart_LoadELF_Memory2(address + file_offset, file->Length(), &error,
|
||||
&snapshot_data_buffer, &snapshot_text_buffer);
|
||||
delete memory;
|
||||
file->Release();
|
||||
} else {
|
||||
handle = Dart_LoadELF(script_name, file_offset, &error, &vm_data_buffer,
|
||||
&vm_instructions_buffer, &isolate_data_buffer,
|
||||
&isolate_instructions_buffer);
|
||||
handle = Dart_LoadELF2(script_name, file_offset, &error,
|
||||
&snapshot_data_buffer, &snapshot_text_buffer);
|
||||
}
|
||||
if (handle == nullptr) {
|
||||
Syslog::PrintErr("Loading failed: %s\n", error);
|
||||
return nullptr;
|
||||
}
|
||||
return new ElfAppSnapshot(handle, vm_data_buffer, vm_instructions_buffer,
|
||||
isolate_data_buffer, isolate_instructions_buffer);
|
||||
return new ElfAppSnapshot(handle, snapshot_data_buffer, snapshot_text_buffer);
|
||||
}
|
||||
|
||||
class MachODylibAppSnapshot : public AppSnapshot {
|
||||
public:
|
||||
MachODylibAppSnapshot(DartUtils::MagicNumber magic_number,
|
||||
Dart_LoadedMachODylib* macho,
|
||||
const uint8_t* vm_snapshot_data,
|
||||
const uint8_t* vm_snapshot_instructions,
|
||||
const uint8_t* isolate_snapshot_data,
|
||||
const uint8_t* isolate_snapshot_instructions)
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text)
|
||||
: AppSnapshot{magic_number},
|
||||
macho_(macho),
|
||||
vm_snapshot_data_(vm_snapshot_data),
|
||||
vm_snapshot_instructions_(vm_snapshot_instructions),
|
||||
isolate_snapshot_data_(isolate_snapshot_data),
|
||||
isolate_snapshot_instructions_(isolate_snapshot_instructions) {}
|
||||
snapshot_data_(snapshot_data),
|
||||
snapshot_text_(snapshot_text) {}
|
||||
|
||||
virtual ~MachODylibAppSnapshot() { Dart_UnloadMachODylib(macho_); }
|
||||
|
||||
void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) {
|
||||
*vm_data_buffer = vm_snapshot_data_;
|
||||
*vm_instructions_buffer = vm_snapshot_instructions_;
|
||||
*isolate_data_buffer = isolate_snapshot_data_;
|
||||
*isolate_instructions_buffer = isolate_snapshot_instructions_;
|
||||
void SetBuffers(const uint8_t** data_buffer, const uint8_t** text_buffer) {
|
||||
*data_buffer = snapshot_data_;
|
||||
*text_buffer = snapshot_text_;
|
||||
}
|
||||
|
||||
private:
|
||||
Dart_LoadedMachODylib* macho_;
|
||||
const uint8_t* vm_snapshot_data_;
|
||||
const uint8_t* vm_snapshot_instructions_;
|
||||
const uint8_t* isolate_snapshot_data_;
|
||||
const uint8_t* isolate_snapshot_instructions_;
|
||||
const uint8_t* snapshot_data_;
|
||||
const uint8_t* snapshot_text_;
|
||||
};
|
||||
|
||||
static AppSnapshot* TryReadAppSnapshotMachODylib(
|
||||
@@ -422,9 +349,8 @@ static AppSnapshot* TryReadAppSnapshotMachODylib(
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
const uint8_t *vm_data_buffer = nullptr, *vm_instructions_buffer = nullptr,
|
||||
*isolate_data_buffer = nullptr,
|
||||
*isolate_instructions_buffer = nullptr;
|
||||
const uint8_t* snapshot_data_buffer = nullptr;
|
||||
const uint8_t* snapshot_text_buffer = nullptr;
|
||||
Dart_LoadedMachODylib* handle = nullptr;
|
||||
const char* error = nullptr;
|
||||
if (force_load_from_memory) {
|
||||
@@ -439,25 +365,21 @@ static AppSnapshot* TryReadAppSnapshotMachODylib(
|
||||
}
|
||||
const uint8_t* address =
|
||||
reinterpret_cast<const uint8_t*>(memory->address());
|
||||
handle = Dart_LoadMachODylib_Memory(
|
||||
address + file_offset, file->Length(), &error, &vm_data_buffer,
|
||||
&vm_instructions_buffer, &isolate_data_buffer,
|
||||
&isolate_instructions_buffer);
|
||||
handle = Dart_LoadMachODylib_Memory2(address + file_offset, file->Length(),
|
||||
&error, &snapshot_data_buffer,
|
||||
&snapshot_text_buffer);
|
||||
delete memory;
|
||||
file->Release();
|
||||
} else {
|
||||
handle =
|
||||
Dart_LoadMachODylib(script_name, file_offset, &error, &vm_data_buffer,
|
||||
&vm_instructions_buffer, &isolate_data_buffer,
|
||||
&isolate_instructions_buffer);
|
||||
handle = Dart_LoadMachODylib2(script_name, file_offset, &error,
|
||||
&snapshot_data_buffer, &snapshot_text_buffer);
|
||||
}
|
||||
if (handle == nullptr) {
|
||||
Syslog::PrintErr("Loading failed: %s\n", error);
|
||||
return nullptr;
|
||||
}
|
||||
return new MachODylibAppSnapshot(magic_number, handle, vm_data_buffer,
|
||||
vm_instructions_buffer, isolate_data_buffer,
|
||||
isolate_instructions_buffer);
|
||||
return new MachODylibAppSnapshot(magic_number, handle, snapshot_data_buffer,
|
||||
snapshot_text_buffer);
|
||||
}
|
||||
|
||||
static AppSnapshot* TryReadAppSnapshotAt(const char* script_name,
|
||||
@@ -606,10 +528,8 @@ AppSnapshot* Snapshot::TryReadAppendedAppSnapshotFromPE(
|
||||
// PE sections can be less than the page size, and TryReadAppSnapshotElf
|
||||
// won't work if the file offset isn't page-aligned.
|
||||
const char* error = nullptr;
|
||||
const uint8_t* vm_data_buffer = nullptr;
|
||||
const uint8_t* vm_instructions_buffer = nullptr;
|
||||
const uint8_t* isolate_data_buffer = nullptr;
|
||||
const uint8_t* isolate_instructions_buffer = nullptr;
|
||||
const uint8_t* snapshot_data_buffer = nullptr;
|
||||
const uint8_t* snapshot_text_buffer = nullptr;
|
||||
|
||||
const intptr_t offset = section_header.file_offset;
|
||||
const intptr_t size = section_header.file_size;
|
||||
@@ -622,26 +542,23 @@ AppSnapshot* Snapshot::TryReadAppendedAppSnapshotFromPE(
|
||||
|
||||
if (magic_number == DartUtils::kAotELFMagicNumber) {
|
||||
Dart_LoadedElf* const handle =
|
||||
Dart_LoadELF_Memory(snapshot.get(), size, &error, &vm_data_buffer,
|
||||
&vm_instructions_buffer, &isolate_data_buffer,
|
||||
&isolate_instructions_buffer);
|
||||
Dart_LoadELF_Memory2(snapshot.get(), size, &error,
|
||||
&snapshot_data_buffer, &snapshot_text_buffer);
|
||||
|
||||
if (handle == nullptr) {
|
||||
Syslog::PrintErr("Loading failed: %s\n", error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new ElfAppSnapshot(handle, vm_data_buffer,
|
||||
vm_instructions_buffer, isolate_data_buffer,
|
||||
isolate_instructions_buffer);
|
||||
return new ElfAppSnapshot(handle, snapshot_data_buffer,
|
||||
snapshot_text_buffer);
|
||||
}
|
||||
|
||||
if (magic_number == DartUtils::kAotMachO32MagicNumber ||
|
||||
magic_number == DartUtils::kAotMachO64MagicNumber) {
|
||||
Dart_LoadedMachODylib* const handle = Dart_LoadMachODylib_Memory(
|
||||
snapshot.get(), size, &error, &vm_data_buffer,
|
||||
&vm_instructions_buffer, &isolate_data_buffer,
|
||||
&isolate_instructions_buffer);
|
||||
Dart_LoadedMachODylib* const handle = Dart_LoadMachODylib_Memory2(
|
||||
snapshot.get(), size, &error, &snapshot_data_buffer,
|
||||
&snapshot_text_buffer);
|
||||
|
||||
if (handle == nullptr) {
|
||||
Syslog::PrintErr("Loading failed: %s\n", error);
|
||||
@@ -649,8 +566,7 @@ AppSnapshot* Snapshot::TryReadAppendedAppSnapshotFromPE(
|
||||
}
|
||||
|
||||
return new MachODylibAppSnapshot(
|
||||
magic_number, handle, vm_data_buffer, vm_instructions_buffer,
|
||||
isolate_data_buffer, isolate_instructions_buffer);
|
||||
magic_number, handle, snapshot_data_buffer, snapshot_text_buffer);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -981,32 +897,24 @@ void Snapshot::GenerateKernel(const char* snapshot_filename,
|
||||
}
|
||||
|
||||
void Snapshot::GenerateAppJIT(const char* snapshot_filename) {
|
||||
uint8_t* snapshot_data_buffer = nullptr;
|
||||
intptr_t snapshot_data_size = 0;
|
||||
uint8_t* snapshot_text_buffer = nullptr;
|
||||
intptr_t snapshot_text_size = 0;
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
// Snapshots with code are not supported on IA32.
|
||||
uint8_t* isolate_buffer = nullptr;
|
||||
intptr_t isolate_size = 0;
|
||||
|
||||
Dart_Handle result = Dart_CreateSnapshot(nullptr, nullptr, &isolate_buffer,
|
||||
&isolate_size, /*is_core=*/false);
|
||||
if (Dart_IsError(result)) {
|
||||
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
|
||||
}
|
||||
|
||||
WriteAppSnapshot(snapshot_filename, isolate_buffer, isolate_size, nullptr, 0);
|
||||
Dart_Handle result =
|
||||
Dart_CreateSnapshot(&snapshot_data_buffer, &snapshot_data_size);
|
||||
#else
|
||||
uint8_t* isolate_data_buffer = nullptr;
|
||||
intptr_t isolate_data_size = 0;
|
||||
uint8_t* isolate_instructions_buffer = nullptr;
|
||||
intptr_t isolate_instructions_size = 0;
|
||||
Dart_Handle result = Dart_CreateAppJITSnapshotAsBlobs(
|
||||
&isolate_data_buffer, &isolate_data_size, &isolate_instructions_buffer,
|
||||
&isolate_instructions_size);
|
||||
&snapshot_data_buffer, &snapshot_data_size, &snapshot_text_buffer,
|
||||
&snapshot_text_size);
|
||||
#endif
|
||||
if (Dart_IsError(result)) {
|
||||
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
|
||||
}
|
||||
WriteAppSnapshot(snapshot_filename, isolate_data_buffer, isolate_data_size,
|
||||
isolate_instructions_buffer, isolate_instructions_size);
|
||||
#endif
|
||||
WriteAppSnapshot(snapshot_filename, snapshot_data_buffer, snapshot_data_size,
|
||||
snapshot_text_buffer, snapshot_text_size);
|
||||
}
|
||||
|
||||
static void StreamingWriteCallback(void* callback_data,
|
||||
|
||||
@@ -17,10 +17,8 @@ class AppSnapshot {
|
||||
public:
|
||||
virtual ~AppSnapshot() {}
|
||||
|
||||
virtual void SetBuffers(const uint8_t** vm_data_buffer,
|
||||
const uint8_t** vm_instructions_buffer,
|
||||
const uint8_t** isolate_data_buffer,
|
||||
const uint8_t** isolate_instructions_buffer) = 0;
|
||||
virtual void SetBuffers(const uint8_t** snapshot_data_buffer,
|
||||
const uint8_t** snapshot_text_buffer) = 0;
|
||||
|
||||
bool IsJIT() const { return magic_number_ == DartUtils::kAppJITMagicNumber; }
|
||||
bool IsAOT() const { return DartUtils::IsAotMagicNumber(magic_number_); }
|
||||
|
||||
@@ -69,17 +69,10 @@ DartEngine_SnapshotData Engine::AotFromFile(const char* path, char** error) {
|
||||
void* library =
|
||||
Utils::LoadDynamicLibrary(path, /*search_dll_load_dir=*/false, error);
|
||||
|
||||
result.vm_snapshot_data = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kVmSnapshotDataCSymbol));
|
||||
result.vm_snapshot_instructions =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kVmSnapshotInstructionsCSymbol));
|
||||
result.vm_isolate_data =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kIsolateSnapshotDataCSymbol));
|
||||
result.vm_isolate_instructions =
|
||||
reinterpret_cast<const uint8_t*>(Utils::ResolveSymbolInDynamicLibrary(
|
||||
library, kIsolateSnapshotInstructionsCSymbol));
|
||||
result.snapshot_data = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kSnapshotDataCSymbol));
|
||||
result.snapshot_text = reinterpret_cast<const uint8_t*>(
|
||||
Utils::ResolveSymbolInDynamicLibrary(library, kSnapshotTextCSymbol));
|
||||
|
||||
if (*error != nullptr) {
|
||||
return result;
|
||||
@@ -153,12 +146,6 @@ Dart_Isolate Engine::StartIsolate(DartEngine_SnapshotData snapshot,
|
||||
MutexLocker ml(&engine_lifecycle_);
|
||||
if (!first_isolate_started_) {
|
||||
Dart_InitializeParams initialize_params = CreateInitializeParams();
|
||||
|
||||
if (Dart_IsPrecompiledRuntime()) {
|
||||
initialize_params.vm_snapshot_data = snapshot.vm_snapshot_data;
|
||||
initialize_params.vm_snapshot_instructions =
|
||||
snapshot.vm_snapshot_instructions;
|
||||
}
|
||||
*error = Dart_Initialize(&initialize_params);
|
||||
if (*error != nullptr) {
|
||||
return nullptr;
|
||||
@@ -176,8 +163,8 @@ Dart_Isolate Engine::StartIsolate(DartEngine_SnapshotData snapshot,
|
||||
// Automatically sets the root library for the isolate.
|
||||
isolate = Dart_CreateIsolateGroup(
|
||||
snapshot.script_uri, strrchr(snapshot.script_uri, '/'),
|
||||
snapshot.vm_isolate_data, snapshot.vm_isolate_instructions,
|
||||
&isolate_flags, nullptr, nullptr, error);
|
||||
snapshot.snapshot_data, snapshot.snapshot_text, &isolate_flags, nullptr,
|
||||
nullptr, error);
|
||||
} else {
|
||||
isolate = Dart_CreateIsolateGroupFromKernel(
|
||||
snapshot.script_uri, snapshot.script_uri, snapshot.kernel_buffer,
|
||||
|
||||
@@ -53,10 +53,8 @@ typedef struct DartEngine_SnapshotData {
|
||||
intptr_t kernel_buffer_size;
|
||||
};
|
||||
struct {
|
||||
const uint8_t* vm_snapshot_data;
|
||||
const uint8_t* vm_snapshot_instructions;
|
||||
const uint8_t* vm_isolate_data;
|
||||
const uint8_t* vm_isolate_instructions;
|
||||
const uint8_t* snapshot_data;
|
||||
const uint8_t* snapshot_text;
|
||||
};
|
||||
};
|
||||
} DartEngine_SnapshotData;
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
namespace dart {
|
||||
namespace snapshot_analyzer {
|
||||
typedef struct {
|
||||
const uint8_t* vm_snapshot_data;
|
||||
const uint8_t* vm_snapshot_instructions;
|
||||
const uint8_t* vm_isolate_data;
|
||||
const uint8_t* vm_isolate_instructions;
|
||||
const uint8_t* snapshot_data;
|
||||
const uint8_t* snapshot_text;
|
||||
} Dart_SnapshotAnalyzerInformation;
|
||||
|
||||
void Dart_DumpSnapshotInformationAsJson(
|
||||
|
||||
+60
-83
@@ -578,7 +578,7 @@ DART_EXPORT const char* Dart_VersionString(void);
|
||||
* for each part.
|
||||
*/
|
||||
|
||||
#define DART_FLAGS_CURRENT_VERSION (0x0000000d)
|
||||
#define DART_FLAGS_CURRENT_VERSION (0x0000000e)
|
||||
|
||||
typedef struct {
|
||||
int32_t version;
|
||||
@@ -594,6 +594,8 @@ typedef struct {
|
||||
bool snapshot_is_dontneed_safe;
|
||||
bool branch_coverage;
|
||||
bool coverage;
|
||||
bool dwarf_stack_traces;
|
||||
bool code_comments;
|
||||
} Dart_IsolateFlags;
|
||||
|
||||
/**
|
||||
@@ -872,19 +874,8 @@ typedef struct {
|
||||
*/
|
||||
int32_t version;
|
||||
|
||||
/**
|
||||
* A buffer containing snapshot data, or NULL if no snapshot is provided.
|
||||
*
|
||||
* If provided, the buffer must remain valid until Dart_Cleanup returns.
|
||||
*/
|
||||
/* TRANSITION */
|
||||
const uint8_t* vm_snapshot_data;
|
||||
|
||||
/**
|
||||
* A buffer containing a snapshot of precompiled instructions, or NULL if
|
||||
* no snapshot is provided.
|
||||
*
|
||||
* If provided, the buffer must remain valid until Dart_Cleanup returns.
|
||||
*/
|
||||
const uint8_t* vm_snapshot_instructions;
|
||||
|
||||
/**
|
||||
@@ -929,7 +920,7 @@ typedef struct {
|
||||
/**
|
||||
* A function to be called by the service isolate when it requires the
|
||||
* vmservice assets archive. See Dart_GetVMServiceAssetsArchive.
|
||||
*
|
||||
*
|
||||
* This field is deprecated and has no effect.
|
||||
*/
|
||||
Dart_GetVMServiceAssetsArchive get_service_assets;
|
||||
@@ -1013,10 +1004,10 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
|
||||
* that allows it to load the same program into such a child isolate.
|
||||
* \param name A short name for the isolate to improve debugging messages.
|
||||
* Typically of the format 'foo.dart:main()'.
|
||||
* \param isolate_snapshot_data Buffer containing the snapshot data of the
|
||||
* \param snapshot_data Buffer containing the snapshot data of the
|
||||
* isolate or NULL if no snapshot is provided. If provided, the buffer must
|
||||
* remain valid until the isolate shuts down.
|
||||
* \param isolate_snapshot_instructions Buffer containing the snapshot
|
||||
* \param snapshot_text Buffer containing the snapshot
|
||||
* instructions of the isolate or NULL if no snapshot is provided. If
|
||||
* provided, the buffer must remain valid until the isolate shuts down.
|
||||
* \param flags Pointer to VM specific flags or NULL for default flags.
|
||||
@@ -1033,15 +1024,14 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
|
||||
*
|
||||
* \return The new isolate on success, or NULL if isolate creation failed.
|
||||
*/
|
||||
DART_EXPORT Dart_Isolate
|
||||
Dart_CreateIsolateGroup(const char* script_uri,
|
||||
const char* name,
|
||||
const uint8_t* isolate_snapshot_data,
|
||||
const uint8_t* isolate_snapshot_instructions,
|
||||
Dart_IsolateFlags* flags,
|
||||
void* isolate_group_data,
|
||||
void* isolate_data,
|
||||
char** error);
|
||||
DART_EXPORT Dart_Isolate Dart_CreateIsolateGroup(const char* script_uri,
|
||||
const char* name,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text,
|
||||
Dart_IsolateFlags* flags,
|
||||
void* isolate_group_data,
|
||||
void* isolate_data,
|
||||
char** error);
|
||||
/**
|
||||
* Creates a new isolate inside the isolate group of [group_member].
|
||||
*
|
||||
@@ -1419,26 +1409,17 @@ DART_EXPORT void Dart_ExitIsolate(void);
|
||||
* Requires there to be a current isolate. Not available in the precompiled
|
||||
* runtime (check Dart_IsPrecompiledRuntime).
|
||||
*
|
||||
* \param vm_snapshot_data_buffer Returns a pointer to a buffer containing the
|
||||
* vm snapshot. This buffer is scope allocated and is only valid
|
||||
* \param snapshot_data_buffer Returns a pointer to a buffer containing
|
||||
* the snapshot. This buffer is scope allocated and is only valid
|
||||
* until the next call to Dart_ExitScope.
|
||||
* \param vm_snapshot_data_size Returns the size of vm_snapshot_data_buffer.
|
||||
* \param isolate_snapshot_data_buffer Returns a pointer to a buffer containing
|
||||
* the isolate snapshot. This buffer is scope allocated and is only valid
|
||||
* until the next call to Dart_ExitScope.
|
||||
* \param isolate_snapshot_data_size Returns the size of
|
||||
* isolate_snapshot_data_buffer.
|
||||
* \param is_core Create a snapshot containing core libraries.
|
||||
* Such snapshot should be agnostic to null safety mode.
|
||||
* \param snapshot_data_size Returns the size of
|
||||
* snapshot_data_buffer.
|
||||
*
|
||||
* \return A valid handle if no error occurs during the operation.
|
||||
*/
|
||||
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
|
||||
Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
|
||||
intptr_t* vm_snapshot_data_size,
|
||||
uint8_t** isolate_snapshot_data_buffer,
|
||||
intptr_t* isolate_snapshot_data_size,
|
||||
bool is_core);
|
||||
Dart_CreateSnapshot(uint8_t** snapshot_data_buffer,
|
||||
intptr_t* snapshot_data_size);
|
||||
|
||||
/**
|
||||
* Returns whether the buffer contains a kernel file.
|
||||
@@ -3549,7 +3530,7 @@ Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler);
|
||||
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
|
||||
Dart_DeferredLoadComplete(intptr_t loading_unit_id,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions);
|
||||
const uint8_t* snapshot_text);
|
||||
|
||||
/**
|
||||
* Notifies the VM that a deferred load failed. This function
|
||||
@@ -3601,12 +3582,12 @@ Dart_LoadScriptFromBytecode(const uint8_t* kernel_buffer, intptr_t kernel_size);
|
||||
*
|
||||
* \param snapshot_data Buffer containing the module snapshot data.
|
||||
* Must remain valid until isolate group shutdown.
|
||||
* \param snapshot_instructions Buffer containing the module snapshot
|
||||
* \param snapshot_text Buffer containing the module snapshot
|
||||
* instructions. Must remain valid until isolate group shutdown.
|
||||
*/
|
||||
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
|
||||
Dart_LoadModuleSnapshot(const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions);
|
||||
const uint8_t* snapshot_text);
|
||||
|
||||
/**
|
||||
* Gets the library for the root script for the current isolate.
|
||||
@@ -3951,7 +3932,7 @@ DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri,
|
||||
const char* package_config,
|
||||
const char* original_working_directory,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size);
|
||||
|
||||
@@ -4022,6 +4003,23 @@ DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
|
||||
// symbol names in the objects are given by the '...AsmSymbol' definitions.
|
||||
#if defined(__APPLE__)
|
||||
#define kSnapshotBuildIdCSymbol "kDartSnapshotBuildId"
|
||||
#define kSnapshotDataCSymbol "kDartSnapshotData"
|
||||
#define kSnapshotTextCSymbol "kDartSnapshotText"
|
||||
#define kSnapshotBssCSymbol "kDartSnapshotBss"
|
||||
#else
|
||||
#define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId"
|
||||
#define kSnapshotDataCSymbol "_kDartSnapshotData"
|
||||
#define kSnapshotTextCSymbol "_kDartSnapshotText"
|
||||
#define kSnapshotBssCSymbol "_kDartSnapshotBss"
|
||||
#endif
|
||||
|
||||
#define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId"
|
||||
#define kSnapshotDataAsmSymbol "_kDartSnapshotData"
|
||||
#define kSnapshotTextAsmSymbol "_kDartSnapshotText"
|
||||
#define kSnapshotBssAsmSymbol "_kDartSnapshotBss"
|
||||
|
||||
/* TRANSITION */
|
||||
#if defined(__APPLE__)
|
||||
#define kVmSnapshotDataCSymbol "kDartVmSnapshotData"
|
||||
#define kVmSnapshotInstructionsCSymbol "kDartVmSnapshotInstructions"
|
||||
#define kVmSnapshotBssCSymbol "kDartVmSnapshotBss"
|
||||
@@ -4029,7 +4027,6 @@ DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
|
||||
#define kIsolateSnapshotInstructionsCSymbol "kDartIsolateSnapshotInstructions"
|
||||
#define kIsolateSnapshotBssCSymbol "kDartIsolateSnapshotBss"
|
||||
#else
|
||||
#define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId"
|
||||
#define kVmSnapshotDataCSymbol "_kDartVmSnapshotData"
|
||||
#define kVmSnapshotInstructionsCSymbol "_kDartVmSnapshotInstructions"
|
||||
#define kVmSnapshotBssCSymbol "_kDartVmSnapshotBss"
|
||||
@@ -4038,15 +4035,6 @@ DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
|
||||
#define kIsolateSnapshotBssCSymbol "_kDartIsolateSnapshotBss"
|
||||
#endif
|
||||
|
||||
#define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId"
|
||||
#define kVmSnapshotDataAsmSymbol "_kDartVmSnapshotData"
|
||||
#define kVmSnapshotInstructionsAsmSymbol "_kDartVmSnapshotInstructions"
|
||||
#define kVmSnapshotBssAsmSymbol "_kDartVmSnapshotBss"
|
||||
#define kIsolateSnapshotDataAsmSymbol "_kDartIsolateSnapshotData"
|
||||
#define kIsolateSnapshotInstructionsAsmSymbol \
|
||||
"_kDartIsolateSnapshotInstructions"
|
||||
#define kIsolateSnapshotBssAsmSymbol "_kDartIsolateSnapshotBss"
|
||||
|
||||
/**
|
||||
* Creates a precompiled snapshot.
|
||||
* - A root library must have been loaded.
|
||||
@@ -4057,10 +4045,8 @@ DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
|
||||
*
|
||||
* The assembly should be compiled as a static or shared library and linked or
|
||||
* loaded by the embedder. Running this snapshot requires a VM compiled with
|
||||
* DART_PRECOMPILED_RUNTIME. The kDartVmSnapshotData and
|
||||
* kDartVmSnapshotInstructions should be passed to Dart_Initialize. The
|
||||
* kDartIsolateSnapshotData and kDartIsolateSnapshotInstructions should be
|
||||
* passed to Dart_CreateIsolateGroup.
|
||||
* DART_PRECOMPILED_RUNTIME. The kDartSnapshotData and kDartSnapshotText should
|
||||
* be passed to Dart_CreateIsolateGroup.
|
||||
*
|
||||
* The callback will be invoked one or more times to provide the assembly code.
|
||||
*
|
||||
@@ -4092,16 +4078,13 @@ Dart_CreateAppAOTSnapshotAsAssemblies(
|
||||
* - Dart_Precompile must have been called.
|
||||
*
|
||||
* Outputs an ELF shared library defining the symbols
|
||||
* - _kDartVmSnapshotData
|
||||
* - _kDartVmSnapshotInstructions
|
||||
* - _kDartIsolateSnapshotData
|
||||
* - _kDartIsolateSnapshotInstructions
|
||||
* - _kDartSnapshotData
|
||||
* - _kDartSnapshotText
|
||||
*
|
||||
* The shared library should be dynamically loaded by the embedder.
|
||||
* Running this snapshot requires a VM compiled with DART_PRECOMPILED_RUNTIME.
|
||||
* The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
|
||||
* Dart_Initialize. The kDartIsolateSnapshotData and
|
||||
* kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
|
||||
* The kDartSnapshotData and kDartSnapshotText should be passed to
|
||||
* Dart_CreateIsolateGroup.
|
||||
*
|
||||
* The callback will be invoked one or more times to provide the binary output.
|
||||
*
|
||||
@@ -4137,16 +4120,13 @@ typedef enum {
|
||||
* - Dart_Precompile must have been called.
|
||||
*
|
||||
* Outputs a snapshot in the specified binary format defining the symbols
|
||||
* - _kDartVmSnapshotData
|
||||
* - _kDartVmSnapshotInstructions
|
||||
* - _kDartIsolateSnapshotData
|
||||
* - _kDartIsolateSnapshotInstructions
|
||||
* - _kDartSnapshotData
|
||||
* - _kDartSnapshotText
|
||||
*
|
||||
* The shared library should be dynamically loaded by the embedder.
|
||||
* Running this snapshot requires a VM compiled with DART_PRECOMPILED_RUNTIME.
|
||||
* The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
|
||||
* Dart_Initialize. The kDartIsolateSnapshotData and
|
||||
* kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
|
||||
* The kDartSnapshotData and kDartSnapshotText should be passed to
|
||||
* Dart_CreateIsolateGroup.
|
||||
*
|
||||
* The callback will be invoked one or more times to provide the binary output.
|
||||
*
|
||||
@@ -4184,18 +4164,15 @@ Dart_CreateAppAOTSnapshotAsBinary(Dart_AotBinaryFormat format,
|
||||
*
|
||||
* Outputs both a snapshot and a relocatable object file in
|
||||
* the specified binary format defining the symbols
|
||||
* - _kDartVmSnapshotData
|
||||
* - _kDartVmSnapshotInstructions
|
||||
* - _kDartIsolateSnapshotData
|
||||
* - _kDartIsolateSnapshotInstructions
|
||||
* - _kDartSnapshotData
|
||||
* - _kDartSnapshotText
|
||||
* Whether or not the snapshot is stripped, the relocatable object file
|
||||
* contains all debugging information.
|
||||
*
|
||||
* The shared library should be dynamically loaded by the embedder.
|
||||
* Running this snapshot requires a VM compiled with DART_PRECOMPILED_RUNTIME.
|
||||
* The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
|
||||
* Dart_Initialize. The kDartIsolateSnapshotData and
|
||||
* kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
|
||||
* The kDartSnapshotData and kDartSnapshotText should be passed to
|
||||
* Dart_CreateIsolateGroup.
|
||||
*
|
||||
* The callback will be invoked one or more times to provide the binary output.
|
||||
*
|
||||
@@ -4273,10 +4250,10 @@ DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses(void);
|
||||
* \return A valid handle if no error occurs during the operation.
|
||||
*/
|
||||
DART_EXPORT DART_API_WARN_UNUSED_RESULT Dart_Handle
|
||||
Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
|
||||
intptr_t* isolate_snapshot_data_size,
|
||||
uint8_t** isolate_snapshot_instructions_buffer,
|
||||
intptr_t* isolate_snapshot_instructions_size);
|
||||
Dart_CreateAppJITSnapshotAsBlobs(uint8_t** snapshot_data_buffer,
|
||||
intptr_t* snapshot_data_size,
|
||||
uint8_t** snapshot_text_buffer,
|
||||
intptr_t* snapshot_text_size);
|
||||
|
||||
/**
|
||||
* Get obfuscation map for precompiled code.
|
||||
|
||||
@@ -193,8 +193,7 @@ DEFINE_NATIVE_ENTRY(Developer_NativeRuntime_buildId, 0, 0) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
IsolateGroup* isolate_group = thread->isolate_group();
|
||||
ASSERT(isolate_group != nullptr);
|
||||
if (const uint8_t* instructions =
|
||||
isolate_group->source()->snapshot_instructions) {
|
||||
if (const uint8_t* instructions = isolate_group->source()->snapshot_text) {
|
||||
const auto& build_id = OS::GetAppBuildId(instructions);
|
||||
if (build_id.data != nullptr) {
|
||||
ZoneTextBuffer buffer(zone);
|
||||
|
||||
@@ -319,27 +319,25 @@ DEFINE_NATIVE_ENTRY(Internal_deoptimizeFunctionsOnStack, 0, 0) {
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Internal_allocateObjectInstructionsStart, 0, 0) {
|
||||
auto isolate_group = thread->isolate_group();
|
||||
auto& stub =
|
||||
Code::Handle(zone, isolate_group->object_store()->allocate_object_stub());
|
||||
auto& stub = StubCode::AllocateObject();
|
||||
ASSERT(!stub.IsUnknownDartCode());
|
||||
// We return the start offset in the isolate instructions instead of the
|
||||
// full address because that fits into small Smis on 32-bit architectures
|
||||
// or compressed pointer builds.
|
||||
const uword instructions_start =
|
||||
reinterpret_cast<uword>(isolate_group->source()->snapshot_instructions);
|
||||
reinterpret_cast<uword>(isolate_group->source()->snapshot_text);
|
||||
return Smi::New(stub.PayloadStart() - instructions_start);
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Internal_allocateObjectInstructionsEnd, 0, 0) {
|
||||
auto isolate_group = thread->isolate_group();
|
||||
auto& stub =
|
||||
Code::Handle(zone, isolate_group->object_store()->allocate_object_stub());
|
||||
auto& stub = StubCode::AllocateObject();
|
||||
ASSERT(!stub.IsUnknownDartCode());
|
||||
// We return the end offset in the isolate instructions instead of the
|
||||
// full address because that fits into small Smis on 32-bit architectures
|
||||
// or compressed pointer builds.
|
||||
const uword instructions_start =
|
||||
reinterpret_cast<uword>(isolate_group->source()->snapshot_instructions);
|
||||
reinterpret_cast<uword>(isolate_group->source()->snapshot_text);
|
||||
return Smi::New((stub.PayloadStart() - instructions_start) + stub.Size());
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +222,14 @@ uint32_t Utils::StringHash(const void* data, int length) {
|
||||
|
||||
#undef MIX
|
||||
|
||||
// TODO(63370): Proper 64-bit hash.
|
||||
uint64_t Utils::StringHash64(const void* data, int length) {
|
||||
uint64_t hi = StringHash(data, length / 2);
|
||||
uint64_t lo = StringHash(reinterpret_cast<const uint8_t*>(data) + length / 2,
|
||||
length / 2);
|
||||
return hi << 32 | lo;
|
||||
}
|
||||
|
||||
uint32_t Utils::WordHash(intptr_t key) {
|
||||
// TODO(iposva): Need to check hash spreading.
|
||||
// This example is from http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
|
||||
@@ -212,6 +212,7 @@ class Utils {
|
||||
|
||||
// Computes a hash value for the given series of bytes.
|
||||
static uint32_t StringHash(const void* data, int length);
|
||||
static uint64_t StringHash64(const void* data, int length);
|
||||
|
||||
// Computes a hash value for the given word.
|
||||
static uint32_t WordHash(intptr_t key);
|
||||
|
||||
@@ -370,13 +370,13 @@ main() {
|
||||
"Dart_WriteHeapSnapshot",
|
||||
"Dart_WriteProfileToTimeline",
|
||||
if (isAOTRuntime) ...[
|
||||
"Dart_LoadELF",
|
||||
"Dart_LoadELF_Memory",
|
||||
"Dart_LoadMachODylib",
|
||||
"Dart_LoadMachODylib_Memory",
|
||||
"Dart_LoadELF2",
|
||||
"Dart_LoadELF_Memory2",
|
||||
"Dart_LoadMachODylib2",
|
||||
"Dart_LoadMachODylib_Memory2",
|
||||
"Dart_UnloadELF",
|
||||
"Dart_UnloadMachODylib",
|
||||
if (!Platform.isMacOS) ...["Dart_LoadELF_Fd", "Dart_LoadMachODylib_Fd"],
|
||||
if (!Platform.isMacOS) ...["Dart_LoadELF_Fd2", "Dart_LoadMachODylib_Fd2"],
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ void checkVMSymbolsAreValid(
|
||||
break;
|
||||
// In assembly snapshots, we use local object symbols to initialize the
|
||||
// InstructionsSection header with the right offset to the BSS section.
|
||||
case '_kDartSnapshotBss':
|
||||
case '_kDartVmSnapshotBss':
|
||||
case '_kDartIsolateSnapshotBss':
|
||||
Expect.isTrue(isAssembled);
|
||||
@@ -259,16 +260,16 @@ void checkElf(Elf? snapshot, Elf debugInfo, {required bool isAssembled}) {
|
||||
// using the --add-readonly-data-symbols flag.
|
||||
Expect.isNotEmpty(debugLocalObjectSymbols);
|
||||
|
||||
// We expect exactly two local object symbols with names starting with
|
||||
// We expect exactly one local object symbols with names starting with
|
||||
// 'RawBytes'.
|
||||
int rawBytesSeen = debugLocalObjectSymbols.fold<int>(
|
||||
0,
|
||||
(i, s) => i + (s.name.startsWith('RawBytes') ? 1 : 0),
|
||||
);
|
||||
Expect.equals(
|
||||
2,
|
||||
1,
|
||||
rawBytesSeen,
|
||||
'saw $rawBytesSeen (!= 2) RawBytes local object symbols',
|
||||
'saw $rawBytesSeen (!= 1) RawBytes local object symbols',
|
||||
);
|
||||
|
||||
// All snapshots include at least one (and likely many) duplicate local
|
||||
|
||||
@@ -220,7 +220,6 @@ Future<void> runTests<T>(
|
||||
|
||||
void checkHeader(StackTraceHeader header) {
|
||||
// These should be all available.
|
||||
expect(header.vmStart, isNotNull);
|
||||
expect(header.isolateStart, isNotNull);
|
||||
expect(header.isolateDsoBase, isNotNull);
|
||||
expect(header.buildId, isNotNull);
|
||||
@@ -325,7 +324,7 @@ void checkAllocateObjectOffset(
|
||||
callInfo != null &&
|
||||
callInfo.length == 1 &&
|
||||
callInfo.single is StubCallInfo &&
|
||||
(callInfo.single as StubCallInfo).name.endsWith('AllocateObjectStub');
|
||||
(callInfo.single as StubCallInfo).name.endsWith('stub AllocateObject');
|
||||
expect(
|
||||
got,
|
||||
equals(expectedValue),
|
||||
|
||||
@@ -73,13 +73,13 @@ Future<void> testJIT(String dillPath, String snapshotKind) async {
|
||||
await withTempDir('v8-snapshot-profile-$description', (String tempDir) async {
|
||||
// Generate the snapshot profile.
|
||||
final profilePath = path.join(tempDir, 'profile.heapsnapshot');
|
||||
final vmDataPath = path.join(tempDir, 'vm_data.bin');
|
||||
final isolateDataPath = path.join(tempDir, 'isolate_data.bin');
|
||||
final snapshotDataPath = path.join(tempDir, 'snapshot_data.bin');
|
||||
final snapshotTextPath = path.join(tempDir, 'snapshot_text.bin');
|
||||
|
||||
await run(genSnapshot, <String>[
|
||||
'--snapshot-kind=$snapshotKind',
|
||||
'--vm_snapshot_data=$vmDataPath',
|
||||
'--isolate_snapshot_data=$isolateDataPath',
|
||||
'--snapshot_data=$snapshotDataPath',
|
||||
'--snapshot_text=$snapshotTextPath',
|
||||
"--write-v8-snapshot-profile-to=$profilePath",
|
||||
dillPath,
|
||||
]);
|
||||
@@ -92,7 +92,8 @@ Future<void> testJIT(String dillPath, String snapshotKind) async {
|
||||
// the same as the sum of the shallow sizes of all objects in the profile.
|
||||
// This ensures that all bytes are accounted for in some way.
|
||||
int actualSize =
|
||||
await File(vmDataPath).length() + await File(isolateDataPath).length();
|
||||
await File(snapshotDataPath).length() +
|
||||
await File(snapshotTextPath).length();
|
||||
final expectedSize = profile.nodes.fold<int>(
|
||||
0,
|
||||
(size, n) => size + n.selfSize,
|
||||
@@ -201,22 +202,12 @@ Future<void> testAOT(
|
||||
Expect.isNotNull(elf);
|
||||
elf!; // To refine type to non-nullable version.
|
||||
|
||||
final vmTextSectionSymbol = elf.dynamicSymbolFor(vmSymbolName);
|
||||
Expect.isNotNull(vmTextSectionSymbol);
|
||||
final vmDataSectionSymbol = elf.dynamicSymbolFor(vmDataSymbolName);
|
||||
Expect.isNotNull(vmDataSectionSymbol);
|
||||
final isolateTextSectionSymbol = elf.dynamicSymbolFor(isolateSymbolName);
|
||||
Expect.isNotNull(isolateTextSectionSymbol);
|
||||
final isolateDataSectionSymbol = elf.dynamicSymbolFor(
|
||||
isolateDataSymbolName,
|
||||
);
|
||||
Expect.isNotNull(isolateDataSectionSymbol);
|
||||
final textSectionSymbol = elf.dynamicSymbolFor(textSymbolName);
|
||||
Expect.isNotNull(textSectionSymbol);
|
||||
final dataSectionSymbol = elf.dynamicSymbolFor(dataSymbolName);
|
||||
Expect.isNotNull(dataSectionSymbol);
|
||||
|
||||
final actualSize =
|
||||
vmTextSectionSymbol!.size +
|
||||
vmDataSectionSymbol!.size +
|
||||
isolateTextSectionSymbol!.size +
|
||||
isolateDataSectionSymbol!.size;
|
||||
final actualSize = textSectionSymbol!.size + dataSectionSymbol!.size;
|
||||
|
||||
Expect.equals(
|
||||
expectedSize,
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2012, 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.
|
||||
"""Script to create snapshot bin file."""
|
||||
|
||||
import getopt
|
||||
import optparse
|
||||
import os
|
||||
from os.path import basename, join
|
||||
import sys
|
||||
import utils
|
||||
|
||||
|
||||
def BuildOptions():
|
||||
result = optparse.OptionParser()
|
||||
result.add_option(
|
||||
"--executable",
|
||||
action="store",
|
||||
type="string",
|
||||
help="path to snapshot generator executable")
|
||||
result.add_option(
|
||||
"--snapshot_kind",
|
||||
action="store",
|
||||
type="string",
|
||||
help="kind of snapshot to generate",
|
||||
default="core")
|
||||
result.add_option(
|
||||
"--vm_flag",
|
||||
action="append",
|
||||
type="string",
|
||||
default=[],
|
||||
help="pass additional Dart VM flag")
|
||||
result.add_option(
|
||||
"--vm_output_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="output file name into which vm isolate snapshot in binary form " +
|
||||
"is generated")
|
||||
result.add_option(
|
||||
"--vm_instructions_output_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="output file name into which vm isolate snapshot in binary form " +
|
||||
"is generated")
|
||||
result.add_option(
|
||||
"--isolate_output_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="output file name into which isolate snapshot in binary form " +
|
||||
"is generated")
|
||||
result.add_option(
|
||||
"--isolate_instructions_output_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="output file name into which isolate snapshot in binary form " +
|
||||
"is generated")
|
||||
result.add_option(
|
||||
"--script",
|
||||
action="store",
|
||||
type="string",
|
||||
help="Dart script for which snapshot is to be generated")
|
||||
result.add_option(
|
||||
"--packages",
|
||||
action="store",
|
||||
type="string",
|
||||
help="package config file used to reasolve package: imports.")
|
||||
result.add_option(
|
||||
"-v",
|
||||
"--verbose",
|
||||
help='Verbose output.',
|
||||
default=False,
|
||||
action="store_true")
|
||||
result.add_option(
|
||||
"--timestamp_file",
|
||||
action="store",
|
||||
type="string",
|
||||
help="Path to timestamp file that will be written",
|
||||
default="")
|
||||
return result
|
||||
|
||||
|
||||
def ProcessOptions(options):
|
||||
if not options.executable:
|
||||
sys.stderr.write('--executable not specified\n')
|
||||
return False
|
||||
if not options.snapshot_kind:
|
||||
sys.stderr.write('--snapshot_kind not specified\n')
|
||||
return False
|
||||
if not options.vm_output_bin:
|
||||
sys.stderr.write('--vm_output_bin not specified\n')
|
||||
return False
|
||||
if not options.isolate_output_bin:
|
||||
sys.stderr.write('--isolate_output_bin not specified\n')
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def CreateTimestampFile(options):
|
||||
if options.timestamp_file != '':
|
||||
dir_name = os.path.dirname(options.timestamp_file)
|
||||
if not os.path.exists(dir_name):
|
||||
os.mkdir(dir_name)
|
||||
open(options.timestamp_file, 'w').close()
|
||||
|
||||
|
||||
def Main():
|
||||
# Parse options.
|
||||
parser = BuildOptions()
|
||||
(options, args) = parser.parse_args()
|
||||
if not ProcessOptions(options):
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
# If there are additional arguments, report error and exit.
|
||||
if args:
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
# Setup arguments to the snapshot generator binary.
|
||||
script_args = ["--ignore_unrecognized_flags"]
|
||||
|
||||
for flag in options.vm_flag:
|
||||
script_args.append(flag)
|
||||
|
||||
# Pass along the packages if there is one.
|
||||
if options.packages:
|
||||
script_args.append(''.join(["--packages=", options.packages]))
|
||||
|
||||
# First setup the vm isolate and regular isolate snapshot output filename.
|
||||
script_args.append(''.join(["--snapshot_kind=", options.snapshot_kind]))
|
||||
script_args.append(''.join(["--vm_snapshot_data=", options.vm_output_bin]))
|
||||
script_args.append(''.join(
|
||||
["--isolate_snapshot_data=", options.isolate_output_bin]))
|
||||
|
||||
if options.vm_instructions_output_bin != None:
|
||||
script_args.append(''.join(
|
||||
["--vm_snapshot_instructions=",
|
||||
options.vm_instructions_output_bin]))
|
||||
if options.isolate_instructions_output_bin != None:
|
||||
script_args.append(''.join([
|
||||
"--isolate_snapshot_instructions=",
|
||||
options.isolate_instructions_output_bin
|
||||
]))
|
||||
|
||||
# Finally append the script name if one is specified.
|
||||
if options.script:
|
||||
script_args.append(options.script)
|
||||
|
||||
# Construct command line to execute the snapshot generator binary and invoke.
|
||||
command = [options.executable] + script_args
|
||||
try:
|
||||
utils.RunCommand(
|
||||
command,
|
||||
outStream=sys.stderr,
|
||||
errStream=sys.stderr,
|
||||
verbose=options.verbose,
|
||||
printErrorInfo=True)
|
||||
except Exception as e:
|
||||
return -1
|
||||
|
||||
# Success, update timestamp file.
|
||||
CreateTimestampFile(options)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(Main())
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2011, 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.
|
||||
|
||||
# Script to convert snapshot files to a C++ file which can be compiled and
|
||||
# linked together with VM binary.
|
||||
|
||||
import getopt
|
||||
import optparse
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import utils
|
||||
|
||||
HOST_OS = utils.GuessOS()
|
||||
HOST_CPUS = utils.GuessCpus()
|
||||
|
||||
|
||||
def BuildOptions():
|
||||
result = optparse.OptionParser()
|
||||
result.add_option(
|
||||
"--vm_input_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="input file name of the vm isolate snapshot in binary form")
|
||||
result.add_option(
|
||||
"--input_bin",
|
||||
action="store",
|
||||
type="string",
|
||||
help="input file name of the isolate snapshot in binary form")
|
||||
result.add_option(
|
||||
"--input_cc",
|
||||
action="store",
|
||||
type="string",
|
||||
help="input file name which contains the C buffer template")
|
||||
result.add_option(
|
||||
"--output",
|
||||
action="store",
|
||||
type="string",
|
||||
help="output file name into which snapshot in C buffer form is generated"
|
||||
)
|
||||
result.add_option(
|
||||
"-v",
|
||||
"--verbose",
|
||||
help='Verbose output.',
|
||||
default=False,
|
||||
action="store_true")
|
||||
return result
|
||||
|
||||
|
||||
def ProcessOptions(options):
|
||||
if not options.vm_input_bin:
|
||||
sys.stderr.write('--vm_input_bin not specified\n')
|
||||
return False
|
||||
if not options.input_bin:
|
||||
sys.stderr.write('--input_bin not specified\n')
|
||||
return False
|
||||
if not options.input_cc:
|
||||
sys.stderr.write('--input_cc not specified\n')
|
||||
return False
|
||||
if not options.output:
|
||||
sys.stderr.write('--output not specified\n')
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def WriteBytesAsText(out, input_file):
|
||||
"""Writes byte contents of the input_file into out file as text.
|
||||
|
||||
Output is formatted as a list of comma separated integer values - one value
|
||||
for each byte.
|
||||
"""
|
||||
with open(input_file, 'rb') as input:
|
||||
lineCounter = 0
|
||||
line = ' '
|
||||
for byte in input.read():
|
||||
line += ' %d,' % ord(byte)
|
||||
lineCounter += 1
|
||||
if lineCounter == 10:
|
||||
out.write(line + '\n')
|
||||
line = ' '
|
||||
lineCounter = 0
|
||||
if lineCounter != 0:
|
||||
out.write(line + '\n')
|
||||
|
||||
|
||||
def GenerateFileFromTemplate(output_file, input_cc_file, vm_isolate_input_file,
|
||||
isolate_input_file):
|
||||
"""Generates C++ file based on a input_cc_file template and two binary files
|
||||
|
||||
Template is expected to have two %s placeholders which would be filled
|
||||
with binary contents of the given files each formatted as a comma separated
|
||||
list of integers.
|
||||
"""
|
||||
snapshot_cc_text = open(input_cc_file).read()
|
||||
chunks = snapshot_cc_text.split("%s")
|
||||
if len(chunks) != 3:
|
||||
raise Exception("Template %s should contain exactly two %%s occurrences"
|
||||
% input_cc_file)
|
||||
|
||||
with open(output_file, 'w') as out:
|
||||
out.write(chunks[0])
|
||||
WriteBytesAsText(out, vm_isolate_input_file)
|
||||
out.write(chunks[1])
|
||||
WriteBytesAsText(out, isolate_input_file)
|
||||
out.write(chunks[2])
|
||||
|
||||
|
||||
def Main():
|
||||
# Parse options.
|
||||
parser = BuildOptions()
|
||||
(options, args) = parser.parse_args()
|
||||
if not ProcessOptions(options):
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
# If there are additional arguments, report error and exit.
|
||||
if args:
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
GenerateFileFromTemplate(options.output, options.input_cc,
|
||||
options.vm_input_bin, options.input_bin)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(Main())
|
||||
@@ -270,26 +270,13 @@ namespace {
|
||||
// instructions section by comparing payloads.
|
||||
const char* TryIdentifyIsolateSpecificStubCopy(ObjectStore* object_store,
|
||||
const Code& code) {
|
||||
#define MATCH(member, name) \
|
||||
if (object_store->member() != Code::null() && \
|
||||
StubCode::name().ptr() == object_store->member() && \
|
||||
StubCode::name().Size() == code.Size() && \
|
||||
memcmp(reinterpret_cast<void*>(code.PayloadStart()), \
|
||||
reinterpret_cast<void*>(StubCode::name().PayloadStart()), \
|
||||
code.Size()) == 0) { \
|
||||
return "_iso_stub_" #name "Stub"; \
|
||||
}
|
||||
OBJECT_STORE_STUB_CODE_LIST(MATCH)
|
||||
#undef MATCH
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SnapshotAnalyzer::DumpCode(const Code& code) {
|
||||
js_.PrintProperty("type", "Code");
|
||||
const auto instruction_base =
|
||||
reinterpret_cast<uint64_t>(info_.vm_isolate_instructions);
|
||||
const auto instruction_base = reinterpret_cast<uint64_t>(info_.snapshot_text);
|
||||
|
||||
if (code.IsUnknownDartCode()) {
|
||||
js_.PrintProperty64("offset", 0);
|
||||
@@ -357,8 +344,7 @@ void SnapshotAnalyzer::DumpCode(uword start_pc,
|
||||
uword end_pc,
|
||||
const char* name) {
|
||||
js_.PrintProperty("type", "Code");
|
||||
const auto instruction_base =
|
||||
reinterpret_cast<uint64_t>(info_.vm_isolate_instructions);
|
||||
const auto instruction_base = reinterpret_cast<uint64_t>(info_.snapshot_text);
|
||||
|
||||
js_.PrintProperty64("offset",
|
||||
static_cast<uint64_t>(start_pc) - instruction_base);
|
||||
@@ -662,11 +648,10 @@ void SnapshotAnalyzer::DumpSnapshotInformation(char** buffer,
|
||||
js_.OpenObject();
|
||||
js_.OpenObject("snapshot_data");
|
||||
// Base addresses of the snapshot data, useful to calculate relative offsets.
|
||||
js_.PrintfProperty("vm_data", "%p", info_.vm_snapshot_data);
|
||||
js_.PrintfProperty("vm_instructions", "%p", info_.vm_snapshot_instructions);
|
||||
js_.PrintfProperty("isolate_data", "%p", info_.vm_isolate_data);
|
||||
js_.PrintfProperty("isolate_instructions", "%p",
|
||||
info_.vm_isolate_instructions);
|
||||
js_.PrintfProperty("vm_data", "%p", nullptr);
|
||||
js_.PrintfProperty("vm_instructions", "%p", nullptr);
|
||||
js_.PrintfProperty("isolate_data", "%p", info_.snapshot_data);
|
||||
js_.PrintfProperty("isolate_instructions", "%p", info_.snapshot_text);
|
||||
js_.CloseObject();
|
||||
|
||||
{
|
||||
|
||||
+492
-664
File diff suppressed because it is too large
Load Diff
+10
-24
@@ -71,7 +71,8 @@ class LoadingUnitSerializationData : public ZoneObject {
|
||||
// the VM has been initialized.
|
||||
class SnapshotHeaderReader {
|
||||
public:
|
||||
static char* InitializeGlobalVMFlagsFromSnapshot(const Snapshot* snapshot);
|
||||
static char* InitializeIsolateGroupFlagsFromSnapshot(
|
||||
const Snapshot* snapshot);
|
||||
|
||||
explicit SnapshotHeaderReader(const Snapshot* snapshot)
|
||||
: SnapshotHeaderReader(snapshot->kind(),
|
||||
@@ -85,8 +86,6 @@ class SnapshotHeaderReader {
|
||||
stream_.SetPosition(Snapshot::kHeaderSize);
|
||||
}
|
||||
|
||||
void SetCoverageFromSnapshotFeatures(IsolateGroup* isolate_group);
|
||||
|
||||
// Verifies the version and features in the snapshot are compatible with the
|
||||
// current VM. If isolate is non-null it validates isolate-specific features.
|
||||
//
|
||||
@@ -107,45 +106,33 @@ class SnapshotHeaderReader {
|
||||
|
||||
class FullSnapshotWriter {
|
||||
public:
|
||||
static constexpr intptr_t kInitialSize = 64 * KB;
|
||||
static constexpr intptr_t kInitialSize = 2 * MB;
|
||||
FullSnapshotWriter(Snapshot::Kind kind,
|
||||
NonStreamingWriteStream* vm_snapshot_data,
|
||||
NonStreamingWriteStream* isolate_snapshot_data,
|
||||
ImageWriter* vm_image_writer,
|
||||
ImageWriter* iso_image_writer);
|
||||
NonStreamingWriteStream* snapshot_data,
|
||||
ImageWriter* image_writer);
|
||||
~FullSnapshotWriter();
|
||||
|
||||
// Writes a full snapshot of the program(VM isolate, regular isolate group).
|
||||
// Writes a full snapshot of the program.
|
||||
void WriteFullSnapshot(
|
||||
GrowableArray<LoadingUnitSerializationData*>* data = nullptr);
|
||||
// Writes a snapshot for a deferred loading unit.
|
||||
void WriteUnitSnapshot(GrowableArray<LoadingUnitSerializationData*>* units,
|
||||
LoadingUnitSerializationData* unit,
|
||||
uint32_t program_hash);
|
||||
|
||||
intptr_t VmIsolateSnapshotSize() const { return vm_isolate_snapshot_size_; }
|
||||
intptr_t IsolateSnapshotSize() const { return isolate_snapshot_size_; }
|
||||
|
||||
private:
|
||||
Thread* thread() const { return thread_; }
|
||||
Zone* zone() const { return thread_->zone(); }
|
||||
IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
|
||||
Heap* heap() const { return isolate_group()->heap(); }
|
||||
|
||||
// Writes a snapshot of the VM Isolate.
|
||||
ZoneGrowableArray<Object*>* WriteVMSnapshot();
|
||||
|
||||
// Writes a full snapshot of regular Dart isolate group.
|
||||
void WriteProgramSnapshot(ZoneGrowableArray<Object*>* objects,
|
||||
GrowableArray<LoadingUnitSerializationData*>* data);
|
||||
void WriteProgramSnapshot(GrowableArray<LoadingUnitSerializationData*>* data);
|
||||
|
||||
Thread* thread_;
|
||||
Snapshot::Kind kind_;
|
||||
NonStreamingWriteStream* const vm_snapshot_data_;
|
||||
NonStreamingWriteStream* const isolate_snapshot_data_;
|
||||
intptr_t vm_isolate_snapshot_size_;
|
||||
intptr_t isolate_snapshot_size_;
|
||||
ImageWriter* vm_image_writer_;
|
||||
ImageWriter* isolate_image_writer_;
|
||||
NonStreamingWriteStream* const snapshot_data_;
|
||||
ImageWriter* image_writer_;
|
||||
|
||||
// Stats for benchmarking.
|
||||
intptr_t clustered_vm_size_ = 0;
|
||||
@@ -169,7 +156,6 @@ class FullSnapshotReader {
|
||||
|
||||
// On success, returns nullptr. On failure, returns an error message that the
|
||||
// caller must free.
|
||||
char* ReadVMSnapshot();
|
||||
char* ReadProgramSnapshot();
|
||||
char* ReadUnitSnapshot(const LoadingUnit& unit);
|
||||
|
||||
|
||||
@@ -378,15 +378,13 @@ BENCHMARK_SIZE(CoreSnapshotSize) {
|
||||
Api::CheckAndFinalizePendingClasses(thread);
|
||||
|
||||
// Write snapshot with object content.
|
||||
MallocWriteStream vm_snapshot_data(FullSnapshotWriter::kInitialSize);
|
||||
MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
|
||||
FullSnapshotWriter writer(
|
||||
Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
|
||||
/*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
|
||||
FullSnapshotWriter writer(Snapshot::kFull, &isolate_snapshot_data,
|
||||
/*image_writer=*/nullptr);
|
||||
writer.WriteFullSnapshot();
|
||||
const Snapshot* snapshot =
|
||||
Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
|
||||
ASSERT(snapshot->kind() == Snapshot::kFullCore);
|
||||
ASSERT(snapshot->kind() == Snapshot::kFull);
|
||||
benchmark->set_score(snapshot->length());
|
||||
}
|
||||
|
||||
@@ -415,15 +413,13 @@ BENCHMARK_SIZE(StandaloneSnapshotSize) {
|
||||
Api::CheckAndFinalizePendingClasses(thread);
|
||||
|
||||
// Write snapshot with object content.
|
||||
MallocWriteStream vm_snapshot_data(FullSnapshotWriter::kInitialSize);
|
||||
MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
|
||||
FullSnapshotWriter writer(
|
||||
Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
|
||||
/*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
|
||||
FullSnapshotWriter writer(Snapshot::kFull, &isolate_snapshot_data,
|
||||
/*image_writer=*/nullptr);
|
||||
writer.WriteFullSnapshot();
|
||||
const Snapshot* snapshot =
|
||||
Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
|
||||
ASSERT(snapshot->kind() == Snapshot::kFullCore);
|
||||
ASSERT(snapshot->kind() == Snapshot::kFull);
|
||||
benchmark->set_score(snapshot->length());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,8 @@ DECLARE_FLAG(int, old_gen_growth_space_ratio);
|
||||
|
||||
namespace bin {
|
||||
// Snapshot pieces if we link in a snapshot, otherwise initialized to nullptr.
|
||||
extern const uint8_t* vm_snapshot_data;
|
||||
extern const uint8_t* vm_snapshot_instructions;
|
||||
extern const uint8_t* core_isolate_snapshot_data;
|
||||
extern const uint8_t* core_isolate_snapshot_instructions;
|
||||
extern const uint8_t* core_snapshot_data;
|
||||
extern const uint8_t* core_snapshot_text;
|
||||
} // namespace bin
|
||||
|
||||
// The BENCHMARK macros are used for benchmarking a specific functionality
|
||||
|
||||
@@ -23,31 +23,7 @@ ClassTable::ClassTable(ClassTableAllocator* allocator)
|
||||
: allocator_(allocator),
|
||||
classes_(allocator),
|
||||
top_level_classes_(allocator) {
|
||||
if (Dart::vm_isolate() == nullptr) {
|
||||
classes_.SetNumCidsAndCapacity(kNumPredefinedCids, kInitialCapacity);
|
||||
} else {
|
||||
// Duplicate the class table from the VM isolate.
|
||||
ClassTable* vm_class_table = Dart::vm_isolate_group()->class_table();
|
||||
classes_.SetNumCidsAndCapacity(kNumPredefinedCids,
|
||||
vm_class_table->classes_.capacity());
|
||||
|
||||
const auto copy_info_for_cid = [&](intptr_t cid) {
|
||||
classes_.At<kClassIndex>(cid) = vm_class_table->At(cid);
|
||||
classes_.At<kSizeIndex>(cid) = vm_class_table->SizeAt(cid);
|
||||
};
|
||||
|
||||
// The following cids don't have a corresponding class object in Dart code.
|
||||
// We therefore need to initialize them eagerly.
|
||||
COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1);
|
||||
for (intptr_t i = kObjectCid; i <= kLastInternalOnlyCid; i++) {
|
||||
copy_info_for_cid(i);
|
||||
}
|
||||
copy_info_for_cid(kTypeArgumentsCid);
|
||||
copy_info_for_cid(kFreeListElement);
|
||||
copy_info_for_cid(kForwardingCorpse);
|
||||
copy_info_for_cid(kDynamicCid);
|
||||
copy_info_for_cid(kVoidCid);
|
||||
}
|
||||
classes_.SetNumCidsAndCapacity(kNumPredefinedCids, kInitialCapacity);
|
||||
UpdateCachedAllocationTracingStateTablePointer();
|
||||
}
|
||||
|
||||
|
||||
@@ -511,7 +511,7 @@ class ClassTable : public MallocAllocated {
|
||||
const char* name,
|
||||
char** error);
|
||||
friend class IsolateGroup; // for table()
|
||||
static constexpr int kInitialCapacity = 512;
|
||||
static constexpr int kInitialCapacity = 4 * KB;
|
||||
|
||||
static constexpr intptr_t kTopLevelCidOffset = kClassIdTagMax + 1;
|
||||
|
||||
|
||||
@@ -518,17 +518,6 @@ void Precompiler::DoCompileAll() {
|
||||
|
||||
global_object_pool_builder()->Reset();
|
||||
stub_pool.CopyInto(global_object_pool_builder());
|
||||
|
||||
// We have various stubs we would like to generate inside the isolate,
|
||||
// to ensure the rest of the AOT compilation will use the
|
||||
// isolate-specific stubs (callable via pc-relative calls).
|
||||
auto& stub_code = Code::Handle();
|
||||
#define DO(member, name) \
|
||||
stub_code = StubCode::BuildIsolateSpecific##name##Stub( \
|
||||
global_object_pool_builder()); \
|
||||
IG->object_store()->set_##member(stub_code);
|
||||
OBJECT_STORE_STUB_CODE_LIST(DO)
|
||||
#undef DO
|
||||
}
|
||||
|
||||
CollectDynamicFunctionNames();
|
||||
@@ -2434,9 +2423,6 @@ void Precompiler::AttachOptimizedTypeTestingStub() {
|
||||
|
||||
// Find all type objects in this isolate.
|
||||
IG->heap()->VisitObjects(&visitor);
|
||||
|
||||
// Find all type objects in the vm-isolate.
|
||||
Dart::vm_isolate_group()->heap()->VisitObjects(&visitor);
|
||||
}
|
||||
|
||||
TypeUsageInfo* type_usage_info = Thread::Current()->type_usage_info();
|
||||
@@ -2450,12 +2436,9 @@ void Precompiler::AttachOptimizedTypeTestingStub() {
|
||||
for (intptr_t i = 0; i < types.length(); i++) {
|
||||
const AbstractType& type = types.At(i);
|
||||
|
||||
if (type.InVMIsolateHeap()) {
|
||||
// The only important types in the vm isolate are
|
||||
// "dynamic"/"void"/"Never", which will get their optimized
|
||||
// testing stub installed at creation.
|
||||
continue;
|
||||
}
|
||||
if (type.type_class_id() == kDynamicCid) continue;
|
||||
if (type.type_class_id() == kVoidCid) continue;
|
||||
if (type.type_class_id() == kNeverCid) continue;
|
||||
|
||||
if (type_usage_info->IsUsedInTypeTest(type)) {
|
||||
code = type_testing_stubs.OptimizedCodeForType(type);
|
||||
|
||||
@@ -3162,20 +3162,19 @@ const RuntimeEntry& NullErrorSlowPath::GetRuntimeEntry(
|
||||
CodePtr NullErrorSlowPath::GetStub(FlowGraphCompiler* compiler,
|
||||
CheckNullInstr::ExceptionType exception_type,
|
||||
bool save_fpu_registers) {
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
switch (exception_type) {
|
||||
case CheckNullInstr::kNoSuchMethod:
|
||||
return save_fpu_registers
|
||||
? object_store->null_error_stub_with_fpu_regs_stub()
|
||||
: object_store->null_error_stub_without_fpu_regs_stub();
|
||||
? StubCode::NullErrorSharedWithFPURegs().ptr()
|
||||
: StubCode::NullErrorSharedWithoutFPURegs().ptr();
|
||||
case CheckNullInstr::kArgumentError:
|
||||
return save_fpu_registers
|
||||
? object_store->null_arg_error_stub_with_fpu_regs_stub()
|
||||
: object_store->null_arg_error_stub_without_fpu_regs_stub();
|
||||
? StubCode::NullArgErrorSharedWithFPURegs().ptr()
|
||||
: StubCode::NullArgErrorSharedWithoutFPURegs().ptr();
|
||||
case CheckNullInstr::kCastError:
|
||||
return save_fpu_registers
|
||||
? object_store->null_cast_error_stub_with_fpu_regs_stub()
|
||||
: object_store->null_cast_error_stub_without_fpu_regs_stub();
|
||||
? StubCode::NullCastErrorSharedWithFPURegs().ptr()
|
||||
: StubCode::NullCastErrorSharedWithoutFPURegs().ptr();
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -3217,12 +3216,9 @@ void RangeErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
save_fpu_registers
|
||||
? object_store->range_error_stub_with_fpu_regs_stub()
|
||||
: object_store->range_error_stub_without_fpu_regs_stub());
|
||||
const auto& stub = save_fpu_registers
|
||||
? StubCode::RangeErrorSharedWithFPURegs()
|
||||
: StubCode::RangeErrorSharedWithoutFPURegs();
|
||||
compiler->EmitCallToStub(stub);
|
||||
#endif
|
||||
}
|
||||
@@ -3240,12 +3236,9 @@ void WriteErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler,
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
save_fpu_registers
|
||||
? object_store->write_error_stub_with_fpu_regs_stub()
|
||||
: object_store->write_error_stub_without_fpu_regs_stub());
|
||||
const auto& stub = save_fpu_registers
|
||||
? StubCode::WriteErrorSharedWithFPURegs()
|
||||
: StubCode::WriteErrorSharedWithoutFPURegs();
|
||||
compiler->EmitCallToStub(stub);
|
||||
#endif
|
||||
}
|
||||
@@ -3265,13 +3258,10 @@ void LateInitializationErrorSlowPath::EmitSharedStubCall(
|
||||
LateInitializationErrorABI::kFieldReg);
|
||||
__ LoadObject(LateInitializationErrorABI::kFieldReg,
|
||||
Field::ZoneHandle(OriginalField()));
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
const auto& stub =
|
||||
save_fpu_registers
|
||||
? object_store->late_initialization_error_stub_with_fpu_regs_stub()
|
||||
: object_store
|
||||
->late_initialization_error_stub_without_fpu_regs_stub());
|
||||
? StubCode::LateInitializationErrorSharedWithFPURegs()
|
||||
: StubCode::LateInitializationErrorSharedWithoutFPURegs();
|
||||
compiler->EmitCallToStub(stub);
|
||||
#endif
|
||||
}
|
||||
@@ -3533,14 +3523,12 @@ bool FlowGraphCompiler::CanPcRelativeCall(const Function& target) const {
|
||||
|
||||
bool FlowGraphCompiler::CanPcRelativeCall(const Code& target) const {
|
||||
return FLAG_precompiled_mode && !FLAG_force_indirect_calls &&
|
||||
!target.InVMIsolateHeap() &&
|
||||
(LoadingUnit::LoadingUnitOf(function()) ==
|
||||
LoadingUnit::LoadingUnitOf(target));
|
||||
}
|
||||
|
||||
bool FlowGraphCompiler::CanPcRelativeCall(const AbstractType& target) const {
|
||||
return FLAG_precompiled_mode && !FLAG_force_indirect_calls &&
|
||||
!target.InVMIsolateHeap() &&
|
||||
(LoadingUnit::LoadingUnitOf(function()) ==
|
||||
LoadingUnit::LoadingUnit::kRootId);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@ DECLARE_FLAG(bool, enable_simd_inline);
|
||||
|
||||
void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
if (FLAG_precompiled_mode) {
|
||||
auto object_store = isolate_group()->object_store();
|
||||
|
||||
const auto& stub =
|
||||
Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
|
||||
const auto& stub = StubCode::WriteBarrierWrappers();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_write_barrier_wrapper_ =
|
||||
[&](Condition condition, Register reg) {
|
||||
@@ -45,8 +42,7 @@ void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
};
|
||||
}
|
||||
|
||||
const auto& array_stub =
|
||||
Code::ZoneHandle(object_store->array_write_barrier_stub());
|
||||
const auto& array_stub = StubCode::ArrayWriteBarrier();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_array_write_barrier_ =
|
||||
[&](Condition condition) {
|
||||
|
||||
@@ -30,10 +30,7 @@ DECLARE_FLAG(bool, enable_simd_inline);
|
||||
|
||||
void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
if (FLAG_precompiled_mode) {
|
||||
auto object_store = isolate_group()->object_store();
|
||||
|
||||
const auto& stub =
|
||||
Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
|
||||
const auto& stub = StubCode::WriteBarrierWrappers();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
|
||||
const intptr_t offset_into_target =
|
||||
@@ -43,8 +40,7 @@ void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
};
|
||||
}
|
||||
|
||||
const auto& array_stub =
|
||||
Code::ZoneHandle(object_store->array_write_barrier_stub());
|
||||
const auto& array_stub = StubCode::ArrayWriteBarrier();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_array_write_barrier_ = [&]() {
|
||||
assembler_->GenerateUnRelocatedPcRelativeCall();
|
||||
|
||||
@@ -430,7 +430,8 @@ void FlowGraphCompiler::EmitPrologue() {
|
||||
void FlowGraphCompiler::EmitCallToStub(
|
||||
const Code& stub,
|
||||
ObjectPool::SnapshotBehavior snapshot_behavior) {
|
||||
if (stub.InVMIsolateHeap()) {
|
||||
if (stub.IsStubCode()) {
|
||||
// Assumes the stub's Code object will not move.
|
||||
__ CallVmStub(stub);
|
||||
} else {
|
||||
// Ignore snapshot_behavior, ia32 doesn't do snapshots.
|
||||
|
||||
@@ -30,10 +30,7 @@ DECLARE_FLAG(bool, enable_simd_inline);
|
||||
|
||||
void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
if (FLAG_precompiled_mode) {
|
||||
auto object_store = isolate_group()->object_store();
|
||||
|
||||
const auto& stub =
|
||||
Code::ZoneHandle(object_store->write_barrier_wrappers_stub());
|
||||
const auto& stub = StubCode::WriteBarrierWrappers();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_write_barrier_wrapper_ = [&](Register reg) {
|
||||
const intptr_t offset_into_target =
|
||||
@@ -43,8 +40,7 @@ void FlowGraphCompiler::ArchSpecificInitialization() {
|
||||
};
|
||||
}
|
||||
|
||||
const auto& array_stub =
|
||||
Code::ZoneHandle(object_store->array_write_barrier_stub());
|
||||
const auto& array_stub = StubCode::ArrayWriteBarrier();
|
||||
if (CanPcRelativeCall(stub)) {
|
||||
assembler_->generate_invoke_array_write_barrier_ = [&]() {
|
||||
assembler_->GenerateUnRelocatedPcRelativeCall();
|
||||
|
||||
@@ -229,7 +229,7 @@ void HierarchyInfo::BuildRangesFor(ClassTable* table,
|
||||
bool exclude_null) {
|
||||
// Use the class table in cases where the direct subclasses and implementors
|
||||
// are not filled out.
|
||||
if (dst_klass.InVMIsolateHeap() || dst_klass.id() == kInstanceCid) {
|
||||
if (dst_klass.id() == kInstanceCid) {
|
||||
BuildRangesUsingClassTableFor(table, ranges, dst_klass, include_abstract,
|
||||
exclude_null);
|
||||
return;
|
||||
@@ -971,21 +971,20 @@ LocationSummary* AllocateClosureInstr::MakeLocationSummary(Zone* zone,
|
||||
}
|
||||
|
||||
void AllocateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
Code& stub = Code::ZoneHandle(compiler->zone());
|
||||
const intptr_t num_elements = NumElements();
|
||||
switch (num_elements) {
|
||||
case 1:
|
||||
stub = object_store->allocate_closure1_stub();
|
||||
stub = StubCode::AllocateClosure1().ptr();
|
||||
break;
|
||||
case 2:
|
||||
stub = object_store->allocate_closure2_stub();
|
||||
stub = StubCode::AllocateClosure2().ptr();
|
||||
break;
|
||||
case 3:
|
||||
stub = object_store->allocate_closure3_stub();
|
||||
stub = StubCode::AllocateClosure3().ptr();
|
||||
break;
|
||||
case 4:
|
||||
stub = object_store->allocate_closure4_stub();
|
||||
stub = StubCode::AllocateClosure4().ptr();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@@ -1416,7 +1415,14 @@ bool Value::NeedsWriteBarrier() {
|
||||
return false;
|
||||
} else {
|
||||
const Object& constant = value->BoundConstant();
|
||||
return constant.ptr()->IsHeapObject() && !constant.InVMIsolateHeap();
|
||||
if (constant.ptr()->IsImmediateObject()) {
|
||||
return false;
|
||||
}
|
||||
// N.B.: Not Page::Of(constant)->is_never_evacuate() because Page::Of
|
||||
// requires us to first filter out image page objects.
|
||||
Page* page = Page::Of(Object::null());
|
||||
ASSERT(page->is_never_evacuate());
|
||||
return !page->Contains(UntaggedObject::ToAddr(constant.ptr()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4592,7 +4598,6 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
ASSERT((FLAG_experimental_shared_data && !field().is_shared()) ||
|
||||
(field().has_initializer() && field().is_late()));
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const Field& original_field = Field::ZoneHandle(field().Original());
|
||||
|
||||
compiler::Label no_call;
|
||||
@@ -4602,7 +4607,7 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
auto& stub = Code::ZoneHandle(compiler->zone());
|
||||
if (calls_initializer()) {
|
||||
if (field().needs_load_guard()) {
|
||||
stub = object_store->init_static_field_stub();
|
||||
stub = StubCode::InitStaticField().ptr();
|
||||
} else {
|
||||
// The stubs below call the initializer function directly, so make sure
|
||||
// one is created.
|
||||
@@ -4610,14 +4615,14 @@ void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
original_field.EnsureInitializerFunction();
|
||||
}
|
||||
stub = field().is_shared()
|
||||
? object_store->init_shared_late_static_field_stub()
|
||||
? StubCode::InitSharedLateStaticField().ptr()
|
||||
: (field().is_final()
|
||||
? object_store->init_late_final_static_field_stub()
|
||||
: object_store->init_late_static_field_stub());
|
||||
? StubCode::InitLateFinalStaticField().ptr()
|
||||
: StubCode::InitLateStaticField().ptr());
|
||||
}
|
||||
} else {
|
||||
ASSERT(FLAG_experimental_shared_data && !field().is_shared());
|
||||
stub = object_store->check_isolate_field_access_stub();
|
||||
stub = StubCode::CheckIsolateFieldAccess().ptr();
|
||||
}
|
||||
|
||||
__ LoadObject(InitStaticFieldABI::kFieldReg, original_field);
|
||||
@@ -4789,22 +4794,21 @@ void LoadFieldInstr::EmitNativeCodeForInitializerCall(
|
||||
|
||||
__ LoadObject(InitInstanceFieldABI::kFieldReg, original_field);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
auto& stub = Code::ZoneHandle(compiler->zone());
|
||||
if (field.needs_load_guard()) {
|
||||
stub = object_store->init_instance_field_stub();
|
||||
stub = StubCode::InitInstanceField().ptr();
|
||||
} else if (field.is_late()) {
|
||||
if (!field.has_nontrivial_initializer()) {
|
||||
stub = object_store->init_instance_field_stub();
|
||||
stub = StubCode::InitInstanceField().ptr();
|
||||
} else {
|
||||
// Stubs for late field initialization call initializer
|
||||
// function directly, so make sure one is created.
|
||||
original_field.EnsureInitializerFunction();
|
||||
|
||||
if (field.is_final()) {
|
||||
stub = object_store->init_late_final_instance_field_stub();
|
||||
stub = StubCode::InitLateFinalInstanceField().ptr();
|
||||
} else {
|
||||
stub = object_store->init_late_instance_field_stub();
|
||||
stub = StubCode::InitLateInstanceField().ptr();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -4827,11 +4831,7 @@ LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
|
||||
}
|
||||
|
||||
void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& throw_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->throw_stub());
|
||||
|
||||
compiler->GenerateStubCall(source(), throw_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::Throw(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
// Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
|
||||
@@ -4854,12 +4854,8 @@ LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const {
|
||||
}
|
||||
|
||||
void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& re_throw_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->re_throw_stub());
|
||||
|
||||
compiler->SetNeedsStackTrace(catch_try_index());
|
||||
compiler->GenerateStubCall(source(), re_throw_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::ReThrow(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
// Issue(dartbug.com/41353): Right now we have to emit an extra breakpoint
|
||||
@@ -8322,18 +8318,11 @@ const Code& DartReturnInstr::GetReturnStub(FlowGraphCompiler* compiler) const {
|
||||
ASSERT(function.IsSuspendableFunction());
|
||||
if (function.IsAsyncFunction()) {
|
||||
if (compiler->is_optimizing() && !value()->Type()->CanBeFuture()) {
|
||||
return Code::ZoneHandle(compiler->zone(),
|
||||
compiler->isolate_group()
|
||||
->object_store()
|
||||
->return_async_not_future_stub());
|
||||
return StubCode::ReturnAsyncNotFuture();
|
||||
}
|
||||
return Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
compiler->isolate_group()->object_store()->return_async_stub());
|
||||
return StubCode::ReturnAsync();
|
||||
} else if (function.IsAsyncGenerator()) {
|
||||
return Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
compiler->isolate_group()->object_store()->return_async_star_stub());
|
||||
return StubCode::ReturnAsyncStar();
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -8895,23 +8884,22 @@ LocationSummary* Call1ArgStubInstr::MakeLocationSummary(Zone* zone,
|
||||
}
|
||||
|
||||
void Call1ArgStubInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ObjectStore* object_store = compiler->isolate_group()->object_store();
|
||||
Code& stub = Code::ZoneHandle(compiler->zone());
|
||||
switch (stub_id_) {
|
||||
case StubId::kCloneSuspendState:
|
||||
stub = object_store->clone_suspend_state_stub();
|
||||
stub = StubCode::CloneSuspendState().ptr();
|
||||
break;
|
||||
case StubId::kInitAsync:
|
||||
stub = object_store->init_async_stub();
|
||||
stub = StubCode::InitAsync().ptr();
|
||||
break;
|
||||
case StubId::kInitAsyncStar:
|
||||
stub = object_store->init_async_star_stub();
|
||||
stub = StubCode::InitAsyncStar().ptr();
|
||||
break;
|
||||
case StubId::kInitSyncStar:
|
||||
stub = object_store->init_sync_star_stub();
|
||||
stub = StubCode::InitSyncStar().ptr();
|
||||
break;
|
||||
case StubId::kFfiAsyncCallbackSend:
|
||||
stub = object_store->ffi_async_callback_send_stub();
|
||||
stub = StubCode::FfiAsyncCallbackSend().ptr();
|
||||
break;
|
||||
}
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
@@ -8944,23 +8932,22 @@ void SuspendInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Use deopt_id as a yield index.
|
||||
compiler->EmitYieldPositionMetadata(source(), deopt_id());
|
||||
|
||||
ObjectStore* object_store = compiler->isolate_group()->object_store();
|
||||
Code& stub = Code::ZoneHandle(compiler->zone());
|
||||
switch (stub_id_) {
|
||||
case StubId::kAwait:
|
||||
stub = object_store->await_stub();
|
||||
stub = StubCode::Await().ptr();
|
||||
break;
|
||||
case StubId::kAwaitWithTypeCheck:
|
||||
stub = object_store->await_with_type_check_stub();
|
||||
stub = StubCode::AwaitWithTypeCheck().ptr();
|
||||
break;
|
||||
case StubId::kYieldAsyncStar:
|
||||
stub = object_store->yield_async_star_stub();
|
||||
stub = StubCode::YieldAsyncStar().ptr();
|
||||
break;
|
||||
case StubId::kSuspendSyncStarAtStart:
|
||||
stub = object_store->suspend_sync_star_at_start_stub();
|
||||
stub = StubCode::SuspendSyncStarAtStart().ptr();
|
||||
break;
|
||||
case StubId::kSuspendSyncStarAtYield:
|
||||
stub = object_store->suspend_sync_star_at_yield_stub();
|
||||
stub = StubCode::SuspendSyncStarAtYield().ptr();
|
||||
break;
|
||||
}
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
@@ -8993,9 +8980,7 @@ LocationSummary* AllocateRecordInstr::MakeLocationSummary(Zone* zone,
|
||||
}
|
||||
|
||||
void AllocateRecordInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Code& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
compiler->isolate_group()->object_store()->allocate_record_stub());
|
||||
const Code& stub = StubCode::AllocateRecord();
|
||||
__ LoadImmediate(AllocateRecordABI::kShapeReg,
|
||||
Smi::RawValue(shape().AsInt()));
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
@@ -9023,17 +9008,16 @@ LocationSummary* AllocateSmallRecordInstr::MakeLocationSummary(Zone* zone,
|
||||
}
|
||||
|
||||
void AllocateSmallRecordInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
Code& stub = Code::ZoneHandle(compiler->zone());
|
||||
if (shape().HasNamedFields()) {
|
||||
__ LoadImmediate(AllocateSmallRecordABI::kShapeReg,
|
||||
Smi::RawValue(shape().AsInt()));
|
||||
switch (num_fields()) {
|
||||
case 2:
|
||||
stub = object_store->allocate_record2_named_stub();
|
||||
stub = StubCode::AllocateRecord2Named().ptr();
|
||||
break;
|
||||
case 3:
|
||||
stub = object_store->allocate_record3_named_stub();
|
||||
stub = StubCode::AllocateRecord3Named().ptr();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
@@ -9041,10 +9025,10 @@ void AllocateSmallRecordInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
} else {
|
||||
switch (num_fields()) {
|
||||
case 2:
|
||||
stub = object_store->allocate_record2_stub();
|
||||
stub = StubCode::AllocateRecord2().ptr();
|
||||
break;
|
||||
case 3:
|
||||
stub = object_store->allocate_record3_stub();
|
||||
stub = StubCode::AllocateRecord3().ptr();
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -3134,10 +3134,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
__ Bind(&slow_path);
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_array_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
|
||||
compiler->GenerateStubCall(source(), allocate_array_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateArray(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
__ Bind(&done);
|
||||
@@ -3178,11 +3175,9 @@ class AllocateContextSlowPath
|
||||
instruction(), /*num_slow_path_args=*/0);
|
||||
ASSERT(slow_path_env != nullptr);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub = Code::ZoneHandle(
|
||||
compiler->zone(), object_store->allocate_context_stub());
|
||||
__ LoadImmediate(R1, instruction()->num_context_variables());
|
||||
compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(instruction()->source(),
|
||||
StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs,
|
||||
instruction()->deopt_id(), slow_path_env);
|
||||
ASSERT(instruction()->locs()->out(0).reg() == R0);
|
||||
@@ -3234,11 +3229,8 @@ void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->temp(0).reg() == R1);
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
|
||||
__ LoadImmediate(R1, num_context_variables());
|
||||
compiler->GenerateStubCall(source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
}
|
||||
@@ -3258,10 +3250,7 @@ void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->in(0).reg() == R4);
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& clone_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
|
||||
compiler->GenerateStubCall(source(), clone_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::CloneContext(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
}
|
||||
@@ -3404,13 +3393,10 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
compiler::target::Thread::stack_limit_offset()));
|
||||
__ cmp(SP, compiler::Operand(IP));
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs
|
||||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::StackOverflowSharedWithFPURegs()
|
||||
: StubCode::StackOverflowSharedWithoutFPURegs();
|
||||
const bool using_shared_stub = locs()->call_on_shared_slow_path();
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub) &&
|
||||
compiler->flow_graph().graph_entry()->NeedsFrame()) {
|
||||
@@ -4461,19 +4447,7 @@ LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
|
||||
// Shared slow path is used in BoxInt64Instr::EmitNativeCode in
|
||||
// precompiled mode and only after VM isolate stubs where
|
||||
// replaced with isolate-specific stubs.
|
||||
auto object_store = IsolateGroup::Current()->object_store();
|
||||
const bool stubs_in_vm_isolate =
|
||||
object_store->allocate_mint_with_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap() ||
|
||||
object_store->allocate_mint_without_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap();
|
||||
const bool shared_slow_path_call =
|
||||
SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
|
||||
const bool shared_slow_path_call = SlowPathSharingSupported(opt);
|
||||
LocationSummary* summary = new (zone) LocationSummary(
|
||||
zone, kNumInputs, kNumTemps,
|
||||
ValueFitsSmi()
|
||||
@@ -4527,12 +4501,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
|
||||
: object_store->allocate_mint_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::AllocateMintSharedWithFPURegs()
|
||||
: StubCode::AllocateMintSharedWithoutFPURegs();
|
||||
|
||||
ASSERT(!locs()->live_registers()->ContainsRegister(
|
||||
AllocateMintABI::kResultReg));
|
||||
|
||||
@@ -2744,10 +2744,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
__ Bind(&slow_path);
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_array_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
|
||||
compiler->GenerateStubCall(source(), allocate_array_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateArray(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
__ Bind(&done);
|
||||
@@ -2788,12 +2785,9 @@ class AllocateContextSlowPath
|
||||
instruction(), /*num_slow_path_args=*/0);
|
||||
ASSERT(slow_path_env != nullptr);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub = Code::ZoneHandle(
|
||||
compiler->zone(), object_store->allocate_context_stub());
|
||||
|
||||
__ LoadImmediate(R1, instruction()->num_context_variables());
|
||||
compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(instruction()->source(),
|
||||
StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs,
|
||||
instruction()->deopt_id(), slow_path_env);
|
||||
ASSERT(instruction()->locs()->out(0).reg() == R0);
|
||||
@@ -2844,11 +2838,8 @@ void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->temp(0).reg() == R1);
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
|
||||
__ LoadImmediate(R1, num_context_variables());
|
||||
compiler->GenerateStubCall(source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
}
|
||||
@@ -2868,10 +2859,7 @@ void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->in(0).reg() == R5);
|
||||
ASSERT(locs()->out(0).reg() == R0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& clone_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
|
||||
compiler->GenerateStubCall(source(), clone_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::CloneContext(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
}
|
||||
@@ -2965,13 +2953,10 @@ class CheckStackOverflowSlowPath
|
||||
__ TsanFuncEntry();
|
||||
}
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs
|
||||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::StackOverflowSharedWithFPURegs()
|
||||
: StubCode::StackOverflowSharedWithoutFPURegs();
|
||||
|
||||
if (compiler->CanPcRelativeCall(stub)) {
|
||||
__ GenerateUnRelocatedPcRelativeCall();
|
||||
@@ -3758,19 +3743,7 @@ LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
|
||||
// Shared slow path is used in BoxInt64Instr::EmitNativeCode in
|
||||
// precompiled mode and only after VM isolate stubs where
|
||||
// replaced with isolate-specific stubs.
|
||||
auto object_store = IsolateGroup::Current()->object_store();
|
||||
const bool stubs_in_vm_isolate =
|
||||
object_store->allocate_mint_with_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap() ||
|
||||
object_store->allocate_mint_without_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap();
|
||||
const bool shared_slow_path_call =
|
||||
SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
|
||||
const bool shared_slow_path_call = SlowPathSharingSupported(opt);
|
||||
LocationSummary* summary = new (zone) LocationSummary(
|
||||
zone, kNumInputs, kNumTemps,
|
||||
ValueFitsSmi() ? LocationSummary::kNoCall
|
||||
@@ -3825,12 +3798,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ TsanFuncEntry();
|
||||
}
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
|
||||
: object_store->allocate_mint_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::AllocateMintSharedWithFPURegs()
|
||||
: StubCode::AllocateMintSharedWithoutFPURegs();
|
||||
|
||||
ASSERT(!locs()->live_registers()->ContainsRegister(
|
||||
AllocateMintABI::kResultReg));
|
||||
|
||||
@@ -2349,10 +2349,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
__ Bind(&slow_path);
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_array_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
|
||||
compiler->GenerateStubCall(source(), allocate_array_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateArray(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
__ Bind(&done);
|
||||
|
||||
@@ -2947,10 +2947,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
__ Bind(&slow_path);
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_array_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
|
||||
compiler->GenerateStubCall(source(), allocate_array_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateArray(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
__ Bind(&done);
|
||||
@@ -2991,12 +2988,9 @@ class AllocateContextSlowPath
|
||||
instruction(), /*num_slow_path_args=*/0);
|
||||
ASSERT(slow_path_env != nullptr);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub = Code::ZoneHandle(
|
||||
compiler->zone(), object_store->allocate_context_stub());
|
||||
|
||||
__ LoadImmediate(T1, instruction()->num_context_variables());
|
||||
compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(instruction()->source(),
|
||||
StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs,
|
||||
instruction()->deopt_id(), slow_path_env);
|
||||
ASSERT(instruction()->locs()->out(0).reg() == A0);
|
||||
@@ -3047,11 +3041,8 @@ void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->temp(0).reg() == T1);
|
||||
ASSERT(locs()->out(0).reg() == A0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
|
||||
__ LoadImmediate(T1, num_context_variables());
|
||||
compiler->GenerateStubCall(source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
}
|
||||
@@ -3071,10 +3062,7 @@ void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->in(0).reg() == T5);
|
||||
ASSERT(locs()->out(0).reg() == A0);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& clone_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
|
||||
compiler->GenerateStubCall(source(), clone_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::CloneContext(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
}
|
||||
@@ -3170,13 +3158,10 @@ class CheckStackOverflowSlowPath
|
||||
__ TsanFuncEntry();
|
||||
}
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs
|
||||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::StackOverflowSharedWithFPURegs()
|
||||
: StubCode::StackOverflowSharedWithoutFPURegs();
|
||||
|
||||
if (compiler->CanPcRelativeCall(stub)) {
|
||||
__ GenerateUnRelocatedPcRelativeCall();
|
||||
@@ -4071,19 +4056,7 @@ void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
|
||||
LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
// Shared slow path is used in BoxInt64Instr::EmitNativeCode in
|
||||
// FLAG_use_bare_instructions mode and only after VM isolate stubs where
|
||||
// replaced with isolate-specific stubs.
|
||||
auto object_store = IsolateGroup::Current()->object_store();
|
||||
const bool stubs_in_vm_isolate =
|
||||
object_store->allocate_mint_with_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap() ||
|
||||
object_store->allocate_mint_without_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap();
|
||||
const bool shared_slow_path_call =
|
||||
SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
|
||||
const bool shared_slow_path_call = SlowPathSharingSupported(opt);
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
|
||||
LocationSummary* summary = new (zone) LocationSummary(
|
||||
@@ -4145,12 +4118,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
|
||||
: object_store->allocate_mint_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::AllocateMintSharedWithFPURegs()
|
||||
: StubCode::AllocateMintSharedWithoutFPURegs();
|
||||
|
||||
ASSERT(!locs()->live_registers()->ContainsRegister(
|
||||
AllocateMintABI::kResultReg));
|
||||
@@ -4201,12 +4172,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ TsanFuncEntry();
|
||||
}
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
|
||||
: object_store->allocate_mint_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::AllocateMintSharedWithFPURegs()
|
||||
: StubCode::AllocateMintSharedWithoutFPURegs();
|
||||
|
||||
ASSERT(!locs()->live_registers()->ContainsRegister(
|
||||
AllocateMintABI::kResultReg));
|
||||
|
||||
@@ -100,16 +100,14 @@ AliasIdentity::AliasIdentity(FlowGraphDeserializer* d)
|
||||
|
||||
void ArgumentsDescriptor::Write(FlowGraphSerializer* s) const {
|
||||
if (IsCached()) {
|
||||
// Simple argument descriptors are cached in the VM isolate.
|
||||
// Simple argument descriptors are cached.
|
||||
// Write them as arguments count and query cache during deserialization.
|
||||
ASSERT(NamedCount() == 0);
|
||||
ASSERT(Count() == Size());
|
||||
ASSERT(array_.InVMIsolateHeap());
|
||||
s->Write<intptr_t>(TypeArgsLen());
|
||||
s->Write<intptr_t>(Count());
|
||||
} else {
|
||||
ASSERT(array_.IsCanonical());
|
||||
ASSERT(!array_.InVMIsolateHeap());
|
||||
s->Write<intptr_t>(-1);
|
||||
s->Write<const Array&>(array_);
|
||||
}
|
||||
@@ -505,16 +503,6 @@ void FlowGraphSerializer::WriteTrait<const Code&>::Write(FlowGraphSerializer* s,
|
||||
return;
|
||||
}
|
||||
}
|
||||
intptr_t index = StubCode::NumEntries();
|
||||
ObjectStore* object_store = s->isolate_group()->object_store();
|
||||
#define MATCH(member, name) \
|
||||
if (object_store->member() == x.ptr()) { \
|
||||
s->Write<intptr_t>(index); \
|
||||
return; \
|
||||
} \
|
||||
++index;
|
||||
OBJECT_STORE_STUB_CODE_LIST(MATCH)
|
||||
#undef MATCH
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
@@ -525,15 +513,6 @@ const Code& FlowGraphDeserializer::ReadTrait<const Code&>::Read(
|
||||
if (stub_id < StubCode::NumEntries()) {
|
||||
return StubCode::EntryAt(stub_id);
|
||||
}
|
||||
intptr_t index = StubCode::NumEntries();
|
||||
ObjectStore* object_store = d->isolate_group()->object_store();
|
||||
#define MATCH(member, name) \
|
||||
if (index == stub_id) { \
|
||||
return Code::ZoneHandle(d->zone(), object_store->member()); \
|
||||
} \
|
||||
++index;
|
||||
OBJECT_STORE_STUB_CODE_LIST(MATCH)
|
||||
#undef MATCH
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
@@ -2722,10 +2722,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
}
|
||||
|
||||
__ Bind(&slow_path);
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_array_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_array_stub());
|
||||
compiler->GenerateStubCall(source(), allocate_array_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateArray(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
__ Bind(&done);
|
||||
@@ -2765,13 +2762,10 @@ class AllocateContextSlowPath
|
||||
instruction(), /*num_slow_path_args=*/0);
|
||||
ASSERT(slow_path_env != nullptr);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub = Code::ZoneHandle(
|
||||
compiler->zone(), object_store->allocate_context_stub());
|
||||
|
||||
__ LoadImmediate(
|
||||
R10, compiler::Immediate(instruction()->num_context_variables()));
|
||||
compiler->GenerateStubCall(instruction()->source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(instruction()->source(),
|
||||
StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs,
|
||||
instruction()->deopt_id(), slow_path_env);
|
||||
ASSERT(instruction()->locs()->out(0).reg() == RAX);
|
||||
@@ -2823,12 +2817,8 @@ void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->temp(0).reg() == R10);
|
||||
ASSERT(locs()->out(0).reg() == RAX);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& allocate_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->allocate_context_stub());
|
||||
|
||||
__ LoadImmediate(R10, compiler::Immediate(num_context_variables()));
|
||||
compiler->GenerateStubCall(source(), allocate_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::AllocateContext(),
|
||||
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
|
||||
env());
|
||||
}
|
||||
@@ -2848,10 +2838,7 @@ void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->in(0).reg() == R9);
|
||||
ASSERT(locs()->out(0).reg() == RAX);
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& clone_context_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->clone_context_stub());
|
||||
compiler->GenerateStubCall(source(), clone_context_stub,
|
||||
compiler->GenerateStubCall(source(), StubCode::CloneContext(),
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id(), env());
|
||||
}
|
||||
@@ -4018,19 +4005,7 @@ LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 1;
|
||||
const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
|
||||
// Shared slow path is used in BoxInt64Instr::EmitNativeCode in
|
||||
// precompiled mode and only after VM isolate stubs where
|
||||
// replaced with isolate-specific stubs.
|
||||
auto object_store = IsolateGroup::Current()->object_store();
|
||||
const bool stubs_in_vm_isolate =
|
||||
object_store->allocate_mint_with_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap() ||
|
||||
object_store->allocate_mint_without_fpu_regs_stub()
|
||||
->untag()
|
||||
->InVMIsolateHeap();
|
||||
const bool shared_slow_path_call =
|
||||
SlowPathSharingSupported(opt) && !stubs_in_vm_isolate;
|
||||
const bool shared_slow_path_call = SlowPathSharingSupported(opt);
|
||||
LocationSummary* summary = new (zone) LocationSummary(
|
||||
zone, kNumInputs, kNumTemps,
|
||||
ValueFitsSmi()
|
||||
@@ -4093,12 +4068,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ TsanFuncEntry();
|
||||
}
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
compiler->zone(),
|
||||
live_fpu_regs ? object_store->allocate_mint_with_fpu_regs_stub()
|
||||
: object_store->allocate_mint_without_fpu_regs_stub());
|
||||
const auto& stub = live_fpu_regs
|
||||
? StubCode::AllocateMintSharedWithFPURegs()
|
||||
: StubCode::AllocateMintSharedWithoutFPURegs();
|
||||
|
||||
ASSERT(!locs()->live_registers()->ContainsRegister(
|
||||
AllocateMintABI::kResultReg));
|
||||
|
||||
@@ -64,11 +64,6 @@ bool CHA::IsGuardedClass(intptr_t cid) const {
|
||||
bool CHA::HasSubclasses(const Class& cls) {
|
||||
ASSERT(!cls.IsNull());
|
||||
ASSERT(!IsInternalOnlyClassId(cls.id()));
|
||||
// Can't track dependencies for classes on the VM heap since those are
|
||||
// read-only.
|
||||
// TODO(fschneider): Enable tracking of CHA dependent code for VM heap
|
||||
// classes.
|
||||
if (cls.InVMIsolateHeap()) return true;
|
||||
|
||||
if (cls.IsObjectClass()) {
|
||||
// Class Object has subclasses, although we do not keep track of them.
|
||||
@@ -92,7 +87,6 @@ bool CHA::HasSubclasses(intptr_t cid) const {
|
||||
|
||||
bool CHA::ConcreteSubclasses(const Class& cls,
|
||||
GrowableArray<intptr_t>* class_ids) {
|
||||
if (cls.InVMIsolateHeap()) return false;
|
||||
if (cls.IsObjectClass()) return false;
|
||||
if (cls.has_dynamically_extendable_subtypes()) return false;
|
||||
|
||||
@@ -119,11 +113,6 @@ bool CHA::ConcreteSubclasses(const Class& cls,
|
||||
}
|
||||
|
||||
bool CHA::IsImplemented(const Class& cls) {
|
||||
// Can't track dependencies for classes on the VM heap since those are
|
||||
// read-only.
|
||||
// TODO(fschneider): Enable tracking of CHA dependent code for VM heap
|
||||
// classes.
|
||||
if (cls.InVMIsolateHeap()) return true;
|
||||
if (cls.has_dynamically_extendable_subtypes()) return true;
|
||||
|
||||
return cls.is_implemented();
|
||||
@@ -227,12 +216,6 @@ bool CHA::IsConsistentWithCurrentHierarchy() const {
|
||||
bool CHA::HasOverride(const Class& cls,
|
||||
const String& function_name,
|
||||
intptr_t* subclasses_count) {
|
||||
// Can't track dependencies for classes on the VM heap since those are
|
||||
// read-only.
|
||||
// TODO(fschneider): Enable tracking of CHA dependent code for VM heap
|
||||
// classes.
|
||||
if (cls.InVMIsolateHeap()) return true;
|
||||
|
||||
// Subclasses of Object are not tracked by CHA. Safely assume that overrides
|
||||
// exist.
|
||||
if (cls.IsObjectClass()) {
|
||||
|
||||
@@ -968,10 +968,8 @@ JoinEntryInstr* BaseFlowGraphBuilder::BuildThrowNoSuchMethod() {
|
||||
JoinEntryInstr* nsm = BuildJoinEntry();
|
||||
|
||||
Fragment failing(nsm);
|
||||
const Code& nsm_handler = Code::ZoneHandle(
|
||||
Z, IG->object_store()->call_closure_no_such_method_stub());
|
||||
failing += LoadArgDescriptor();
|
||||
failing += TailCall(nsm_handler);
|
||||
failing += TailCall(StubCode::CallClosureNoSuchMethod());
|
||||
|
||||
return nsm;
|
||||
}
|
||||
|
||||
@@ -1268,10 +1268,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
||||
break;
|
||||
}
|
||||
case MethodRecognizer::kSuspendState_resume: {
|
||||
const Code& resume_stub =
|
||||
Code::ZoneHandle(Z, IG->object_store()->resume_stub());
|
||||
body += NullConstant();
|
||||
body += TailCall(resume_stub);
|
||||
body += TailCall(StubCode::Resume());
|
||||
break;
|
||||
}
|
||||
case MethodRecognizer::kTypedList_GetInt8:
|
||||
|
||||
@@ -76,7 +76,7 @@ CodeRelocator::CodeRelocator(Thread* thread,
|
||||
target_(Object::Handle(thread->zone())),
|
||||
destination_(Code::Handle(thread->zone())) {}
|
||||
|
||||
void CodeRelocator::Relocate(bool is_vm_isolate) {
|
||||
void CodeRelocator::Relocate() {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
auto& current_caller = Code::Handle(zone);
|
||||
auto& call_targets = Array::Handle(zone);
|
||||
@@ -412,46 +412,10 @@ CodePtr CodeRelocator::GetTarget(const StaticCallsTableEntry& call) {
|
||||
if (target_.IsAbstractType()) {
|
||||
target_ = AbstractType::Cast(target_).type_test_stub();
|
||||
destination_ = Code::Cast(target_).ptr();
|
||||
|
||||
// The AssertAssignableInstr will emit pc-relative calls to the TTS iff
|
||||
// dst_type is instantiated. If we happened to not install an optimized
|
||||
// TTS but rather a default one, it will live in the vm-isolate (to
|
||||
// which we cannot make pc-relative calls).
|
||||
// Though we have "equivalent" isolate-specific stubs we can use as
|
||||
// targets instead.
|
||||
//
|
||||
// (We could make the AOT compiler install isolate-specific stubs
|
||||
// into the types directly, but that does not work for types which
|
||||
// live in the "vm-isolate" - such as `Type::dynamic_type()`).
|
||||
if (destination_.InVMIsolateHeap()) {
|
||||
auto object_store = thread_->isolate_group()->object_store();
|
||||
|
||||
if (destination_.ptr() == StubCode::DefaultTypeTest().ptr()) {
|
||||
destination_ = object_store->default_tts_stub();
|
||||
} else if (destination_.ptr() ==
|
||||
StubCode::DefaultNullableTypeTest().ptr()) {
|
||||
destination_ = object_store->default_nullable_tts_stub();
|
||||
} else if (destination_.ptr() == StubCode::TopTypeTypeTest().ptr()) {
|
||||
destination_ = object_store->top_type_tts_stub();
|
||||
} else if (destination_.ptr() == StubCode::UnreachableTypeTest().ptr()) {
|
||||
destination_ = object_store->unreachable_tts_stub();
|
||||
} else if (destination_.ptr() == StubCode::SlowTypeTest().ptr()) {
|
||||
destination_ = object_store->slow_tts_stub();
|
||||
} else if (destination_.ptr() ==
|
||||
StubCode::NullableTypeParameterTypeTest().ptr()) {
|
||||
destination_ = object_store->nullable_type_parameter_tts_stub();
|
||||
} else if (destination_.ptr() ==
|
||||
StubCode::TypeParameterTypeTest().ptr()) {
|
||||
destination_ = object_store->type_parameter_tts_stub();
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ASSERT(target_.IsCode());
|
||||
destination_ = Code::Cast(target_).ptr();
|
||||
}
|
||||
ASSERT(!destination_.InVMIsolateHeap());
|
||||
return destination_.ptr();
|
||||
}
|
||||
|
||||
|
||||
@@ -148,10 +148,9 @@ class CodeRelocator : public StackResource {
|
||||
// the ".text" segment.
|
||||
static void Relocate(Thread* thread,
|
||||
GrowableArray<CodePtr>* code_objects,
|
||||
GrowableArray<ImageWriterCommand>* commands,
|
||||
bool is_vm_isolate) {
|
||||
GrowableArray<ImageWriterCommand>* commands) {
|
||||
CodeRelocator relocator(thread, code_objects, commands);
|
||||
relocator.Relocate(is_vm_isolate);
|
||||
relocator.Relocate();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -159,7 +158,7 @@ class CodeRelocator : public StackResource {
|
||||
GrowableArray<CodePtr>* code_objects,
|
||||
GrowableArray<ImageWriterCommand>* commands);
|
||||
|
||||
void Relocate(bool is_vm_isolate);
|
||||
void Relocate();
|
||||
|
||||
void FindLargestInstruction();
|
||||
|
||||
|
||||
@@ -179,8 +179,7 @@ struct RelocatorTestHelper {
|
||||
}
|
||||
|
||||
GrowableArray<ImageWriterCommand> commands;
|
||||
CodeRelocator::Relocate(thread, &raw_codes, &commands,
|
||||
/*is_vm_isolate=*/false);
|
||||
CodeRelocator::Relocate(thread, &raw_codes, &commands);
|
||||
|
||||
uword expected_offset = 0;
|
||||
fun(commands, &expected_offset);
|
||||
|
||||
@@ -957,7 +957,7 @@ uword Code::EntryPointOf(const dart::Code& code) {
|
||||
}
|
||||
|
||||
bool CanEmbedAsRawPointerInGeneratedCode(const dart::Object& obj) {
|
||||
return obj.IsSmi() || obj.InVMIsolateHeap();
|
||||
return obj.IsSmi() || obj.IsNull() || obj.IsCode();
|
||||
}
|
||||
|
||||
word ToRawPointer(const dart::Object& a) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+71
-216
@@ -65,10 +65,8 @@ DEFINE_FLAG(bool,
|
||||
false,
|
||||
"Also check core snapshot matches on OS and arch");
|
||||
|
||||
Isolate* Dart::vm_isolate_ = nullptr;
|
||||
int64_t Dart::start_time_micros_ = 0;
|
||||
ThreadPool* Dart::thread_pool_ = nullptr;
|
||||
Snapshot::Kind Dart::vm_snapshot_kind_ = Snapshot::kInvalid;
|
||||
Dart_ThreadStartCallback Dart::thread_start_callback_ = nullptr;
|
||||
Dart_ThreadExitCallback Dart::thread_exit_callback_ = nullptr;
|
||||
Dart_FileOpenCallback Dart::file_open_callback_ = nullptr;
|
||||
@@ -298,30 +296,6 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
|
||||
return Utils::StrDup("Can only target one sanitizer at a time");
|
||||
}
|
||||
|
||||
if (vm_isolate_ != nullptr) {
|
||||
return Utils::StrDup("VM initialization is in an inconsistent state.");
|
||||
}
|
||||
|
||||
const Snapshot* snapshot = nullptr;
|
||||
if (params->vm_snapshot_data != nullptr) {
|
||||
snapshot = Snapshot::SetupFromBuffer(params->vm_snapshot_data);
|
||||
if (snapshot == nullptr) {
|
||||
return Utils::StrDup("Invalid vm isolate snapshot seen");
|
||||
}
|
||||
}
|
||||
|
||||
// We are initializing the VM. We will take the VM-global flags used
|
||||
// during snapshot generation time also at runtime (this avoids the need
|
||||
// for the embedder to pass the same flags used during snapshot generation
|
||||
// also to the runtime).
|
||||
if (snapshot != nullptr) {
|
||||
char* error =
|
||||
SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(snapshot);
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
FrameLayout::Init();
|
||||
|
||||
set_thread_start_callback(params->thread_start);
|
||||
@@ -364,149 +338,25 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
|
||||
StoreBuffer::Init();
|
||||
MarkingStack::Init();
|
||||
TargetCPUFeatures::Init();
|
||||
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
||||
// Dart VM requires at least SSE2.
|
||||
if (!TargetCPUFeatures::sse2_supported()) {
|
||||
return Utils::StrDup("SSE2 is required.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DART_INCLUDE_SIMULATOR)
|
||||
Simulator::Init();
|
||||
#endif
|
||||
// Create the VM isolate and finish the VM initialization.
|
||||
Object::InitVtables();
|
||||
OffsetsTable::Init();
|
||||
ASSERT(thread_pool_ == nullptr);
|
||||
thread_pool_ = new ThreadPool();
|
||||
{
|
||||
ASSERT(vm_isolate_ == nullptr);
|
||||
ASSERT(Flags::Initialized());
|
||||
const bool is_vm_isolate = true;
|
||||
|
||||
// Setup default flags for the VM isolate.
|
||||
Dart_IsolateFlags api_flags;
|
||||
Isolate::FlagsInitialize(&api_flags);
|
||||
api_flags.is_system_isolate = true;
|
||||
|
||||
// We make a fake [IsolateGroupSource] here, since the "vm-isolate" is not
|
||||
// really an isolate itself - it acts more as a container for VM-global
|
||||
// objects.
|
||||
std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
|
||||
kVmIsolateName, kVmIsolateName, params->vm_snapshot_data,
|
||||
params->vm_snapshot_instructions, nullptr, -1, api_flags));
|
||||
// ObjectStore should be created later, after null objects are initialized.
|
||||
auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr,
|
||||
/*object_store=*/nullptr, api_flags,
|
||||
/*is_vm_isolate*/ true);
|
||||
group->CreateHeap(/*is_vm_isolate=*/true,
|
||||
/*is_service_or_kernel_isolate=*/false);
|
||||
IsolateGroup::RegisterIsolateGroup(group);
|
||||
vm_isolate_ =
|
||||
Isolate::InitIsolate(kVmIsolateName, group, api_flags, is_vm_isolate);
|
||||
group->set_initial_spawn_successful();
|
||||
|
||||
// Verify assumptions about executing in the VM isolate.
|
||||
ASSERT(vm_isolate_ == Isolate::Current());
|
||||
ASSERT(vm_isolate_ == Thread::Current()->isolate());
|
||||
|
||||
Thread* T = Thread::Current();
|
||||
ASSERT(T != nullptr);
|
||||
StackZone zone(T);
|
||||
Object::InitNullAndBool(vm_isolate_->group());
|
||||
vm_isolate_->isolate_group_->set_object_store(new ObjectStore());
|
||||
vm_isolate_->isolate_object_store()->Init();
|
||||
vm_isolate_->finalizers_ = GrowableObjectArray::null();
|
||||
Object::Init(vm_isolate_->group());
|
||||
OffsetsTable::Init();
|
||||
ArgumentsDescriptor::Init();
|
||||
ICData::Init();
|
||||
if (params->vm_snapshot_data != nullptr) {
|
||||
#if defined(SUPPORT_TIMELINE)
|
||||
TimelineBeginEndScope tbes(Timeline::GetVMStream(), "ReadVMSnapshot");
|
||||
#endif
|
||||
ASSERT(snapshot != nullptr);
|
||||
vm_snapshot_kind_ = snapshot->kind();
|
||||
|
||||
if (Snapshot::IncludesCode(vm_snapshot_kind_)) {
|
||||
if (vm_snapshot_kind_ == Snapshot::kFullAOT) {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
return Utils::StrDup("JIT runtime cannot run a precompiled snapshot");
|
||||
#endif
|
||||
}
|
||||
if (params->vm_snapshot_instructions == nullptr) {
|
||||
return Utils::StrDup("Missing instructions snapshot");
|
||||
}
|
||||
} else if (Snapshot::IsFull(vm_snapshot_kind_)) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return Utils::StrDup(
|
||||
"Precompiled runtime requires a precompiled snapshot");
|
||||
#else
|
||||
StubCode::Init();
|
||||
Object::FinishInit(vm_isolate_->group());
|
||||
#endif
|
||||
} else {
|
||||
return Utils::StrDup("Invalid vm isolate snapshot seen");
|
||||
}
|
||||
FullSnapshotReader reader(snapshot, params->vm_snapshot_instructions, T);
|
||||
char* error = reader.ReadVMSnapshot();
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
}
|
||||
|
||||
Object::FinishInit(vm_isolate_->group());
|
||||
#if defined(SUPPORT_TIMELINE)
|
||||
if (tbes.enabled()) {
|
||||
tbes.SetNumArguments(2);
|
||||
tbes.FormatArgument(0, "snapshotSize", "%" Pd, snapshot->length());
|
||||
tbes.FormatArgument(
|
||||
1, "heapSize", "%" Pd,
|
||||
vm_isolate_group()->heap()->UsedInWords(Heap::kOld) * kWordSize);
|
||||
}
|
||||
#endif // !defined(PRODUCT)
|
||||
if (FLAG_trace_isolates) {
|
||||
OS::PrintErr("Size of vm isolate snapshot = %" Pd "\n",
|
||||
snapshot->length());
|
||||
vm_isolate_group()->heap()->PrintSizes();
|
||||
MegamorphicCacheTable::PrintSizes(T);
|
||||
intptr_t size;
|
||||
intptr_t capacity;
|
||||
Symbols::GetStats(vm_isolate_->group(), &size, &capacity);
|
||||
OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
|
||||
OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
|
||||
}
|
||||
} else {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return Utils::StrDup(
|
||||
"Precompiled runtime requires a precompiled snapshot");
|
||||
#else
|
||||
vm_snapshot_kind_ = Snapshot::kNone;
|
||||
StubCode::Init();
|
||||
Object::FinishInit(vm_isolate_->group());
|
||||
Symbols::Init(vm_isolate_->group());
|
||||
#endif
|
||||
}
|
||||
// We need to initialize the constants here for the vm isolate thread due to
|
||||
// bootstrapping issues.
|
||||
T->InitVMConstants();
|
||||
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
|
||||
// Dart VM requires at least SSE2.
|
||||
if (!TargetCPUFeatures::sse2_supported()) {
|
||||
return Utils::StrDup("SSE2 is required.");
|
||||
}
|
||||
#endif
|
||||
{
|
||||
#if defined(SUPPORT_TIMELINE)
|
||||
TimelineBeginEndScope tbes(Timeline::GetVMStream(), "FinalizeVMIsolate");
|
||||
#endif
|
||||
Object::FinalizeVMIsolate(vm_isolate_->group());
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
vm_isolate_group()->heap()->Verify("Dart::DartInit", kRequireMarked);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DART_INCLUDE_PROFILER)
|
||||
Profiler::Init();
|
||||
#endif
|
||||
|
||||
// Allocate the "persistent" scoped handles for the predefined API
|
||||
// values (such as Dart_True, Dart_False and Dart_Null).
|
||||
Api::InitHandles();
|
||||
|
||||
Thread::ExitIsolate(); // Unregister the VM isolate from this thread.
|
||||
Isolate::SetCreateGroupCallback(params->create_group);
|
||||
Isolate::SetInitializeCallback_(params->initialize_isolate);
|
||||
Isolate::SetShutdownCallback(params->shutdown_isolate);
|
||||
@@ -558,20 +408,6 @@ static void DumpAliveIsolates(intptr_t num_attempts,
|
||||
});
|
||||
}
|
||||
|
||||
static bool OnlyVmIsolateLeft() {
|
||||
intptr_t count = 0;
|
||||
bool found_vm_isolate = false;
|
||||
IsolateGroup::ForEach([&](IsolateGroup* group) {
|
||||
group->ForEachIsolate([&](Isolate* isolate) {
|
||||
count++;
|
||||
if (isolate == Dart::vm_isolate()) {
|
||||
found_vm_isolate = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
return count == 1 && found_vm_isolate;
|
||||
}
|
||||
|
||||
// This waits until only the VM, service and kernel isolates are in the list.
|
||||
void Dart::WaitForApplicationIsolateShutdown() {
|
||||
ASSERT(!Isolate::creation_enabled_);
|
||||
@@ -601,7 +437,7 @@ void Dart::WaitForIsolateShutdown() {
|
||||
ASSERT(!Isolate::creation_enabled_);
|
||||
MonitorLocker ml(Isolate::isolate_creation_monitor_);
|
||||
intptr_t num_attempts = 0;
|
||||
while (!IsolateGroup::HasOnlyVMIsolateGroup() ||
|
||||
while (IsolateGroup::HasIsolateGroups() ||
|
||||
(Isolate::pending_shutdowns_ != 0)) {
|
||||
Monitor::WaitResult retval = ml.Wait(1000);
|
||||
if (retval == Monitor::kTimedOut) {
|
||||
@@ -631,7 +467,7 @@ void Dart::WaitForIsolateShutdown() {
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(OnlyVmIsolateLeft());
|
||||
ASSERT(!IsolateGroup::HasIsolateGroups());
|
||||
}
|
||||
|
||||
char* Dart::Cleanup() {
|
||||
@@ -639,7 +475,6 @@ char* Dart::Cleanup() {
|
||||
if (!DartInitializationState::StartCleanup()) {
|
||||
return Utils::StrDup("VM already terminated.");
|
||||
}
|
||||
ASSERT(vm_isolate_ != nullptr);
|
||||
|
||||
if (FLAG_trace_shutdown) {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Starting shutdown\n",
|
||||
@@ -678,7 +513,7 @@ char* Dart::Cleanup() {
|
||||
}
|
||||
Isolate::KillAllIsolates(Isolate::kInternalKillMsg);
|
||||
|
||||
// Wait for all isolates, but the service and the vm isolate to shut down.
|
||||
// Wait for all isolates, but the service and the kernel isolate to shut down.
|
||||
// Only do that if there is a service isolate running.
|
||||
if (ServiceIsolate::IsRunning() || KernelIsolate::IsRunning()) {
|
||||
if (FLAG_trace_shutdown) {
|
||||
@@ -737,23 +572,6 @@ char* Dart::Cleanup() {
|
||||
Profiler::Cleanup();
|
||||
#endif // defined(DART_INCLUDE_PROFILER)
|
||||
|
||||
Api::Cleanup();
|
||||
|
||||
// Set the VM isolate as current isolate.
|
||||
if (FLAG_trace_shutdown) {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Cleaning up vm isolate\n",
|
||||
UptimeMillis());
|
||||
}
|
||||
|
||||
// If Dart_Cleanup() is called on a thread which hasn't invoked any Dart API
|
||||
// functions before, entering the "vm-isolate" will cause lazy creation of a
|
||||
// OSThread (which is attached to the current thread via TLS).
|
||||
//
|
||||
// If we run in PRODUCT mode this lazy creation of OSThread can happen here,
|
||||
// which is why disabling the OSThread creation has to come after entering the
|
||||
// "vm-isolate".
|
||||
Thread::EnterIsolate(vm_isolate_);
|
||||
|
||||
// Disable creation of any new OSThread structures which means no more new
|
||||
// threads can do an EnterIsolate. This must come after isolate shutdown
|
||||
// because new threads may need to be spawned to shutdown the isolates.
|
||||
@@ -766,21 +584,15 @@ char* Dart::Cleanup() {
|
||||
}
|
||||
OSThread::DisableOSThreadCreation();
|
||||
|
||||
ShutdownIsolate(Thread::Current());
|
||||
vm_isolate_ = nullptr;
|
||||
ASSERT(Isolate::IsolateListLength() == 0);
|
||||
Service::Cleanup();
|
||||
PortMap::Cleanup();
|
||||
IsolateGroup::Cleanup();
|
||||
ICData::Cleanup();
|
||||
ArgumentsDescriptor::Cleanup();
|
||||
OffsetsTable::Cleanup();
|
||||
TargetCPUFeatures::Cleanup();
|
||||
MarkingStack::Cleanup();
|
||||
StoreBuffer::Cleanup();
|
||||
Object::Cleanup();
|
||||
Page::Cleanup();
|
||||
StubCode::Cleanup();
|
||||
#if defined(SUPPORT_TIMELINE)
|
||||
if (FLAG_trace_shutdown) {
|
||||
OS::PrintErr("[+%" Pd64 "ms] SHUTDOWN: Shutting down timeline\n",
|
||||
@@ -848,7 +660,7 @@ Isolate* Dart::CreateIsolate(const char* name_prefix,
|
||||
|
||||
char* Dart::InitIsolateGroupFromSnapshot(Thread* T,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size) {
|
||||
auto IG = T->isolate_group();
|
||||
@@ -867,16 +679,19 @@ char* Dart::InitIsolateGroupFromSnapshot(Thread* T,
|
||||
if (snapshot == nullptr) {
|
||||
return Utils::StrDup("Invalid snapshot");
|
||||
}
|
||||
if (!IsSnapshotCompatible(vm_snapshot_kind_, snapshot->kind())) {
|
||||
return OS::SCreate(nullptr,
|
||||
"Incompatible snapshot kinds: vm '%s', isolate '%s'",
|
||||
Snapshot::KindToCString(vm_snapshot_kind_),
|
||||
Snapshot::KindToCString(snapshot->kind()));
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (snapshot->kind() != Snapshot::kFullAOT) {
|
||||
return Utils::StrDup("AOT runtime cannot run a JIT snapshot");
|
||||
}
|
||||
#else
|
||||
if (snapshot->kind() == Snapshot::kFullAOT) {
|
||||
return Utils::StrDup("JIT runtime cannot run an AOT snapshot");
|
||||
}
|
||||
#endif
|
||||
if (FLAG_trace_isolates) {
|
||||
OS::PrintErr("Size of isolate snapshot = %" Pd "\n", snapshot->length());
|
||||
}
|
||||
FullSnapshotReader reader(snapshot, snapshot_instructions, T);
|
||||
FullSnapshotReader reader(snapshot, snapshot_text, T);
|
||||
char* error = reader.ReadProgramSnapshot();
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
@@ -906,7 +721,7 @@ char* Dart::InitIsolateGroupFromSnapshot(Thread* T,
|
||||
MegamorphicCacheTable::PrintSizes(T);
|
||||
}
|
||||
} else {
|
||||
if ((vm_snapshot_kind_ != Snapshot::kNone) && kernel_buffer == nullptr) {
|
||||
if (kernel_buffer == nullptr) {
|
||||
return Utils::StrDup("Missing isolate snapshot");
|
||||
}
|
||||
}
|
||||
@@ -940,15 +755,56 @@ static void FinalizeBuiltinClasses(Thread* thread) {
|
||||
|
||||
char* Dart::InitializeIsolateGroup(Thread* T,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size) {
|
||||
char* error =
|
||||
InitIsolateGroupFromSnapshot(T, snapshot_data, snapshot_instructions,
|
||||
kernel_buffer, kernel_buffer_size);
|
||||
// TODO(bootstrap-only-in-gen-snapshot)
|
||||
bool skip_bootstrap = false;
|
||||
if (snapshot_data != nullptr && kernel_buffer == nullptr) {
|
||||
const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
|
||||
skip_bootstrap = snapshot->kind() == Snapshot::kFullAOT ||
|
||||
snapshot->kind() == Snapshot::kFullJIT;
|
||||
char* error =
|
||||
SnapshotHeaderReader::InitializeIsolateGroupFlagsFromSnapshot(snapshot);
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
StackZone zone(T);
|
||||
IsolateGroup* IG = T->isolate_group();
|
||||
Object::InitNullAndBool(IG);
|
||||
|
||||
// Fix fields that were initialized with Object::null() before it pointed to
|
||||
// the null objects and so currently have Smi 0.
|
||||
T->isolate()->FixInitiallyNullFields();
|
||||
T->FixInitiallyNullFields();
|
||||
|
||||
IG->set_object_store(new ObjectStore());
|
||||
if (!skip_bootstrap) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
#else
|
||||
Object::Init(IG);
|
||||
ArgumentsDescriptor::Init();
|
||||
ICData::Init();
|
||||
StubCode::Init();
|
||||
T->InitVMConstants();
|
||||
T->set_thread_locals(Array::empty_array());
|
||||
Symbols::Init(IG);
|
||||
Object::FinishInit(IG);
|
||||
Api::InitHandles();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
char* error = InitIsolateGroupFromSnapshot(T, snapshot_data, snapshot_text,
|
||||
kernel_buffer, kernel_buffer_size);
|
||||
if (error != nullptr) {
|
||||
return error;
|
||||
}
|
||||
T->isolate_group()->set_bootstrapping(false);
|
||||
|
||||
Object::VerifyBuiltinVtables();
|
||||
|
||||
@@ -1037,9 +893,7 @@ ErrorPtr Dart::InitializeIsolate(Thread* T,
|
||||
return Error::null();
|
||||
}
|
||||
|
||||
char* Dart::FeaturesString(IsolateGroup* isolate_group,
|
||||
bool is_vm_isolate,
|
||||
Snapshot::Kind kind) {
|
||||
char* Dart::FeaturesString(IsolateGroup* isolate_group, Snapshot::Kind kind) {
|
||||
TextBuffer buffer(64);
|
||||
|
||||
// Different fields are included for DEBUG/RELEASE/PRODUCT.
|
||||
@@ -1068,8 +922,6 @@ char* Dart::FeaturesString(IsolateGroup* isolate_group,
|
||||
} while (0);
|
||||
|
||||
if (Snapshot::IncludesCode(kind)) {
|
||||
VM_GLOBAL_FLAG_LIST(ADD_P, ADD_R, ADD_C, ADD_D);
|
||||
|
||||
ADD_FLAG(asan, FLAG_target_address_sanitizer)
|
||||
ADD_FLAG(msan, FLAG_target_memory_sanitizer)
|
||||
ADD_FLAG(tsan, FLAG_target_thread_sanitizer)
|
||||
@@ -1090,6 +942,9 @@ char* Dart::FeaturesString(IsolateGroup* isolate_group,
|
||||
FLAG_branch_coverage);
|
||||
ADD_ISOLATE_GROUP_FLAG(coverage, coverage, FLAG_coverage);
|
||||
}
|
||||
ADD_ISOLATE_GROUP_FLAG(code_comments, code_comments, FLAG_code_comments);
|
||||
ADD_ISOLATE_GROUP_FLAG(dwarf_stack_traces, dwarf_stack_traces,
|
||||
FLAG_dwarf_stack_traces_mode);
|
||||
}
|
||||
|
||||
if (Snapshot::IncludesCode(kind) || FLAG_check_core_snapshot_match) {
|
||||
|
||||
+7
-18
@@ -50,15 +50,14 @@ class Dart : public AllStatic {
|
||||
// caller must free.
|
||||
static char* InitializeIsolateGroup(Thread* T,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size);
|
||||
static char* InitIsolateGroupFromSnapshot(
|
||||
Thread* T,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size);
|
||||
static char* InitIsolateGroupFromSnapshot(Thread* T,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size);
|
||||
static ErrorPtr InitializeIsolate(Thread* T,
|
||||
bool is_first_isolate_in_group,
|
||||
void* isolate_data);
|
||||
@@ -66,11 +65,6 @@ class Dart : public AllStatic {
|
||||
static void RunShutdownCallback();
|
||||
static void ShutdownIsolate(Thread* T);
|
||||
|
||||
static Isolate* vm_isolate() { return vm_isolate_; }
|
||||
static IsolateGroup* vm_isolate_group() {
|
||||
if (vm_isolate_ == nullptr) return nullptr;
|
||||
return vm_isolate_->group();
|
||||
}
|
||||
static ThreadPool* thread_pool() { return thread_pool_; }
|
||||
|
||||
static int64_t UptimeMicros();
|
||||
@@ -79,10 +73,7 @@ class Dart : public AllStatic {
|
||||
}
|
||||
|
||||
// The returned string has to be free()ed.
|
||||
static char* FeaturesString(IsolateGroup* isolate_group,
|
||||
bool is_vm_snapshot,
|
||||
Snapshot::Kind kind);
|
||||
static Snapshot::Kind vm_snapshot_kind() { return vm_snapshot_kind_; }
|
||||
static char* FeaturesString(IsolateGroup* isolate_group, Snapshot::Kind kind);
|
||||
|
||||
static Dart_ThreadStartCallback thread_start_callback() {
|
||||
return thread_start_callback_;
|
||||
@@ -144,10 +135,8 @@ class Dart : public AllStatic {
|
||||
static void WaitForIsolateShutdown();
|
||||
static void WaitForApplicationIsolateShutdown();
|
||||
|
||||
static Isolate* vm_isolate_;
|
||||
static int64_t start_time_micros_;
|
||||
static ThreadPool* thread_pool_;
|
||||
static Snapshot::Kind vm_snapshot_kind_;
|
||||
static Dart_ThreadStartCallback thread_start_callback_;
|
||||
static Dart_ThreadExitCallback thread_exit_callback_;
|
||||
static Dart_FileOpenCallback file_open_callback_;
|
||||
|
||||
+40
-70
@@ -506,7 +506,6 @@ ApiLocalScope* Api::TopScope(Thread* thread) {
|
||||
void Api::InitHandles() {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
ASSERT(isolate != nullptr);
|
||||
ASSERT(isolate == Dart::vm_isolate());
|
||||
ApiState* state = isolate->group()->api_state();
|
||||
ASSERT(state != nullptr);
|
||||
|
||||
@@ -520,8 +519,6 @@ void Api::InitHandles() {
|
||||
Object::unwind_in_progress_error().ptr());
|
||||
}
|
||||
|
||||
void Api::Cleanup() {}
|
||||
|
||||
bool Api::StringGetPeerHelper(NativeArguments* arguments,
|
||||
int arg_index,
|
||||
void** peer) {
|
||||
@@ -1223,7 +1220,7 @@ static Dart_Isolate CreateIsolate(IsolateGroup* group,
|
||||
char* error_str = nullptr;
|
||||
if (is_new_group) {
|
||||
error_str = Dart::InitializeIsolateGroup(
|
||||
T, source->snapshot_data, source->snapshot_instructions,
|
||||
T, source->snapshot_data, source->snapshot_text,
|
||||
source->kernel_buffer, source->kernel_buffer_size);
|
||||
}
|
||||
if (error_str == nullptr) {
|
||||
@@ -1308,11 +1305,8 @@ Dart_CreateIsolateGroup(const char* script_uri,
|
||||
std::unique_ptr<IsolateGroupSource> source(
|
||||
new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
|
||||
snapshot_instructions, nullptr, -1, *flags));
|
||||
auto group = new IsolateGroup(std::move(source), isolate_group_data, *flags,
|
||||
/*is_vm_isolate=*/false);
|
||||
group->CreateHeap(
|
||||
/*is_vm_isolate=*/false,
|
||||
flags->is_service_isolate || flags->is_kernel_isolate);
|
||||
auto group = new IsolateGroup(std::move(source), isolate_group_data, *flags);
|
||||
group->CreateHeap(flags->is_service_isolate || flags->is_kernel_isolate);
|
||||
IsolateGroup::RegisterIsolateGroup(group);
|
||||
Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
|
||||
non_null_name, isolate_data, error);
|
||||
@@ -1343,12 +1337,9 @@ Dart_CreateIsolateGroupFromKernel(const char* script_uri,
|
||||
std::shared_ptr<IsolateGroupSource> source(
|
||||
new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
|
||||
kernel_buffer, kernel_buffer_size, *flags));
|
||||
auto group = new IsolateGroup(source, isolate_group_data, *flags,
|
||||
/*is_vm_isolate=*/false);
|
||||
auto group = new IsolateGroup(source, isolate_group_data, *flags);
|
||||
IsolateGroup::RegisterIsolateGroup(group);
|
||||
group->CreateHeap(
|
||||
/*is_vm_isolate=*/false,
|
||||
flags->is_service_isolate || flags->is_kernel_isolate);
|
||||
group->CreateHeap(flags->is_service_isolate || flags->is_kernel_isolate);
|
||||
Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
|
||||
non_null_name, isolate_data, error);
|
||||
if (isolate != nullptr) {
|
||||
@@ -1840,22 +1831,15 @@ DART_EXPORT void Dart_ExitIsolate() {
|
||||
Thread::ExitIsolate();
|
||||
}
|
||||
|
||||
DART_EXPORT Dart_Handle
|
||||
Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
|
||||
intptr_t* vm_snapshot_data_size,
|
||||
uint8_t** isolate_snapshot_data_buffer,
|
||||
intptr_t* isolate_snapshot_data_size,
|
||||
bool is_core) {
|
||||
DART_EXPORT Dart_Handle Dart_CreateSnapshot(uint8_t** snapshot_data_buffer,
|
||||
intptr_t* snapshot_data_size) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return Api::NewError("Cannot create snapshots on an AOT runtime.");
|
||||
#else
|
||||
DARTSCOPE(Thread::Current());
|
||||
API_TIMELINE_DURATION(T);
|
||||
if (vm_snapshot_data_buffer != nullptr) {
|
||||
CHECK_NULL(vm_snapshot_data_size);
|
||||
}
|
||||
CHECK_NULL(isolate_snapshot_data_buffer);
|
||||
CHECK_NULL(isolate_snapshot_data_size);
|
||||
CHECK_NULL(snapshot_data_buffer);
|
||||
CHECK_NULL(snapshot_data_size);
|
||||
// Finalize all classes if needed.
|
||||
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
|
||||
if (Api::IsError(state)) {
|
||||
@@ -1872,22 +1856,14 @@ Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
|
||||
}
|
||||
#endif // #if defined(DEBUG)
|
||||
|
||||
ZoneWriteStream vm_snapshot_data(Api::TopScope(T)->zone(),
|
||||
FullSnapshotWriter::kInitialSize);
|
||||
ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
|
||||
FullSnapshotWriter::kInitialSize);
|
||||
const Snapshot::Kind snapshot_kind =
|
||||
is_core ? Snapshot::kFullCore : Snapshot::kFull;
|
||||
FullSnapshotWriter writer(
|
||||
snapshot_kind, &vm_snapshot_data, &isolate_snapshot_data,
|
||||
nullptr /* vm_image_writer */, nullptr /* isolate_image_writer */);
|
||||
const Snapshot::Kind snapshot_kind = Snapshot::kFull;
|
||||
FullSnapshotWriter writer(snapshot_kind, &isolate_snapshot_data,
|
||||
nullptr /* image_writer */);
|
||||
writer.WriteFullSnapshot();
|
||||
if (vm_snapshot_data_buffer != nullptr) {
|
||||
*vm_snapshot_data_buffer = vm_snapshot_data.buffer();
|
||||
*vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
|
||||
}
|
||||
*isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
|
||||
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
|
||||
*snapshot_data_buffer = isolate_snapshot_data.buffer();
|
||||
*snapshot_data_size = isolate_snapshot_data.bytes_written();
|
||||
return Api::Success();
|
||||
#endif
|
||||
}
|
||||
@@ -4380,9 +4356,8 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
|
||||
if (FLAG_verify_entry_points) {
|
||||
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
if (!cls.is_allocated() &&
|
||||
(Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
|
||||
#if defined(DEBUG) && defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (!cls.is_allocated()) {
|
||||
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
|
||||
}
|
||||
#endif
|
||||
@@ -4514,8 +4489,8 @@ DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
|
||||
if (FLAG_verify_entry_points) {
|
||||
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
|
||||
#if defined(DEBUG) && defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (!cls.is_allocated()) {
|
||||
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
|
||||
}
|
||||
#endif
|
||||
@@ -4546,8 +4521,8 @@ Dart_AllocateWithNativeFields(Dart_Handle type,
|
||||
if (FLAG_verify_entry_points) {
|
||||
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
|
||||
#if defined(DEBUG) && defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (!cls.is_allocated()) {
|
||||
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
|
||||
}
|
||||
#endif
|
||||
@@ -6109,13 +6084,6 @@ static Dart_Handle DeferredLoadComplete(intptr_t loading_unit_id,
|
||||
if (snapshot == nullptr) {
|
||||
return Api::NewError("Invalid snapshot");
|
||||
}
|
||||
if (!IsSnapshotCompatible(Dart::vm_snapshot_kind(), snapshot->kind())) {
|
||||
const String& message = String::Handle(String::NewFormatted(
|
||||
"Incompatible snapshot kinds: vm '%s', isolate '%s'",
|
||||
Snapshot::KindToCString(Dart::vm_snapshot_kind()),
|
||||
Snapshot::KindToCString(snapshot->kind())));
|
||||
return Api::NewHandle(T, ApiError::New(message));
|
||||
}
|
||||
|
||||
FullSnapshotReader reader(snapshot, snapshot_instructions, T);
|
||||
char* error = reader.ReadUnitSnapshot(unit);
|
||||
@@ -6726,8 +6694,7 @@ static void CreateAppAOTSnapshotHelper(
|
||||
object_callback_data != nullptr ? &object_stream_value : nullptr;
|
||||
|
||||
auto const use_output_writer = [&](ImageWriter* image_writer) {
|
||||
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data,
|
||||
&isolate_snapshot_data, image_writer,
|
||||
FullSnapshotWriter writer(Snapshot::kFullAOT, &isolate_snapshot_data,
|
||||
image_writer);
|
||||
|
||||
if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
|
||||
@@ -6911,20 +6878,23 @@ Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
|
||||
return Api::NewError(
|
||||
"This VM was built without support for AOT compilation.");
|
||||
#else
|
||||
DARTSCOPE(Thread::Current());
|
||||
API_TIMELINE_DURATION(T);
|
||||
CHECK_NULL(callback);
|
||||
|
||||
TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
|
||||
StreamingWriteStream assembly_stream(kAssemblyInitialSize, callback,
|
||||
callback_data);
|
||||
AssemblyImageWriter image_writer(T, &assembly_stream);
|
||||
ZoneWriteStream vm_snapshot_data(T->zone(), FullSnapshotWriter::kInitialSize);
|
||||
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data, nullptr,
|
||||
&image_writer, nullptr);
|
||||
|
||||
writer.WriteFullSnapshot();
|
||||
|
||||
const char assembly[] =
|
||||
".text\n"
|
||||
".globl _kDartVmSnapshotInstructions\n"
|
||||
".balign 64, 0\n"
|
||||
"_kDartVmSnapshotInstructions:\n"
|
||||
".quad 0\n"
|
||||
".size _kDartVmSnapshotInstructions, .-_kDartVmSnapshotInstructions\n"
|
||||
".type _kDartVmSnapshotInstructions, %object\n"
|
||||
".section .rodata\n"
|
||||
".globl _kDartVmSnapshotData\n"
|
||||
".balign 64, 0\n"
|
||||
"_kDartVmSnapshotData:\n"
|
||||
".quad 0\n"
|
||||
".size _kDartVmSnapshotData, .-_kDartVmSnapshotData\n"
|
||||
".type _kDartVmSnapshotData, %object\n";
|
||||
callback(callback_data, reinterpret_cast<const uint8_t*>(assembly),
|
||||
sizeof(assembly));
|
||||
return Api::Success();
|
||||
#endif
|
||||
}
|
||||
@@ -7152,8 +7122,8 @@ Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
|
||||
Api::TopScope(T)->zone(), FullSnapshotWriter::kInitialSize);
|
||||
BlobImageWriter image_writer(T, /*vm_instructions=*/nullptr,
|
||||
&isolate_snapshot_instructions);
|
||||
FullSnapshotWriter writer(Snapshot::kFullJIT, nullptr, &isolate_snapshot_data,
|
||||
nullptr, &image_writer);
|
||||
FullSnapshotWriter writer(Snapshot::kFullJIT, &isolate_snapshot_data,
|
||||
&image_writer);
|
||||
writer.WriteFullSnapshot();
|
||||
|
||||
*isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
|
||||
|
||||
@@ -38,7 +38,6 @@ UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create_group = TesterState::create_callback;
|
||||
params.shutdown_isolate = TesterState::shutdown_callback;
|
||||
params.cleanup_group = TesterState::group_cleanup_callback;
|
||||
@@ -64,42 +63,10 @@ UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
|
||||
EXPECT(Dart_Cleanup() == nullptr);
|
||||
}
|
||||
|
||||
UNIT_TEST_CASE(DartAPI_DartInitializeCallsCodeObserver) {
|
||||
EXPECT(Dart_SetVMFlags(TesterState::argc, TesterState::argv) == nullptr);
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create_group = TesterState::create_callback;
|
||||
params.shutdown_isolate = TesterState::shutdown_callback;
|
||||
params.cleanup_group = TesterState::group_cleanup_callback;
|
||||
params.start_kernel_isolate = true;
|
||||
|
||||
bool was_called = false;
|
||||
Dart_CodeObserver code_observer;
|
||||
code_observer.data = &was_called;
|
||||
code_observer.on_new_code = [](Dart_CodeObserver* observer, const char* name,
|
||||
uintptr_t base, uintptr_t size) {
|
||||
*static_cast<bool*>(observer->data) = true;
|
||||
};
|
||||
params.code_observer = &code_observer;
|
||||
|
||||
// Reinitialize and ensure we can execute Dart code.
|
||||
EXPECT(Dart_Initialize(¶ms) == nullptr);
|
||||
|
||||
// Wait for 5 seconds to let the kernel service load the snapshot,
|
||||
// which should trigger calls to the code observer.
|
||||
OS::Sleep(5);
|
||||
|
||||
EXPECT(was_called);
|
||||
EXPECT(Dart_Cleanup() == nullptr);
|
||||
}
|
||||
|
||||
UNIT_TEST_CASE(DartAPI_DartInitializeHeapSizes) {
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create_group = TesterState::create_callback;
|
||||
params.shutdown_isolate = TesterState::shutdown_callback;
|
||||
params.cleanup_group = TesterState::group_cleanup_callback;
|
||||
@@ -166,7 +133,6 @@ UNIT_TEST_CASE(DartAPI_DartCleanupWaitsForGroupCleanupCallbacks) {
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create_group = CreateCallback;
|
||||
params.shutdown_isolate = TesterState::shutdown_callback;
|
||||
params.cleanup_group = CleanupCallback;
|
||||
@@ -10835,7 +10801,6 @@ UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
|
||||
Dart_InitializeParams params;
|
||||
memset(¶ms, 0, sizeof(Dart_InitializeParams));
|
||||
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
||||
params.vm_snapshot_data = TesterState::vm_snapshot_data;
|
||||
params.create_group = TesterState::create_callback;
|
||||
params.shutdown_isolate = TesterState::shutdown_callback;
|
||||
params.cleanup_group = TesterState::group_cleanup_callback;
|
||||
|
||||
@@ -631,8 +631,6 @@ void ArgumentsDescriptor::Init() {
|
||||
ASSERT(cache_index == kCachedDescriptorCount);
|
||||
}
|
||||
|
||||
void ArgumentsDescriptor::Cleanup() {}
|
||||
|
||||
ObjectPtr DartLibraryCalls::InstanceCreate(const Library& lib,
|
||||
const String& class_name,
|
||||
const String& constructor_name,
|
||||
|
||||
+27
-16
@@ -863,11 +863,11 @@ class BitsContainer : public ElfSection {
|
||||
|
||||
// Returns the hash for the portion corresponding to symbol_name.
|
||||
// Returns 0 if the portion has no bytes or no portions have that name.
|
||||
uint32_t Hash(const char* symbol_name) const {
|
||||
uint64_t Hash(const char* symbol_name) const {
|
||||
for (const auto& portion : portions_) {
|
||||
if (strcmp(symbol_name, portion.symbol_name) == 0) {
|
||||
if (portion.bytes == nullptr) return 0;
|
||||
const uint32_t hash = Utils::StringHash(portion.bytes, portion.size);
|
||||
const uint64_t hash = Utils::StringHash64(portion.bytes, portion.size);
|
||||
// Ensure a non-zero return.
|
||||
return hash == 0 ? 1 : hash;
|
||||
}
|
||||
@@ -1162,14 +1162,9 @@ void ElfWriter::CreateBSS() {
|
||||
const char* symbol_name;
|
||||
intptr_t label;
|
||||
// First determine whether this is the VM's text portion or the isolate's.
|
||||
if (strcmp(portion.symbol_name, kVmSnapshotInstructionsAsmSymbol) == 0) {
|
||||
size = BSS::kVmEntryCount * compiler::target::kWordSize;
|
||||
symbol_name = kVmSnapshotBssAsmSymbol;
|
||||
label = kVmBssLabel;
|
||||
} else if (strcmp(portion.symbol_name,
|
||||
kIsolateSnapshotInstructionsAsmSymbol) == 0) {
|
||||
if (strcmp(portion.symbol_name, kSnapshotTextAsmSymbol) == 0) {
|
||||
size = BSS::kIsolateGroupEntryCount * compiler::target::kWordSize;
|
||||
symbol_name = kIsolateSnapshotBssAsmSymbol;
|
||||
symbol_name = kSnapshotBssAsmSymbol;
|
||||
label = kIsolateBssLabel;
|
||||
} else {
|
||||
// Not VM or isolate text.
|
||||
@@ -1225,6 +1220,24 @@ void ElfSymbolTable::Initialize(const GrowableArray<ElfSection*>& sections) {
|
||||
// dynamic symbols there also. (see dartbug.com/41783).
|
||||
AddSymbol(portion.symbol_name, binding, type, portion.size,
|
||||
section->index, portion.offset, portion.label);
|
||||
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (strcmp(portion.symbol_name, "_kDartSnapshotText") == 0) {
|
||||
AddSymbol("_kDartVmSnapshotInstructions", binding, type,
|
||||
portion.size, section->index, portion.offset,
|
||||
portion.label);
|
||||
AddSymbol("_kDartIsolateSnapshotInstructions", binding, type,
|
||||
portion.size, section->index, portion.offset,
|
||||
portion.label);
|
||||
}
|
||||
if (strcmp(portion.symbol_name, "_kDartSnapshotData") == 0) {
|
||||
AddSymbol("_kDartVmSnapshotData", binding, type, portion.size,
|
||||
section->index, portion.offset, portion.label);
|
||||
AddSymbol("_kDartIsolateSnapshotData", binding, type, portion.size,
|
||||
section->index, portion.offset, portion.label);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!dynamic_ && portion.symbols != nullptr) {
|
||||
for (const auto& symbol_data : *portion.symbols) {
|
||||
@@ -1711,15 +1724,13 @@ void ElfWriter::AssertConsistency(const ElfWriter* snapshot,
|
||||
FATAL("Mismatch between snapshot and debug info ELF was detected");
|
||||
}
|
||||
|
||||
// For the build ID, we generate a 128-bit hash, where each 32 bits is a hash of
|
||||
// For the build ID, we generate a 128-bit hash, where each 64 bits is a hash of
|
||||
// the contents of the following segments in order:
|
||||
//
|
||||
// .text(VM) | .text(Isolate) | .rodata(VM) | .rodata(Isolate)
|
||||
// .text(Isolate) | .rodata(Isolate)
|
||||
static constexpr const char* kBuildIdSegmentNames[]{
|
||||
kVmSnapshotInstructionsAsmSymbol,
|
||||
kIsolateSnapshotInstructionsAsmSymbol,
|
||||
kVmSnapshotDataAsmSymbol,
|
||||
kIsolateSnapshotDataAsmSymbol,
|
||||
kSnapshotTextAsmSymbol,
|
||||
kSnapshotDataAsmSymbol,
|
||||
};
|
||||
static constexpr intptr_t kBuildIdSegmentNamesLength =
|
||||
ARRAY_SIZE(kBuildIdSegmentNames);
|
||||
@@ -1730,7 +1741,7 @@ static constexpr intptr_t kBuildIdHeaderSize =
|
||||
void ElfWriter::GenerateBuildId() {
|
||||
// Not idempotent.
|
||||
ASSERT(section_table_->Find(kBuildIdNoteName) == nullptr);
|
||||
uint32_t hashes[kBuildIdSegmentNamesLength];
|
||||
uint64_t hashes[kBuildIdSegmentNamesLength];
|
||||
// Currently, we construct the build ID out of data from two different
|
||||
// sections: the .text section and the .rodata section.
|
||||
//
|
||||
|
||||
@@ -534,7 +534,7 @@ class IntKeyRawPointerValueTrait {
|
||||
|
||||
static Key KeyOf(Pair kv) { return kv.key; }
|
||||
static Value ValueOf(Pair kv) { return kv.value; }
|
||||
static uword Hash(Key key) { return key; }
|
||||
static uword Hash(Key key) { return FinalizeHash(key); }
|
||||
static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
|
||||
};
|
||||
|
||||
|
||||
@@ -31,10 +31,6 @@ struct ArrayStorageTraits {
|
||||
return Array::New(length, space);
|
||||
}
|
||||
|
||||
static bool IsImmutable(const ArrayHandle& handle) {
|
||||
return handle.ptr()->untag()->InVMIsolateHeap();
|
||||
}
|
||||
|
||||
static ObjectPtr At(ArrayHandle* array, intptr_t index) {
|
||||
return array->At(index);
|
||||
}
|
||||
@@ -65,10 +61,6 @@ struct WeakArrayStorageTraits {
|
||||
return WeakArray::New(length, space);
|
||||
}
|
||||
|
||||
static bool IsImmutable(const ArrayHandle& handle) {
|
||||
return handle.ptr()->untag()->InVMIsolateHeap();
|
||||
}
|
||||
|
||||
static ObjectPtr At(ArrayHandle* array, intptr_t index) {
|
||||
return array->At(index);
|
||||
}
|
||||
@@ -401,9 +393,6 @@ class HashTable : public HashTableBase {
|
||||
}
|
||||
void UpdateCollisions(intptr_t collisions) const {
|
||||
if (KeyTraits::ReportStats()) {
|
||||
if (Storage::IsImmutable(*data_)) {
|
||||
return;
|
||||
}
|
||||
AdjustSmiValueAt(kNumProbesIndex, collisions + 1);
|
||||
if (collisions < 5) {
|
||||
AdjustSmiValueAt(kNumLT5LookupsIndex, 1);
|
||||
|
||||
@@ -312,9 +312,6 @@ void Become::Forward() {
|
||||
if (after->IsImmediateObject()) {
|
||||
InvalidForwarding(before, after, "Cannot target immediates");
|
||||
}
|
||||
if (before->untag()->InVMIsolateHeap()) {
|
||||
InvalidForwarding(before, after, "Cannot forward VM heap objects");
|
||||
}
|
||||
if (before->IsForwardingCorpse() && !IsDummyObject(before)) {
|
||||
InvalidForwarding(before, after, "Cannot forward to multiple targets");
|
||||
}
|
||||
|
||||
@@ -610,15 +610,7 @@ void CompactorTask::PlanMoveToContiguousSize(intptr_t size) {
|
||||
void GCCompactor::SetupImagePageBoundaries() {
|
||||
MallocGrowableArray<ImagePageRange> ranges(4);
|
||||
|
||||
Page* image_page =
|
||||
Dart::vm_isolate_group()->heap()->old_space()->image_pages_;
|
||||
while (image_page != nullptr) {
|
||||
ImagePageRange range = {image_page->object_start(),
|
||||
image_page->object_end()};
|
||||
ranges.Add(range);
|
||||
image_page = image_page->next();
|
||||
}
|
||||
image_page = heap_->old_space()->image_pages_;
|
||||
Page* image_page = heap_->old_space()->image_pages_;
|
||||
while (image_page != nullptr) {
|
||||
ImagePageRange range = {image_page->object_start(),
|
||||
image_page->object_end()};
|
||||
@@ -658,7 +650,7 @@ void GCCompactor::ForwardPointer(ObjectPtr* ptr) {
|
||||
Page* page = Page::Of(old_target);
|
||||
ForwardingPage* forwarding_page = page->forwarding_page();
|
||||
if (forwarding_page == nullptr) {
|
||||
return; // Not moved (VM isolate, large page, code page).
|
||||
return; // Not moved (large page or code page).
|
||||
}
|
||||
if (page->is_never_evacuate()) {
|
||||
// Forwarding page is non-NULL since one is still reserved for use as a
|
||||
@@ -699,7 +691,7 @@ void GCCompactor::ForwardCompressedPointer(uword heap_base,
|
||||
Page* page = Page::Of(old_target);
|
||||
ForwardingPage* forwarding_page = page->forwarding_page();
|
||||
if (forwarding_page == nullptr) {
|
||||
return; // Not moved (VM isolate, large page, code page).
|
||||
return; // Not moved (large page or code page).
|
||||
}
|
||||
if (page->is_never_evacuate()) {
|
||||
// Forwarding page is non-NULL since one is still reserved for use as a
|
||||
|
||||
+8
-47
@@ -36,7 +36,6 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, write_protect_vm_isolate, true, "Write protect vm_isolate.");
|
||||
DEFINE_FLAG(bool,
|
||||
disable_heap_verification,
|
||||
false,
|
||||
@@ -50,11 +49,9 @@ DEFINE_FLAG(charp,
|
||||
#endif
|
||||
|
||||
Heap::Heap(IsolateGroup* isolate_group,
|
||||
bool is_vm_isolate,
|
||||
intptr_t max_new_gen_semi_words,
|
||||
intptr_t max_old_gen_words)
|
||||
: isolate_group_(isolate_group),
|
||||
is_vm_isolate_(is_vm_isolate),
|
||||
new_space_(this, max_new_gen_semi_words),
|
||||
old_space_(this, max_old_gen_words),
|
||||
read_only_(false),
|
||||
@@ -372,10 +369,6 @@ void HeapIterationScope::IterateOldObjectsNoImagePages(
|
||||
old_space_->VisitObjectsNoImagePages(visitor);
|
||||
}
|
||||
|
||||
void HeapIterationScope::IterateVMIsolateObjects(ObjectVisitor* visitor) const {
|
||||
Dart::vm_isolate_group()->heap()->VisitObjects(visitor);
|
||||
}
|
||||
|
||||
void HeapIterationScope::IterateObjectPointers(
|
||||
ObjectPointerVisitor* visitor,
|
||||
ValidationPolicy validate_frames) {
|
||||
@@ -475,13 +468,6 @@ void Heap::CollectNewSpaceGarbage(Thread* thread,
|
||||
NoActiveIsolateScope no_active_isolate_scope(thread);
|
||||
ASSERT(reason != GCReason::kPromotion);
|
||||
ASSERT(reason != GCReason::kFinalize);
|
||||
if (thread->isolate_group() == Dart::vm_isolate_group()) {
|
||||
// The vm isolate cannot safely collect garbage due to unvisited read-only
|
||||
// handles and slots bootstrapped with RAW_NULL. Ignore GC requests to
|
||||
// trigger a nice out-of-memory message instead of a crash in the middle of
|
||||
// visiting pointers.
|
||||
return;
|
||||
}
|
||||
{
|
||||
GcSafepointOperationScope safepoint_operation(thread);
|
||||
RecordBeforeGC(type, reason);
|
||||
@@ -524,16 +510,15 @@ void Heap::CollectOldSpaceGarbage(Thread* thread,
|
||||
ASSERT(type != GCType::kScavenge);
|
||||
ASSERT(reason != GCReason::kNewSpace);
|
||||
ASSERT(reason != GCReason::kStoreBuffer);
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
if (type == GCType::kMarkCompact) {
|
||||
type = GCType::kMarkSweep;
|
||||
}
|
||||
#else
|
||||
if (FLAG_use_compactor) {
|
||||
type = GCType::kMarkCompact;
|
||||
}
|
||||
if (thread->isolate_group() == Dart::vm_isolate_group()) {
|
||||
// The vm isolate cannot safely collect garbage due to unvisited read-only
|
||||
// handles and slots bootstrapped with RAW_NULL. Ignore GC requests to
|
||||
// trigger a nice out-of-memory message instead of a crash in the middle of
|
||||
// visiting pointers.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
GcSafepointOperationScope safepoint_operation(thread);
|
||||
if (reason == GCReason::kFinalize) {
|
||||
@@ -705,12 +690,11 @@ void Heap::WriteProtect(bool read_only) {
|
||||
}
|
||||
|
||||
void Heap::Init(IsolateGroup* isolate_group,
|
||||
bool is_vm_isolate,
|
||||
intptr_t max_new_gen_words,
|
||||
intptr_t max_old_gen_words) {
|
||||
ASSERT(isolate_group->heap() == nullptr);
|
||||
std::unique_ptr<Heap> heap(new Heap(isolate_group, is_vm_isolate,
|
||||
max_new_gen_words, max_old_gen_words));
|
||||
std::unique_ptr<Heap> heap(
|
||||
new Heap(isolate_group, max_new_gen_words, max_old_gen_words));
|
||||
isolate_group->set_heap(std::move(heap));
|
||||
}
|
||||
|
||||
@@ -748,8 +732,6 @@ ObjectSet* Heap::CreateAllocatedObjectSet(Zone* zone,
|
||||
ObjectSet* allocated_set = new (zone) ObjectSet(zone);
|
||||
|
||||
this->AddRegionsToObjectSet(allocated_set);
|
||||
Isolate* vm_isolate = Dart::vm_isolate();
|
||||
vm_isolate->group()->heap()->AddRegionsToObjectSet(allocated_set);
|
||||
|
||||
{
|
||||
VerifyObjectVisitor object_visitor(isolate_group(), allocated_set,
|
||||
@@ -761,13 +743,6 @@ ObjectSet* Heap::CreateAllocatedObjectSet(Zone* zone,
|
||||
kRequireMarked);
|
||||
this->VisitObjectsImagePages(&object_visitor);
|
||||
}
|
||||
{
|
||||
// VM isolate heap is premarked.
|
||||
VerifyObjectVisitor vm_object_visitor(isolate_group(), allocated_set,
|
||||
kRequireMarked);
|
||||
vm_isolate->group()->heap()->VisitObjects(&vm_object_visitor);
|
||||
}
|
||||
|
||||
return allocated_set;
|
||||
}
|
||||
|
||||
@@ -1174,20 +1149,6 @@ ForceGrowthScope::~ForceGrowthScope() {
|
||||
thread()->DecrementForceGrowthScopeDepth();
|
||||
}
|
||||
|
||||
WritableVMIsolateScope::WritableVMIsolateScope(Thread* thread)
|
||||
: ThreadStackResource(thread) {
|
||||
if (FLAG_write_protect_vm_isolate) {
|
||||
Dart::vm_isolate_group()->heap()->WriteProtect(false);
|
||||
}
|
||||
}
|
||||
|
||||
WritableVMIsolateScope::~WritableVMIsolateScope() {
|
||||
ASSERT(Dart::vm_isolate_group()->heap()->UsedInWords(Heap::kNew) == 0);
|
||||
if (FLAG_write_protect_vm_isolate) {
|
||||
Dart::vm_isolate_group()->heap()->WriteProtect(true);
|
||||
}
|
||||
}
|
||||
|
||||
WritableCodePages::WritableCodePages(Thread* thread,
|
||||
IsolateGroup* isolate_group)
|
||||
: StackResource(thread), isolate_group_(isolate_group) {
|
||||
|
||||
@@ -133,7 +133,6 @@ class Heap {
|
||||
|
||||
// Initialize the heap and register it with the isolate.
|
||||
static void Init(IsolateGroup* isolate_group,
|
||||
bool is_vm_isolate,
|
||||
intptr_t max_new_gen_words,
|
||||
intptr_t max_old_gen_words);
|
||||
|
||||
@@ -274,7 +273,6 @@ class Heap {
|
||||
intptr_t ReachabilityBarrier() { return old_space_.collections(); }
|
||||
|
||||
IsolateGroup* isolate_group() const { return isolate_group_; }
|
||||
bool is_vm_isolate() const { return is_vm_isolate_; }
|
||||
|
||||
void SetupImagePage(void* pointer, uword size, bool is_executable) {
|
||||
old_space_.SetupImagePage(pointer, size, is_executable);
|
||||
@@ -312,7 +310,6 @@ class Heap {
|
||||
};
|
||||
|
||||
Heap(IsolateGroup* isolate_group,
|
||||
bool is_vm_isolate,
|
||||
intptr_t max_new_gen_semi_words, // Max capacity of new semi-space.
|
||||
intptr_t max_old_gen_words);
|
||||
|
||||
@@ -350,7 +347,6 @@ class Heap {
|
||||
void CollectForDebugging(Thread* thread);
|
||||
|
||||
IsolateGroup* const isolate_group_;
|
||||
const bool is_vm_isolate_;
|
||||
|
||||
// The different spaces used for allocation.
|
||||
Scavenger new_space_;
|
||||
@@ -405,8 +401,6 @@ class HeapIterationScope : public ThreadStackResource {
|
||||
void IterateOldObjects(ObjectVisitor* visitor) const;
|
||||
void IterateOldObjectsNoImagePages(ObjectVisitor* visitor) const;
|
||||
|
||||
void IterateVMIsolateObjects(ObjectVisitor* visitor) const;
|
||||
|
||||
void IterateObjectPointers(ObjectPointerVisitor* visitor,
|
||||
ValidationPolicy validate_frames);
|
||||
void IterateStackPointers(ObjectPointerVisitor* visitor,
|
||||
@@ -429,14 +423,6 @@ class ForceGrowthScope : public ThreadStackResource {
|
||||
DISALLOW_COPY_AND_ASSIGN(ForceGrowthScope);
|
||||
};
|
||||
|
||||
// Note: During this scope all pages are writable and the code pages are
|
||||
// non-executable.
|
||||
class WritableVMIsolateScope : ThreadStackResource {
|
||||
public:
|
||||
explicit WritableVMIsolateScope(Thread* thread);
|
||||
~WritableVMIsolateScope();
|
||||
};
|
||||
|
||||
class WritableCodePages : StackResource {
|
||||
public:
|
||||
WritableCodePages(Thread* thread, IsolateGroup* isolate_group);
|
||||
|
||||
@@ -61,7 +61,7 @@ intptr_t Page::CachedSize() {
|
||||
}
|
||||
|
||||
static bool CanUseCache(uword flags) {
|
||||
return (flags & (Page::kImage | Page::kLarge | Page::kVMIsolate)) == 0;
|
||||
return (flags & (Page::kImage | Page::kLarge | Page::kFrozen)) == 0;
|
||||
}
|
||||
|
||||
static intptr_t CacheIndex(uword flags) {
|
||||
|
||||
+14
-5
@@ -68,16 +68,17 @@ class Page {
|
||||
enum PageFlags : uword {
|
||||
kExecutable = 1 << 0,
|
||||
kLarge = 1 << 1,
|
||||
// Not allocated by VM, premarked, cannot change permissions.
|
||||
kImage = 1 << 2,
|
||||
kVMIsolate = 1 << 3,
|
||||
kNew = 1 << 4,
|
||||
kEvacuationCandidate = 1 << 5,
|
||||
kNeverEvacuate = 1 << 6,
|
||||
kNew = 1 << 3,
|
||||
kEvacuationCandidate = 1 << 4,
|
||||
kNeverEvacuate = 1 << 5,
|
||||
// Allocated by VM, premarked, cannot change permissions.
|
||||
kFrozen = 1 << 6,
|
||||
};
|
||||
bool is_executable() const { return (flags_ & kExecutable) != 0; }
|
||||
bool is_large() const { return (flags_ & kLarge) != 0; }
|
||||
bool is_image() const { return (flags_ & kImage) != 0; }
|
||||
bool is_vm_isolate() const { return (flags_ & kVMIsolate) != 0; }
|
||||
bool is_new() const { return (flags_ & kNew) != 0; }
|
||||
bool is_old() const { return !is_new(); }
|
||||
bool is_evacuation_candidate() const {
|
||||
@@ -98,6 +99,14 @@ class Page {
|
||||
flags_ &= ~kNeverEvacuate;
|
||||
}
|
||||
}
|
||||
bool is_frozen() const { return (flags_ & kFrozen) != 0; }
|
||||
void set_frozen(bool value) {
|
||||
if (value) {
|
||||
flags_ |= kFrozen;
|
||||
} else {
|
||||
flags_ &= ~kFrozen;
|
||||
}
|
||||
}
|
||||
|
||||
Page* next() const { return next_; }
|
||||
void set_next(Page* next) { next_ = next; }
|
||||
|
||||
+65
-10
@@ -184,9 +184,6 @@ Page* PageSpace::AllocatePage(bool is_exec, bool link) {
|
||||
if (is_exec) {
|
||||
flags |= Page::kExecutable;
|
||||
}
|
||||
if ((heap_ != nullptr) && (heap_->is_vm_isolate())) {
|
||||
flags |= Page::kVMIsolate;
|
||||
}
|
||||
Page* page = Page::Allocate(Page::kPageSize, flags);
|
||||
if (page == nullptr) {
|
||||
RELEASE_ASSERT(!FLAG_abort_on_oom);
|
||||
@@ -204,7 +201,7 @@ Page* PageSpace::AllocatePage(bool is_exec, bool link) {
|
||||
}
|
||||
|
||||
page->set_object_end(page->memory_->end());
|
||||
if (!is_exec && (heap_ != nullptr) && !heap_->is_vm_isolate()) {
|
||||
if (!is_exec) {
|
||||
page->AllocateForwardingPage();
|
||||
}
|
||||
|
||||
@@ -228,9 +225,6 @@ Page* PageSpace::AllocateLargePage(intptr_t size, bool is_exec) {
|
||||
if (is_exec) {
|
||||
flags |= Page::kExecutable;
|
||||
}
|
||||
if ((heap_ != nullptr) && (heap_->is_vm_isolate())) {
|
||||
flags |= Page::kVMIsolate;
|
||||
}
|
||||
Page* page = Page::Allocate(page_size_in_words << kWordSizeLog2, flags);
|
||||
|
||||
MutexLocker ml(&pages_lock_);
|
||||
@@ -433,6 +427,58 @@ void PageSpace::ReleaseLock(FreeList* freelist) {
|
||||
usage_.used_in_words -= (freelist->ReleaseBumpAllocation() >> kWordSizeLog2);
|
||||
}
|
||||
|
||||
void PageSpace::Freeze(Page* page) {
|
||||
ASSERT(FLAG_write_protect_code);
|
||||
|
||||
// Move to the image page list and premark its objects. This page is like an
|
||||
// image page, except that we are responsible for freeing it at shutdown.
|
||||
|
||||
{
|
||||
Page* prev_page = nullptr;
|
||||
Page* search_page = exec_pages_;
|
||||
while (search_page != nullptr) {
|
||||
if (search_page == page) {
|
||||
search_page = search_page->next();
|
||||
if (prev_page == nullptr) {
|
||||
exec_pages_ = search_page;
|
||||
} else {
|
||||
prev_page->WriteProtect(false);
|
||||
prev_page->set_next(search_page);
|
||||
prev_page->WriteProtect(true);
|
||||
}
|
||||
} else {
|
||||
prev_page = search_page;
|
||||
search_page = search_page->next();
|
||||
}
|
||||
}
|
||||
if (exec_pages_tail_ == page) {
|
||||
exec_pages_tail_ = prev_page;
|
||||
}
|
||||
}
|
||||
|
||||
page->WriteProtect(false);
|
||||
{
|
||||
page->set_next(image_pages_);
|
||||
image_pages_ = page;
|
||||
|
||||
uword scan = page->object_start();
|
||||
uword end = page->object_end();
|
||||
while (scan < end) {
|
||||
ObjectPtr obj = UntaggedObject::FromAddr(scan);
|
||||
if (!obj->IsFreeListElement()) {
|
||||
ASSERT(obj->IsInstructions());
|
||||
obj->untag()->SetMarkBitUnsynchronized();
|
||||
}
|
||||
scan += obj->untag()->HeapSize();
|
||||
}
|
||||
|
||||
page->set_frozen(true);
|
||||
}
|
||||
page->WriteProtect(true);
|
||||
|
||||
freelists_[kExecutableFreelist].Reset();
|
||||
}
|
||||
|
||||
void PageSpace::PauseConcurrentMarking() {
|
||||
MonitorLocker ml(&tasks_lock_);
|
||||
ASSERT(pause_concurrent_marking_.load() == 0);
|
||||
@@ -640,7 +686,7 @@ void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
|
||||
|
||||
void PageSpace::VisitObjectsNoImagePages(ObjectVisitor* visitor) const {
|
||||
for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
|
||||
if (!it.page()->is_image()) {
|
||||
if (!it.page()->is_image() && !it.page()->is_frozen()) {
|
||||
it.page()->VisitObjects(visitor);
|
||||
}
|
||||
}
|
||||
@@ -648,7 +694,7 @@ void PageSpace::VisitObjectsNoImagePages(ObjectVisitor* visitor) const {
|
||||
|
||||
void PageSpace::VisitObjectsImagePages(ObjectVisitor* visitor) const {
|
||||
for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
|
||||
if (it.page()->is_image()) {
|
||||
if (it.page()->is_image() || it.page()->is_frozen()) {
|
||||
it.page()->VisitObjects(visitor);
|
||||
}
|
||||
}
|
||||
@@ -1055,9 +1101,11 @@ void PageSpace::CollectGarbageHelper(Thread* thread,
|
||||
if (marker_ == nullptr) {
|
||||
ASSERT(phase() == kDone);
|
||||
marker_ = new GCMarker(isolate_group, heap_);
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
if (FLAG_use_incremental_compactor) {
|
||||
GCIncrementalCompactor::Prologue(this);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ASSERT(phase() == kAwaitingFinalization);
|
||||
}
|
||||
@@ -1089,9 +1137,11 @@ void PageSpace::CollectGarbageHelper(Thread* thread,
|
||||
bool has_reservation = MarkReservation();
|
||||
|
||||
bool new_space_is_swept = false;
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
if (FLAG_use_incremental_compactor) {
|
||||
new_space_is_swept = GCIncrementalCompactor::Epilogue(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reset the freelists and setup sweeping.
|
||||
for (intptr_t i = 0; i < num_freelists_; i++) {
|
||||
@@ -1341,7 +1391,12 @@ void PageSpace::SweepExecutable() {
|
||||
MutexLocker ml(freelist->mutex());
|
||||
while (page != nullptr) {
|
||||
Page* next_page = page->next();
|
||||
bool page_in_use = sweeper.SweepPage(page, freelist);
|
||||
bool page_in_use;
|
||||
if (page->is_frozen()) {
|
||||
page_in_use = true;
|
||||
} else {
|
||||
page_in_use = sweeper.SweepPage(page, freelist);
|
||||
}
|
||||
if (page_in_use) {
|
||||
prev_page = page;
|
||||
} else {
|
||||
|
||||
@@ -313,6 +313,8 @@ class PageSpace {
|
||||
void AcquireLock(FreeList* freelist);
|
||||
void ReleaseLock(FreeList* freelist);
|
||||
|
||||
void Freeze(Page* page);
|
||||
|
||||
void PauseConcurrentMarking();
|
||||
void ResumeConcurrentMarking();
|
||||
void YieldConcurrentMarking();
|
||||
|
||||
@@ -1744,8 +1744,6 @@ void Scavenger::AddRegionsToObjectSet(ObjectSet* set) const {
|
||||
void Scavenger::TryAllocateNewTLAB(Thread* thread,
|
||||
intptr_t min_size,
|
||||
bool can_safepoint) {
|
||||
ASSERT(heap_ != Dart::vm_isolate_group()->heap());
|
||||
|
||||
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
|
||||
// Find the remaining space available in the TLAB before abandoning it so we
|
||||
// can reset the heap sampling offset in the new TLAB.
|
||||
|
||||
@@ -261,7 +261,6 @@ class Scavenger {
|
||||
|
||||
uword TryAllocateFromTLAB(Thread* thread, intptr_t size) {
|
||||
ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
||||
ASSERT(heap_ != Dart::vm_isolate_group()->heap());
|
||||
|
||||
const uword result = thread->top();
|
||||
const intptr_t remaining = static_cast<intptr_t>(thread->end()) - result;
|
||||
|
||||
@@ -450,7 +450,8 @@ void ImageWriter::DumpInstructionsSizes() {
|
||||
}
|
||||
owner = WeakSerializationReference::Unwrap(data.code_->owner());
|
||||
js.OpenObject();
|
||||
if (owner.IsFunction()) {
|
||||
if (owner.IsFunction() &&
|
||||
(owner.ptr() != StubCode::UnknownDartCode().owner())) {
|
||||
cls = Function::Cast(owner).Owner();
|
||||
name = cls.ScrubbedName();
|
||||
lib = cls.library();
|
||||
@@ -701,12 +702,11 @@ uword ImageWriter::GetMarkedTags(const Object& obj) {
|
||||
const char* ImageWriter::SectionSymbol(ProgramSection section, bool vm) {
|
||||
switch (section) {
|
||||
case ProgramSection::Text:
|
||||
return vm ? kVmSnapshotInstructionsAsmSymbol
|
||||
: kIsolateSnapshotInstructionsAsmSymbol;
|
||||
return kSnapshotTextAsmSymbol;
|
||||
case ProgramSection::Data:
|
||||
return vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
|
||||
return kSnapshotDataAsmSymbol;
|
||||
case ProgramSection::Bss:
|
||||
return vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol;
|
||||
return kSnapshotBssAsmSymbol;
|
||||
case ProgramSection::BuildId:
|
||||
return kSnapshotBuildIdAsmSymbol;
|
||||
}
|
||||
@@ -1288,10 +1288,8 @@ void AssemblyImageWriter::Finalize() {
|
||||
#if defined(DART_TARGET_OS_WINDOWS)
|
||||
// __declspec(dllexport)
|
||||
const char* const exported_symbols[] = {
|
||||
kVmSnapshotDataCSymbol,
|
||||
kVmSnapshotInstructionsCSymbol,
|
||||
kIsolateSnapshotDataCSymbol,
|
||||
kIsolateSnapshotInstructionsCSymbol,
|
||||
kSnapshotDataCSymbol,
|
||||
kSnapshotTextCSymbol,
|
||||
};
|
||||
assembly_stream_->WriteString(".section .drectve,\"yni\"\n");
|
||||
assembly_stream_->WriteString(".ascii \"");
|
||||
@@ -1652,6 +1650,23 @@ void AssemblyImageWriter::ExitSection(ProgramSection name,
|
||||
UNIMPLEMENTED();
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (name == ProgramSection::Text) {
|
||||
assembly_stream_->Printf(
|
||||
".globl _kDartVmSnapshotInstructions\n"
|
||||
"_kDartVmSnapshotInstructions = _kDartSnapshotText\n"
|
||||
".globl _kDartIsolateSnapshotInstructions\n"
|
||||
"_kDartIsolateSnapshotInstructions = _kDartSnapshotText\n");
|
||||
} else if (name == ProgramSection::Data) {
|
||||
assembly_stream_->Printf(
|
||||
".globl _kDartVmSnapshotData\n"
|
||||
"_kDartVmSnapshotData = _kDartSnapshotData\n"
|
||||
".globl _kDartIsolateSnapshotData\n"
|
||||
"_kDartIsolateSnapshotData = _kDartSnapshotData\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// We need to generate a text segment of the appropriate size in the shared
|
||||
// object writer for two reasons:
|
||||
//
|
||||
|
||||
@@ -479,14 +479,11 @@ class ImageWriter : public ValueObject {
|
||||
static constexpr intptr_t SectionLabel(ProgramSection section, bool vm) {
|
||||
switch (section) {
|
||||
case ProgramSection::Text:
|
||||
return vm ? SharedObjectWriter::kVmInstructionsLabel
|
||||
: SharedObjectWriter::kIsolateInstructionsLabel;
|
||||
return SharedObjectWriter::kIsolateInstructionsLabel;
|
||||
case ProgramSection::Data:
|
||||
return vm ? SharedObjectWriter::kVmDataLabel
|
||||
: SharedObjectWriter::kIsolateDataLabel;
|
||||
return SharedObjectWriter::kIsolateDataLabel;
|
||||
case ProgramSection::Bss:
|
||||
return vm ? SharedObjectWriter::kVmBssLabel
|
||||
: SharedObjectWriter::kIsolateBssLabel;
|
||||
return SharedObjectWriter::kIsolateBssLabel;
|
||||
case ProgramSection::BuildId:
|
||||
// Both vm and isolate share the build id section.
|
||||
return SharedObjectWriter::kBuildIdLabel;
|
||||
@@ -769,10 +766,6 @@ class ImageWriter : public ValueObject {
|
||||
};
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::Bss,
|
||||
/*vm=*/true) ==
|
||||
SharedObjectWriter::kVmBssLabel,
|
||||
"unexpected label for VM BSS section");
|
||||
static_assert(ImageWriter::SectionLabel(ImageWriter::ProgramSection::Bss,
|
||||
/*vm=*/false) ==
|
||||
SharedObjectWriter::kIsolateBssLabel,
|
||||
|
||||
+49
-77
@@ -303,13 +303,11 @@ void MutatorThreadPool::NotifyIdle() {
|
||||
IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
void* embedder_data,
|
||||
ObjectStore* object_store,
|
||||
Dart_IsolateFlags api_flags,
|
||||
bool is_vm_isolate)
|
||||
Dart_IsolateFlags api_flags)
|
||||
: class_table_(nullptr),
|
||||
cached_class_table_table_(nullptr),
|
||||
object_store_(object_store),
|
||||
class_table_allocator_(),
|
||||
is_vm_isolate_(is_vm_isolate),
|
||||
embedder_data_(embedder_data),
|
||||
thread_pool_(),
|
||||
isolates_lock_(new SafepointRwLock()),
|
||||
@@ -361,19 +359,17 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
tag_table_lock_(),
|
||||
roots_(new Roots()) {
|
||||
FlagsCopyFrom(api_flags);
|
||||
if (!is_vm_isolate) {
|
||||
intptr_t max_worker_threads;
|
||||
if (FLAG_disable_thread_pool_limit) {
|
||||
max_worker_threads = 0;
|
||||
} else {
|
||||
// There needs to be at least one more thread than active mutators slots
|
||||
// so that there is a thread waiting in IncreaseMutatorCount (instead of
|
||||
// unscheduled task sitting in the thread pool's queue) to eventually
|
||||
// timeout and trigger StealActiveMutators.
|
||||
max_worker_threads = Scavenger::MaxMutatorThreadCount() + 2;
|
||||
}
|
||||
thread_pool_.reset(new MutatorThreadPool(this, max_worker_threads));
|
||||
intptr_t max_worker_threads;
|
||||
if (FLAG_disable_thread_pool_limit) {
|
||||
max_worker_threads = 0;
|
||||
} else {
|
||||
// There needs to be at least one more thread than active mutators slots
|
||||
// so that there is a thread waiting in IncreaseMutatorCount (instead of
|
||||
// unscheduled task sitting in the thread pool's queue) to eventually
|
||||
// timeout and trigger StealActiveMutators.
|
||||
max_worker_threads = Scavenger::MaxMutatorThreadCount() + 2;
|
||||
}
|
||||
thread_pool_.reset(new MutatorThreadPool(this, max_worker_threads));
|
||||
{
|
||||
WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
|
||||
// Keep isolate IDs less than 2^53 so web clients of the service
|
||||
@@ -387,20 +383,13 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
cached_class_table_table_.store(class_table_->table());
|
||||
memset(&native_assets_api_, 0, sizeof(NativeAssetsApi));
|
||||
|
||||
if (!is_vm_isolate) {
|
||||
*roots() = *Dart::vm_isolate_group()->roots();
|
||||
}
|
||||
Roots::SetCurrent(roots());
|
||||
}
|
||||
|
||||
IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
void* embedder_data,
|
||||
Dart_IsolateFlags api_flags,
|
||||
bool is_vm_isolate)
|
||||
: IsolateGroup(source, embedder_data, nullptr, api_flags, is_vm_isolate) {
|
||||
set_object_store(new ObjectStore());
|
||||
object_store()->InitStubs();
|
||||
}
|
||||
Dart_IsolateFlags api_flags)
|
||||
: IsolateGroup(source, embedder_data, nullptr, api_flags) {}
|
||||
|
||||
IsolateGroup::~IsolateGroup() {
|
||||
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -485,12 +474,8 @@ void IsolateGroup::UnregisterIsolateGroupMutator(Thread* mutator) {
|
||||
mutators_.Remove(mutator);
|
||||
}
|
||||
|
||||
void IsolateGroup::CreateHeap(bool is_vm_isolate,
|
||||
bool is_service_or_kernel_isolate) {
|
||||
Heap::Init(this, is_vm_isolate,
|
||||
is_vm_isolate
|
||||
? 0 // New gen size 0; VM isolate should only allocate in old.
|
||||
: FLAG_new_gen_semi_max_size * MBInWords,
|
||||
void IsolateGroup::CreateHeap(bool is_service_or_kernel_isolate) {
|
||||
Heap::Init(this, FLAG_new_gen_semi_max_size * MBInWords,
|
||||
(is_service_or_kernel_isolate ? kDefaultMaxOldGenHeapSize
|
||||
: FLAG_old_gen_heap_size) *
|
||||
MBInWords);
|
||||
@@ -519,13 +504,9 @@ void IsolateGroup::Shutdown() {
|
||||
}
|
||||
// Ensure to join all threads before waiting for pending GC tasks (the thread
|
||||
// pool can trigger idle notification, which can start new GC tasks).
|
||||
//
|
||||
// (The vm-isolate doesn't have a thread pool.)
|
||||
if (!is_vm_isolate_) {
|
||||
ASSERT(thread_pool_ != nullptr);
|
||||
thread_pool_->Shutdown();
|
||||
thread_pool_.reset();
|
||||
}
|
||||
ASSERT(thread_pool_ != nullptr);
|
||||
thread_pool_->Shutdown();
|
||||
thread_pool_.reset();
|
||||
|
||||
{
|
||||
MonitorLocker ml(Isolate::isolate_creation_monitor_);
|
||||
@@ -554,7 +535,7 @@ void IsolateGroup::Shutdown() {
|
||||
// If the creation of the isolate group (or the first isolate within the
|
||||
// isolate group) failed, we do not invoke the cleanup callback (the
|
||||
// embedder is responsible for handling the creation error).
|
||||
if (initial_spawn_successful_ && !is_vm_isolate_) {
|
||||
if (initial_spawn_successful_) {
|
||||
auto group_shutdown_callback = Isolate::GroupCleanupCallback();
|
||||
if (group_shutdown_callback != nullptr) {
|
||||
group_shutdown_callback(embedder_data());
|
||||
@@ -753,6 +734,15 @@ void IsolateGroup::UnregisterIsolateGroup(IsolateGroup* isolate_group) {
|
||||
isolate_groups_->Remove(isolate_group);
|
||||
}
|
||||
|
||||
bool IsolateGroup::HasIsolateGroups() {
|
||||
ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
|
||||
for (auto group : *isolate_groups_) {
|
||||
USE(group);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsolateGroup::HasApplicationIsolateGroups() {
|
||||
ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
|
||||
for (auto group : *isolate_groups_) {
|
||||
@@ -763,16 +753,6 @@ bool IsolateGroup::HasApplicationIsolateGroups() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsolateGroup::HasOnlyVMIsolateGroup() {
|
||||
ReadRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
|
||||
for (auto group : *isolate_groups_) {
|
||||
if (!group->is_vm_isolate()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void IsolateGroup::Init() {
|
||||
ASSERT(isolate_groups_rwlock_ == nullptr);
|
||||
isolate_groups_rwlock_ = new RwLock();
|
||||
@@ -1026,7 +1006,6 @@ void IsolateGroup::RehashConstants(Become* become) {
|
||||
while (it.MoveNext()) {
|
||||
constant ^= set.GetKey(it.Current());
|
||||
ASSERT(!constant.IsNull());
|
||||
ASSERT(!constant.InVMIsolateHeap());
|
||||
constant.ClearCanonical();
|
||||
}
|
||||
set.Release();
|
||||
@@ -1909,18 +1888,10 @@ void Isolate::InitVM() {
|
||||
|
||||
Isolate* Isolate::InitIsolate(const char* name_prefix,
|
||||
IsolateGroup* isolate_group,
|
||||
const Dart_IsolateFlags& api_flags,
|
||||
bool is_vm_isolate) {
|
||||
const Dart_IsolateFlags& api_flags) {
|
||||
Isolate* result = new Isolate(isolate_group, api_flags);
|
||||
result->set_is_vm_isolate(is_vm_isolate);
|
||||
result->BuildName(name_prefix);
|
||||
if (!is_vm_isolate) {
|
||||
// vm isolate object store is initialized later, after null instance
|
||||
// is created (in Dart::Init).
|
||||
// Non-vm isolates need to have isolate object store initialized is that
|
||||
// exit_listeners have to be null-initialized as they will be used if
|
||||
// we fail to create isolate below, have to do low level shutdown.
|
||||
ASSERT(result->group()->object_store() != nullptr);
|
||||
if (!isolate_group->is_bootstrapping()) {
|
||||
result->isolate_object_store()->Init();
|
||||
}
|
||||
|
||||
@@ -1993,6 +1964,16 @@ Isolate* Isolate::InitIsolate(const char* name_prefix,
|
||||
return result;
|
||||
}
|
||||
|
||||
void Isolate::FixInitiallyNullFields() {
|
||||
#if !defined(PRODUCT)
|
||||
pending_service_extension_calls_ = GrowableObjectArray::null();
|
||||
registered_service_extension_handlers_ = GrowableObjectArray::null();
|
||||
#endif
|
||||
finalizers_ = GrowableObjectArray::null();
|
||||
sticky_error_ = Error::null();
|
||||
isolate_object_store_->Init();
|
||||
}
|
||||
|
||||
ObjectPtr IsolateGroup::CallTagHandler(Dart_LibraryTag tag,
|
||||
const Object& arg1,
|
||||
const Object& arg2) {
|
||||
@@ -2680,12 +2661,9 @@ void Isolate::LowLevelCleanup(Isolate* isolate) {
|
||||
// Now it's safe to delete the isolate.
|
||||
delete isolate;
|
||||
|
||||
// Run isolate specific cleanup function for all non "vm-isolate's.
|
||||
const bool is_vm_isolate = Dart::vm_isolate() == isolate;
|
||||
if (!is_vm_isolate) {
|
||||
if (cleanup != nullptr) {
|
||||
cleanup(isolate_group->embedder_data(), callback_data);
|
||||
}
|
||||
// Run isolate specific cleanup function.
|
||||
if (cleanup != nullptr) {
|
||||
cleanup(isolate_group->embedder_data(), callback_data);
|
||||
}
|
||||
|
||||
const bool shutdown_group = isolate_group->UnregisterIsolateDecrementCount();
|
||||
@@ -2695,7 +2673,7 @@ void Isolate::LowLevelCleanup(Isolate* isolate) {
|
||||
Profiler::IsolateGroupShutdown(isolate_group);
|
||||
#endif
|
||||
|
||||
if (!is_vm_isolate) {
|
||||
{
|
||||
Thread::EnterIsolateGroupAsHelper(isolate_group, Thread::kUnknownTask,
|
||||
/*bypass_safepoint=*/false);
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -2717,10 +2695,7 @@ void Isolate::LowLevelCleanup(Isolate* isolate) {
|
||||
Thread::ExitIsolateGroupAsHelper(/*bypass_safepoint=*/false);
|
||||
}
|
||||
|
||||
// The "vm-isolate" does not have a thread pool.
|
||||
ASSERT(is_vm_isolate == (isolate_group->thread_pool() == nullptr));
|
||||
if (is_vm_isolate ||
|
||||
!isolate_group->thread_pool()->CurrentThreadIsWorker()) {
|
||||
if (!isolate_group->thread_pool()->CurrentThreadIsWorker()) {
|
||||
isolate_group->Shutdown();
|
||||
} else {
|
||||
class ShutdownGroupTask : public ThreadPool::Task {
|
||||
@@ -3684,8 +3659,7 @@ bool IsolateGroup::IsSystemIsolateGroup(const IsolateGroup* group) {
|
||||
}
|
||||
|
||||
bool Isolate::IsVMInternalIsolate(const Isolate* isolate) {
|
||||
return isolate->is_kernel_isolate() || isolate->is_service_isolate() ||
|
||||
isolate->is_vm_isolate();
|
||||
return isolate->is_kernel_isolate() || isolate->is_service_isolate();
|
||||
}
|
||||
|
||||
void Isolate::KillLocked(LibMsgId msg_id) {
|
||||
@@ -3736,9 +3710,7 @@ class IsolateKillerVisitor : public IsolateVisitor {
|
||||
kill_system_isolates_(kill_system_isolates) {}
|
||||
|
||||
IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id)
|
||||
: target_(isolate), msg_id_(msg_id), kill_system_isolates_(false) {
|
||||
ASSERT(isolate != Dart::vm_isolate());
|
||||
}
|
||||
: target_(isolate), msg_id_(msg_id), kill_system_isolates_(false) {}
|
||||
|
||||
virtual ~IsolateKillerVisitor() {}
|
||||
|
||||
@@ -3756,11 +3728,11 @@ class IsolateKillerVisitor : public IsolateVisitor {
|
||||
bool ShouldKill(Isolate* isolate) {
|
||||
if (kill_system_isolates_) {
|
||||
ASSERT(target_ == nullptr);
|
||||
// Don't kill the service isolate or vm isolate.
|
||||
// Don't kill the service isolate or kernel isolate.
|
||||
return IsSystemIsolate(isolate) && !Isolate::IsVMInternalIsolate(isolate);
|
||||
}
|
||||
// If a target_ is specified, then only kill the target_.
|
||||
// Otherwise, don't kill the service isolate or vm isolate.
|
||||
// Otherwise, don't kill the service isolate or kernel isolate.
|
||||
return (((target_ != nullptr) && (isolate == target_)) ||
|
||||
((target_ == nullptr) && !IsSystemIsolate(isolate)));
|
||||
}
|
||||
|
||||
+33
-32
@@ -136,16 +136,19 @@ typedef FixedCache<intptr_t, CatchEntryMovesRefPtr, 16> CatchEntryMovesCache;
|
||||
#define BOOL_ISOLATE_GROUP_FLAG_LIST(V) \
|
||||
V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false) \
|
||||
V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts) \
|
||||
V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
|
||||
V(PRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
|
||||
FLAG_use_field_guards) \
|
||||
V(PRODUCT, should_load_vmservice_library, ShouldLoadVmService, \
|
||||
load_vmservice_library, false) \
|
||||
V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
|
||||
V(PRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
|
||||
V(NONPRODUCT, snapshot_is_dontneed_safe, SnapshotIsDontNeedSafe, \
|
||||
snapshot_is_dontneed_safe, false) \
|
||||
V(NONPRODUCT, branch_coverage, BranchCoverage, branch_coverage, \
|
||||
FLAG_branch_coverage) \
|
||||
V(NONPRODUCT, coverage, Coverage, coverage, FLAG_coverage)
|
||||
V(NONPRODUCT, coverage, Coverage, coverage, FLAG_coverage) \
|
||||
V(PRODUCT, dwarf_stack_traces, DwarfStackTraces, dwarf_stack_traces, \
|
||||
FLAG_dwarf_stack_traces_mode) \
|
||||
V(PRODUCT, code_comments, CodeComments, code_comments, FLAG_code_comments)
|
||||
|
||||
// List of Isolate flags with corresponding members of Dart_IsolateFlags and
|
||||
// corresponding global command line flags.
|
||||
@@ -163,14 +166,14 @@ class IsolateGroupSource {
|
||||
IsolateGroupSource(const char* script_uri,
|
||||
const char* name,
|
||||
const uint8_t* snapshot_data,
|
||||
const uint8_t* snapshot_instructions,
|
||||
const uint8_t* snapshot_text,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size,
|
||||
Dart_IsolateFlags flags)
|
||||
: script_uri(script_uri == nullptr ? nullptr : Utils::StrDup(script_uri)),
|
||||
name(Utils::StrDup(name)),
|
||||
snapshot_data(snapshot_data),
|
||||
snapshot_instructions(snapshot_instructions),
|
||||
snapshot_text(snapshot_text),
|
||||
kernel_buffer(kernel_buffer),
|
||||
kernel_buffer_size(kernel_buffer_size),
|
||||
flags(flags),
|
||||
@@ -191,7 +194,7 @@ class IsolateGroupSource {
|
||||
char* script_uri;
|
||||
char* name;
|
||||
const uint8_t* snapshot_data;
|
||||
const uint8_t* snapshot_instructions;
|
||||
const uint8_t* snapshot_text;
|
||||
const uint8_t* kernel_buffer;
|
||||
const intptr_t kernel_buffer_size;
|
||||
Dart_IsolateFlags flags;
|
||||
@@ -318,12 +321,10 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
void* embedder_data,
|
||||
ObjectStore* object_store,
|
||||
Dart_IsolateFlags api_flags,
|
||||
bool is_vm_isolate);
|
||||
Dart_IsolateFlags api_flags);
|
||||
IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
|
||||
void* embedder_data,
|
||||
Dart_IsolateFlags api_flags,
|
||||
bool is_vm_isolate);
|
||||
Dart_IsolateFlags api_flags);
|
||||
~IsolateGroup();
|
||||
|
||||
void RehashConstants(Become* become);
|
||||
@@ -335,7 +336,6 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
std::shared_ptr<IsolateGroupSource> shareable_source() const {
|
||||
return source_;
|
||||
}
|
||||
bool is_vm_isolate() const { return is_vm_isolate_; }
|
||||
void* embedder_data() const { return embedder_data_; }
|
||||
|
||||
bool initial_spawn_successful() { return initial_spawn_successful_; }
|
||||
@@ -385,7 +385,7 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
ThreadRegistry* thread_registry() const { return thread_registry_.get(); }
|
||||
SafepointHandler* safepoint_handler() { return safepoint_handler_.get(); }
|
||||
|
||||
void CreateHeap(bool is_vm_isolate, bool is_service_or_kernel_isolate);
|
||||
void CreateHeap(bool is_service_or_kernel_isolate);
|
||||
void SetupImagePage(const uint8_t* snapshot_buffer, bool is_executable);
|
||||
void Shutdown();
|
||||
|
||||
@@ -461,6 +461,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
const char** obfuscation_map() const { return obfuscation_map_; }
|
||||
|
||||
bool is_system_isolate_group() const { return is_system_isolate_group_; }
|
||||
bool is_bootstrapping() const { return bootstrapping_; }
|
||||
void set_bootstrapping(bool v) { bootstrapping_ = v; }
|
||||
|
||||
// IsolateGroup-specific flag handling.
|
||||
static void FlagsInitialize(Dart_IsolateFlags* api_flags);
|
||||
@@ -502,14 +504,24 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
void set_asserts(bool value) {
|
||||
isolate_group_flags_.UpdateBool<EnableAssertsBit>(value);
|
||||
}
|
||||
|
||||
void set_branch_coverage(bool value) {
|
||||
isolate_group_flags_.UpdateBool<BranchCoverageBit>(value);
|
||||
}
|
||||
|
||||
void set_coverage(bool value) {
|
||||
isolate_group_flags_.UpdateBool<CoverageBit>(value);
|
||||
}
|
||||
void set_use_field_guards(bool value) {
|
||||
isolate_group_flags_.UpdateBool<UseFieldGuardsBit>(value);
|
||||
}
|
||||
void set_use_osr(bool value) {
|
||||
isolate_group_flags_.UpdateBool<UseOsrBit>(value);
|
||||
}
|
||||
void set_code_comments(bool value) {
|
||||
isolate_group_flags_.UpdateBool<CodeCommentsBit>(value);
|
||||
}
|
||||
void set_dwarf_stack_traces(bool value) {
|
||||
isolate_group_flags_.UpdateBool<DwarfStackTracesBit>(value);
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -535,14 +547,6 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
isolate_group_flags_.UpdateBool<HasSeenOOMBit>(value);
|
||||
}
|
||||
|
||||
#if defined(PRODUCT)
|
||||
void set_use_osr(bool use_osr) { ASSERT(!use_osr); }
|
||||
#else // defined(PRODUCT)
|
||||
void set_use_osr(bool use_osr) {
|
||||
isolate_group_flags_.UpdateBool<UseOsrBit>(use_osr);
|
||||
}
|
||||
#endif // defined(PRODUCT)
|
||||
|
||||
// Class table for the program loaded into this isolate group.
|
||||
//
|
||||
// This table is modified by kernel loading.
|
||||
@@ -733,8 +737,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
static void RegisterIsolateGroup(IsolateGroup* isolate_group);
|
||||
static void UnregisterIsolateGroup(IsolateGroup* isolate_group);
|
||||
|
||||
static bool HasIsolateGroups();
|
||||
static bool HasApplicationIsolateGroups();
|
||||
static bool HasOnlyVMIsolateGroup();
|
||||
static bool IsSystemIsolateGroup(const IsolateGroup* group);
|
||||
|
||||
int64_t UptimeMicros() const;
|
||||
@@ -876,7 +880,9 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
V(SnapshotIsDontNeedSafe) \
|
||||
V(BranchCoverage) \
|
||||
V(Coverage) \
|
||||
V(HasDynamicallyExtendableClasses)
|
||||
V(HasDynamicallyExtendableClasses) \
|
||||
V(DwarfStackTraces) \
|
||||
V(CodeComments)
|
||||
|
||||
// Isolate group specific flags.
|
||||
enum FlagBits {
|
||||
@@ -903,7 +909,6 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
|
||||
const char** obfuscation_map_ = nullptr;
|
||||
|
||||
bool is_vm_isolate_ = false;
|
||||
void* embedder_data_ = nullptr;
|
||||
|
||||
IdleTimeHandler idle_time_handler_;
|
||||
@@ -919,6 +924,7 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
|
||||
Dart_DeferredLoadHandler deferred_load_handler_ = nullptr;
|
||||
int64_t start_time_micros_;
|
||||
bool is_system_isolate_group_;
|
||||
bool bootstrapping_ = true;
|
||||
|
||||
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
int64_t last_reload_timestamp_;
|
||||
@@ -1451,11 +1457,6 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
|
||||
void PauseEventHandler();
|
||||
#endif
|
||||
|
||||
bool is_vm_isolate() const { return isolate_flags_.Read<IsVMIsolateBit>(); }
|
||||
void set_is_vm_isolate(bool value) {
|
||||
isolate_flags_.UpdateBool<IsVMIsolateBit>(value);
|
||||
}
|
||||
|
||||
bool is_service_registered() const {
|
||||
return isolate_flags_.Read<IsServiceRegisteredBit>();
|
||||
}
|
||||
@@ -1535,8 +1536,8 @@ class Isolate : public IntrusiveDListEntry<Isolate> {
|
||||
static void InitVM();
|
||||
static Isolate* InitIsolate(const char* name_prefix,
|
||||
IsolateGroup* isolate_group,
|
||||
const Dart_IsolateFlags& api_flags,
|
||||
bool is_vm_isolate = false);
|
||||
const Dart_IsolateFlags& api_flags);
|
||||
void FixInitiallyNullFields();
|
||||
|
||||
// The isolate_creation_monitor_ should be held when calling Kill().
|
||||
void KillLocked(LibMsgId msg_id);
|
||||
|
||||
@@ -1520,14 +1520,13 @@ void ProgramReloadContext::DeoptimizeDependentCode() {
|
||||
TIMELINE_SCOPE(DeoptimizeDependentCode);
|
||||
ClassTable* class_table = IG->class_table();
|
||||
|
||||
const intptr_t bottom = Dart::vm_isolate_group()->class_table()->NumCids();
|
||||
const intptr_t top = IG->class_table()->NumCids();
|
||||
const intptr_t num_cids = IG->class_table()->NumCids();
|
||||
Class& cls = Class::Handle();
|
||||
Array& fields = Array::Handle();
|
||||
Field& field = Field::Handle();
|
||||
Thread* thread = Thread::Current();
|
||||
SafepointWriteRwLocker ml(thread, IG->program_lock());
|
||||
for (intptr_t cls_idx = bottom; cls_idx < top; cls_idx++) {
|
||||
for (intptr_t cls_idx = kInstanceCid; cls_idx < num_cids; cls_idx++) {
|
||||
if (!class_table->HasValidClassAt(cls_idx)) {
|
||||
// Skip.
|
||||
continue;
|
||||
@@ -1550,8 +1549,6 @@ void ProgramReloadContext::DeoptimizeDependentCode() {
|
||||
}
|
||||
|
||||
DeoptimizeTypeTestingStubs();
|
||||
|
||||
// TODO(rmacnak): Also call LibraryPrefix::InvalidateDependentCode.
|
||||
}
|
||||
|
||||
void ProgramReloadContext::CheckpointClasses() {
|
||||
@@ -2285,6 +2282,9 @@ void ProgramReloadContext::InvalidateFunctions(
|
||||
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
|
||||
for (intptr_t i = 0; i < functions.length(); i++) {
|
||||
const Function& func = *functions[i];
|
||||
if (func.ptr() == StubCode::UnknownDartCode().owner()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force-optimized functions cannot deoptimize.
|
||||
if (func.ForceOptimize()) continue;
|
||||
|
||||
@@ -155,9 +155,6 @@ intptr_t Log::cursor() const {
|
||||
bool Log::ShouldLogForIsolateGroup(const IsolateGroup* isolate_group) {
|
||||
if (FLAG_isolate_log_filter == nullptr) {
|
||||
// By default, do not log for the service or kernel isolates.
|
||||
if (isolate_group == Dart::vm_isolate_group()) {
|
||||
return true;
|
||||
}
|
||||
if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+30
-30
@@ -2455,20 +2455,17 @@ void MachOWriter::AssertConsistency(const MachOWriter* snapshot,
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t HashPortion(const MachOSection::Portion& portion) {
|
||||
static uint64_t HashPortion(const MachOSection::Portion& portion) {
|
||||
if (portion.bytes == nullptr) return 0;
|
||||
const uint32_t hash = Utils::StringHash(portion.bytes, portion.size);
|
||||
const uint64_t hash = Utils::StringHash64(portion.bytes, portion.size);
|
||||
// Ensure a non-zero return.
|
||||
return hash == 0 ? 1 : hash;
|
||||
}
|
||||
|
||||
// For the UUID, we generate a 128-bit hash, where each 32 bits is a
|
||||
// For the UUID, we generate a 128-bit hash, where each 64 bits is a
|
||||
// hash of the contents of the following segments in order:
|
||||
//
|
||||
// .text(VM) | .text(Isolate) | .rodata(VM) | .rodata(Isolate)
|
||||
//
|
||||
// Any component of the build ID which does not have an associated section
|
||||
// in the output is kept as 0.
|
||||
// .text(Isolate) | .rodata(Isolate)
|
||||
void MachOHeader::GenerateUuid() {
|
||||
// Don't create a UUID for a relocatable object.
|
||||
if (type_ == SnapshotType::Object) return;
|
||||
@@ -2484,30 +2481,21 @@ void MachOHeader::GenerateUuid() {
|
||||
// used to symbolicize non-symbolic stack traces.
|
||||
if (text_section == nullptr) return;
|
||||
|
||||
auto* const vm_instructions =
|
||||
text_section->FindPortion(kVmSnapshotInstructionsAsmSymbol);
|
||||
auto* const isolate_instructions =
|
||||
text_section->FindPortion(kIsolateSnapshotInstructionsAsmSymbol);
|
||||
// All MachO snapshots have at least one of the two instruction sections.
|
||||
ASSERT(vm_instructions != nullptr || isolate_instructions != nullptr);
|
||||
text_section->FindPortion(kSnapshotTextAsmSymbol);
|
||||
ASSERT(isolate_instructions != nullptr);
|
||||
|
||||
auto* const data_section =
|
||||
text_segment_->FindSection(mach_o::SECT_CONST, mach_o::SEG_TEXT);
|
||||
auto* const vm_data =
|
||||
data_section == nullptr
|
||||
? nullptr
|
||||
: data_section->FindPortion(kVmSnapshotDataAsmSymbol);
|
||||
auto* const isolate_data =
|
||||
data_section == nullptr
|
||||
? nullptr
|
||||
: data_section->FindPortion(kIsolateSnapshotDataAsmSymbol);
|
||||
: data_section->FindPortion(kSnapshotDataAsmSymbol);
|
||||
|
||||
uint32_t hashes[4];
|
||||
hashes[0] = vm_instructions == nullptr ? 0 : HashPortion(*vm_instructions);
|
||||
hashes[1] =
|
||||
isolate_instructions == nullptr ? 0 : HashPortion(*isolate_instructions);
|
||||
hashes[2] = vm_data == nullptr ? 0 : HashPortion(*vm_data);
|
||||
hashes[3] = isolate_data == nullptr ? 0 : HashPortion(*isolate_data);
|
||||
uint64_t hashes[2];
|
||||
COMPILE_ASSERT(sizeof(hashes) == 16); // 128-bit UUID
|
||||
hashes[0] = HashPortion(*isolate_instructions);
|
||||
hashes[1] = HashPortion(*isolate_data);
|
||||
|
||||
auto* const uuid_command = new (zone()) MachOUuid(hashes, sizeof(hashes));
|
||||
commands_.Add(uuid_command);
|
||||
@@ -2547,14 +2535,9 @@ void MachOHeader::CreateBSS() {
|
||||
const char* symbol_name;
|
||||
intptr_t label;
|
||||
// First determine whether this is the VM's text portion or the isolate's.
|
||||
if (strcmp(portion.symbol_name, kVmSnapshotInstructionsAsmSymbol) == 0) {
|
||||
size = BSS::kVmEntryCount * compiler::target::kWordSize;
|
||||
symbol_name = kVmSnapshotBssAsmSymbol;
|
||||
label = SharedObjectWriter::kVmBssLabel;
|
||||
} else if (strcmp(portion.symbol_name,
|
||||
kIsolateSnapshotInstructionsAsmSymbol) == 0) {
|
||||
if (strcmp(portion.symbol_name, kSnapshotTextAsmSymbol) == 0) {
|
||||
size = BSS::kIsolateGroupEntryCount * compiler::target::kWordSize;
|
||||
symbol_name = kIsolateSnapshotBssAsmSymbol;
|
||||
symbol_name = kSnapshotBssAsmSymbol;
|
||||
label = SharedObjectWriter::kIsolateBssLabel;
|
||||
} else {
|
||||
// Not VM or isolate text.
|
||||
@@ -3668,6 +3651,23 @@ void MachOSymbolTable::Initialize(SharedObjectWriter::Type type,
|
||||
if (portion.symbol_name != nullptr) {
|
||||
AddSymbol(portion.symbol_name, mach_o::N_SECT | mach_o::N_EXT, section,
|
||||
desc, portion.offset, portion.label);
|
||||
#if 1
|
||||
// TRANSITION
|
||||
if (strcmp(portion.symbol_name, "_kDartSnapshotText") == 0) {
|
||||
AddSymbol("_kDartVmSnapshotInstructions",
|
||||
mach_o::N_SECT | mach_o::N_EXT, section, desc,
|
||||
portion.offset, portion.label);
|
||||
AddSymbol("_kDartIsolateSnapshotInstructions",
|
||||
mach_o::N_SECT | mach_o::N_EXT, section, desc,
|
||||
portion.offset, portion.label);
|
||||
}
|
||||
if (strcmp(portion.symbol_name, "_kDartSnapshotData") == 0) {
|
||||
AddSymbol("_kDartVmSnapshotData", mach_o::N_SECT | mach_o::N_EXT,
|
||||
section, desc, portion.offset, portion.label);
|
||||
AddSymbol("_kDartIsolateSnapshotData", mach_o::N_SECT | mach_o::N_EXT,
|
||||
section, desc, portion.offset, portion.label);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1444,7 +1444,7 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster {
|
||||
continue;
|
||||
}
|
||||
obj = pool.ObjectAt(i);
|
||||
if (obj.IsInstance() && !obj.IsSmi() && !obj.InVMIsolateHeap()) {
|
||||
if (obj.IsInstance() && !obj.IsSmi()) {
|
||||
obj = Instance::Cast(obj).Canonicalize(d->thread());
|
||||
pool.SetObjectAt(i, obj);
|
||||
}
|
||||
@@ -1625,21 +1625,17 @@ void Deserializer::Deserialize() {
|
||||
AddBaseObject(StubCode::Subtype4TestCache());
|
||||
AddBaseObject(StubCode::Subtype6TestCache());
|
||||
AddBaseObject(StubCode::InstantiateTypeArguments());
|
||||
AddBaseObject(Code::Handle(zone(), object_store->init_async_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->init_async_star_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->init_sync_star_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->await_stub()));
|
||||
AddBaseObject(
|
||||
Code::Handle(zone(), object_store->await_with_type_check_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->yield_async_star_stub()));
|
||||
AddBaseObject(
|
||||
Code::Handle(zone(), object_store->suspend_sync_star_at_start_stub()));
|
||||
AddBaseObject(
|
||||
Code::Handle(zone(), object_store->suspend_sync_star_at_yield_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->return_async_stub()));
|
||||
AddBaseObject(
|
||||
Code::Handle(zone(), object_store->return_async_not_future_stub()));
|
||||
AddBaseObject(Code::Handle(zone(), object_store->return_async_star_stub()));
|
||||
AddBaseObject(StubCode::InitAsync());
|
||||
AddBaseObject(StubCode::InitAsyncStar());
|
||||
AddBaseObject(StubCode::InitSyncStar());
|
||||
AddBaseObject(StubCode::Await());
|
||||
AddBaseObject(StubCode::AwaitWithTypeCheck());
|
||||
AddBaseObject(StubCode::YieldAsyncStar());
|
||||
AddBaseObject(StubCode::SuspendSyncStarAtStart());
|
||||
AddBaseObject(StubCode::SuspendSyncStarAtYield());
|
||||
AddBaseObject(StubCode::ReturnAsync());
|
||||
AddBaseObject(StubCode::ReturnAsyncNotFuture());
|
||||
AddBaseObject(StubCode::ReturnAsyncStar());
|
||||
|
||||
if (num_base_objects_ != (next_ref_index_ - kFirstReference)) {
|
||||
FATAL("Snapshot expects %" Pd
|
||||
|
||||
+58
-344
@@ -490,8 +490,6 @@ static BytecodePtr CreateVMInternalBytecode(KernelBytecode::Opcode opcode) {
|
||||
#endif // defined(DART_DYNAMIC_MODULES)
|
||||
|
||||
void Object::InitNullAndBool(IsolateGroup* isolate_group) {
|
||||
// Should only be run by the vm isolate.
|
||||
ASSERT(isolate_group == Dart::vm_isolate_group());
|
||||
Thread* thread = Thread::Current();
|
||||
auto heap = isolate_group->heap();
|
||||
|
||||
@@ -584,6 +582,28 @@ void Object::InitNullAndBool(IsolateGroup* isolate_group) {
|
||||
ASSERT((null_ & kBoolVsNullMask) == 0);
|
||||
ASSERT((true_ & kBoolVsNullMask) != 0);
|
||||
ASSERT((false_ & kBoolVsNullMask) != 0);
|
||||
// And prevent the compactor from disrupting these patterns.
|
||||
Page::Of(Roots::null_obj())->set_never_evacuate(true);
|
||||
|
||||
Roots::null_object().initRO(Object::null());
|
||||
Roots::null_class().initRO(Class::null());
|
||||
Roots::null_array().initRO(Array::null());
|
||||
Roots::null_string().initRO(String::null());
|
||||
Roots::null_instance().initRO(Instance::null());
|
||||
Roots::null_function().initRO(Function::null());
|
||||
Roots::null_function_type().initRO(FunctionType::null());
|
||||
Roots::null_record_type().initRO(RecordType::null());
|
||||
Roots::null_type_arguments().initRO(TypeArguments::null());
|
||||
Roots::null_closure().initRO(Closure::null());
|
||||
Roots::empty_type_arguments().initRO(TypeArguments::null());
|
||||
Roots::null_abstract_type().initRO(AbstractType::null());
|
||||
Roots::null_compressed_stackmaps().initRO(CompressedStackMaps::null());
|
||||
Roots::bool_true().initRO(Roots::true_obj());
|
||||
Roots::bool_false().initRO(Roots::false_obj());
|
||||
Roots::sentinel().initRO(Roots::sentinel_obj());
|
||||
Roots::unknown_constant().initRO(Roots::unknown_constant_obj());
|
||||
Roots::non_constant().initRO(Roots::non_constant_obj());
|
||||
Roots::optimized_out().initRO(Roots::optimized_out_obj());
|
||||
}
|
||||
|
||||
void Object::InitVtables() {
|
||||
@@ -698,37 +718,12 @@ void Object::InitVtables() {
|
||||
}
|
||||
|
||||
void Object::Init(IsolateGroup* isolate_group) {
|
||||
// Should only be run by the vm isolate.
|
||||
ASSERT(isolate_group == Dart::vm_isolate_group());
|
||||
Heap* heap = isolate_group->heap();
|
||||
Thread* thread = Thread::Current();
|
||||
ASSERT(thread != nullptr);
|
||||
// Ensure lock checks in setters are happy.
|
||||
SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
|
||||
|
||||
InitVtables();
|
||||
|
||||
// Allocate the read only object handles here.
|
||||
Roots::null_object().initRO(Object::null());
|
||||
Roots::null_class().initRO(Class::null());
|
||||
Roots::null_array().initRO(Array::null());
|
||||
Roots::null_string().initRO(String::null());
|
||||
Roots::null_instance().initRO(Instance::null());
|
||||
Roots::null_function().initRO(Function::null());
|
||||
Roots::null_function_type().initRO(FunctionType::null());
|
||||
Roots::null_record_type().initRO(RecordType::null());
|
||||
Roots::null_type_arguments().initRO(TypeArguments::null());
|
||||
Roots::null_closure().initRO(Closure::null());
|
||||
Roots::empty_type_arguments().initRO(TypeArguments::null());
|
||||
Roots::null_abstract_type().initRO(AbstractType::null());
|
||||
Roots::null_compressed_stackmaps().initRO(CompressedStackMaps::null());
|
||||
Roots::bool_true().initRO(Roots::true_obj());
|
||||
Roots::bool_false().initRO(Roots::false_obj());
|
||||
Roots::sentinel().initRO(Roots::sentinel_obj());
|
||||
Roots::unknown_constant().initRO(Roots::unknown_constant_obj());
|
||||
Roots::non_constant().initRO(Roots::non_constant_obj());
|
||||
Roots::optimized_out().initRO(Roots::optimized_out_obj());
|
||||
|
||||
// Initialize the empty array and empty instantiations cache array handles to
|
||||
// null_ in order to be able to check if the empty and zero arrays were
|
||||
// allocated (RAW_NULL is not available).
|
||||
@@ -1058,10 +1053,6 @@ void Object::Init(IsolateGroup* isolate_group) {
|
||||
Roots::empty_type_arguments().SetCanonical();
|
||||
}
|
||||
|
||||
// The VM isolate snapshot object table is initialized to an empty array
|
||||
// as we do not have any VM isolate snapshot at this time.
|
||||
Roots::vm_isolate_snapshot_object_table().initRO(Object::empty_array().ptr());
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kDynamicCid, isolate_group);
|
||||
cls.set_is_abstract();
|
||||
cls.set_num_type_arguments_unsafe(0);
|
||||
@@ -1292,8 +1283,6 @@ void Object::Init(IsolateGroup* isolate_group) {
|
||||
ASSERT(Roots::out_of_memory_error().IsLanguageError());
|
||||
ASSERT(!Roots::unhandled_oom_exception().IsSmi());
|
||||
ASSERT(Roots::unhandled_oom_exception().IsUnhandledException());
|
||||
ASSERT(!Roots::vm_isolate_snapshot_object_table().IsSmi());
|
||||
ASSERT(Roots::vm_isolate_snapshot_object_table().IsArray());
|
||||
ASSERT(!Roots::synthetic_getter_parameter_types().IsSmi());
|
||||
ASSERT(Roots::synthetic_getter_parameter_types().IsArray());
|
||||
ASSERT(!Roots::synthetic_getter_parameter_names().IsSmi());
|
||||
@@ -1331,83 +1320,6 @@ void Object::Init(IsolateGroup* isolate_group) {
|
||||
}
|
||||
|
||||
void Object::FinishInit(IsolateGroup* isolate_group) {
|
||||
// The type testing stubs we initialize in AbstractType objects for the
|
||||
// canonical type of kDynamicCid/kVoidCid need to be set in this
|
||||
// method, which is called after StubCode::InitOnce().
|
||||
Code& code = Code::Handle();
|
||||
|
||||
code = TypeTestingStubGenerator::DefaultCodeForType(Roots::dynamic_type());
|
||||
Roots::dynamic_type().InitializeTypeTestingStubNonAtomic(code);
|
||||
|
||||
code = TypeTestingStubGenerator::DefaultCodeForType(Roots::void_type());
|
||||
Roots::void_type().InitializeTypeTestingStubNonAtomic(code);
|
||||
}
|
||||
|
||||
void Object::Cleanup() {}
|
||||
|
||||
// An object visitor which will mark all visited objects. This is used to
|
||||
// premark all objects in the vm_isolate_ heap. Also precalculates hash
|
||||
// codes so that we can get the identity hash code of objects in the read-
|
||||
// only VM isolate.
|
||||
class FinalizeVMIsolateVisitor : public ObjectVisitor {
|
||||
public:
|
||||
FinalizeVMIsolateVisitor()
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
: counter_(1337)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
void VisitObject(ObjectPtr obj) {
|
||||
// Free list elements should never be marked.
|
||||
ASSERT(!obj->untag()->IsMarked());
|
||||
// No forwarding corpses in the VM isolate.
|
||||
ASSERT(!obj->IsForwardingCorpse());
|
||||
if (!obj->IsFreeListElement()) {
|
||||
obj->untag()->SetMarkBitUnsynchronized();
|
||||
Object::FinalizeReadOnlyObject(obj);
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
// These objects end up in the read-only VM isolate which is shared
|
||||
// between isolates, so we have to prepopulate them with identity hash
|
||||
// codes, since we can't add hash codes later.
|
||||
if (Object::GetCachedHash(obj) == 0) {
|
||||
// Some classes have identity hash codes that depend on their contents,
|
||||
// not per object.
|
||||
ASSERT(!obj->IsStringInstance());
|
||||
if (!obj->IsMint() && !obj->IsDouble()) {
|
||||
counter_ += 2011; // The year Dart was announced and a prime.
|
||||
counter_ &= 0x3fffffff;
|
||||
if (counter_ == 0) counter_++;
|
||||
Object::SetCachedHashIfNotSet(obj, counter_);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (obj->IsClass()) {
|
||||
// Won't be able to update read-only VM isolate classes if implementors
|
||||
// are discovered later. We use kVoidCid instead of kDynamicCid here to
|
||||
// be able to distinguish read-only VM isolate classes during reload.
|
||||
// See ProgramReloadContext::RestoreClassHierarchyInvariants.
|
||||
static_cast<ClassPtr>(obj)->untag()->implementor_cid_ = kVoidCid;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
int32_t counter_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define SET_CLASS_NAME(class_name, name) \
|
||||
cls = table->At(class_name); \
|
||||
cls.set_name(Symbols::name());
|
||||
|
||||
void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
|
||||
// Should only be run by the vm isolate.
|
||||
ASSERT(isolate_group == Dart::vm_isolate_group());
|
||||
|
||||
// Finish initialization of synthetic_getter_parameter_names_ which was
|
||||
// Started in Object::InitOnce()
|
||||
Roots::synthetic_getter_parameter_names().SetAt(0, Symbols::This());
|
||||
@@ -1416,6 +1328,10 @@ void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
|
||||
Class& cls = Class::Handle();
|
||||
ClassTable* table = isolate_group->class_table();
|
||||
|
||||
#define SET_CLASS_NAME(class_name, name) \
|
||||
cls = table->At(class_name); \
|
||||
cls.set_name(Symbols::name());
|
||||
|
||||
SET_CLASS_NAME(kClassCid, Class);
|
||||
SET_CLASS_NAME(kDynamicCid, Dynamic);
|
||||
SET_CLASS_NAME(kVoidCid, Void);
|
||||
@@ -1468,23 +1384,24 @@ void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) {
|
||||
SET_CLASS_NAME(kFreeListElement, FreeListElement);
|
||||
SET_CLASS_NAME(kForwardingCorpse, ForwardingCorpse);
|
||||
|
||||
#undef SET_CLASS_NAME
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
const auto& function =
|
||||
Function::Handle(StubCode::UnknownDartCode().function());
|
||||
function.set_name(Symbols::OptimizedOut());
|
||||
#endif // defined(DART_PRECOMPILER)
|
||||
|
||||
{
|
||||
ASSERT(isolate_group == Dart::vm_isolate_group());
|
||||
Thread* thread = Thread::Current();
|
||||
WritableVMIsolateScope scope(thread);
|
||||
HeapIterationScope iteration(thread);
|
||||
FinalizeVMIsolateVisitor premarker;
|
||||
ASSERT(isolate_group->heap()->UsedInWords(Heap::kNew) == 0);
|
||||
iteration.IterateOldObjectsNoImagePages(&premarker);
|
||||
// Make the VM isolate read-only again after setting all objects as marked.
|
||||
// Note objects in image pages are already pre-marked.
|
||||
}
|
||||
// The type testing stubs we initialize in AbstractType objects for the
|
||||
// canonical type of kDynamicCid/kVoidCid need to be set in this
|
||||
// method, which is called after StubCode::InitOnce().
|
||||
Code& code = Code::Handle();
|
||||
|
||||
code = TypeTestingStubGenerator::DefaultCodeForType(Roots::dynamic_type());
|
||||
Roots::dynamic_type().InitializeTypeTestingStubNonAtomic(code);
|
||||
|
||||
code = TypeTestingStubGenerator::DefaultCodeForType(Roots::void_type());
|
||||
Roots::void_type().InitializeTypeTestingStubNonAtomic(code);
|
||||
}
|
||||
|
||||
void Object::FinalizeReadOnlyObject(ObjectPtr object) {
|
||||
@@ -1532,11 +1449,6 @@ void Object::FinalizeReadOnlyObject(ObjectPtr object) {
|
||||
}
|
||||
}
|
||||
|
||||
void Object::set_vm_isolate_snapshot_object_table(const Array& table) {
|
||||
ASSERT(Isolate::Current() == Dart::vm_isolate());
|
||||
Roots::vm_isolate_snapshot_object_table().initRO(table.ptr());
|
||||
}
|
||||
|
||||
// Make unused space in an object whose type has been transformed safe
|
||||
// for traversing during GC.
|
||||
// The unused part of the transformed object is marked as a FreeListElement
|
||||
@@ -1738,16 +1650,15 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
|
||||
const uint8_t* kernel_buffer,
|
||||
intptr_t kernel_buffer_size) {
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
ASSERT(isolate_group == thread->isolate_group());
|
||||
TIMELINE_DURATION(thread, Isolate, "Object::Init");
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
const bool bootstrapping = false;
|
||||
#else
|
||||
Zone* zone = thread->zone();
|
||||
const bool is_kernel = (kernel_buffer != nullptr);
|
||||
const bool bootstrapping =
|
||||
(Dart::vm_snapshot_kind() == Snapshot::kNone) || is_kernel;
|
||||
const bool bootstrapping = is_kernel;
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME).
|
||||
|
||||
if (bootstrapping) {
|
||||
@@ -1769,7 +1680,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
|
||||
// All RawArray fields will be initialized to an empty array, therefore
|
||||
// initialize array class first.
|
||||
cls = Class::New<Array, RTN::Array>(isolate_group);
|
||||
ASSERT(object_store->array_class() == Class::null());
|
||||
object_store->set_array_class(cls);
|
||||
|
||||
// VM classes that are parameterized (Array, ImmutableArray,
|
||||
@@ -1848,9 +1758,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
|
||||
cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
|
||||
object_store->set_two_byte_string_class(cls);
|
||||
|
||||
// Setup the symbol table for the symbols created in the isolate.
|
||||
Symbols::SetupSymbolTable(isolate_group);
|
||||
|
||||
// Set up the libraries array before initializing the core library.
|
||||
const GrowableObjectArray& libraries =
|
||||
GrowableObjectArray::Handle(zone, GrowableObjectArray::New(Heap::kOld));
|
||||
@@ -2538,174 +2445,10 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
|
||||
// Set up recognized state of all functions (core, math and typed data).
|
||||
MethodRecognizer::InitializeState();
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
} else {
|
||||
// Object::Init version when we are running in a version of dart that has a
|
||||
// full snapshot linked in and an isolate is initialized using the full
|
||||
// snapshot.
|
||||
ObjectStore* object_store = isolate_group->object_store();
|
||||
SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
|
||||
|
||||
Class& cls = Class::Handle(zone);
|
||||
|
||||
// Set up empty classes in the object store, these will get initialized
|
||||
// correctly when we read from the snapshot. This is done to allow
|
||||
// bootstrapping of reading classes from the snapshot. Some classes are not
|
||||
// stored in the object store. Yet we still need to create their Class
|
||||
// object so that they get put into the class_table (as a side effect of
|
||||
// Class::New()).
|
||||
cls = Class::New<Instance, RTN::Instance>(kInstanceCid, isolate_group);
|
||||
object_store->set_object_class(cls);
|
||||
|
||||
cls = Class::New<LibraryPrefix, RTN::LibraryPrefix>(isolate_group);
|
||||
cls = Class::New<Type, RTN::Type>(isolate_group);
|
||||
cls = Class::New<FunctionType, RTN::FunctionType>(isolate_group);
|
||||
cls = Class::New<RecordType, RTN::RecordType>(isolate_group);
|
||||
cls = Class::New<TypeParameter, RTN::TypeParameter>(isolate_group);
|
||||
|
||||
cls = Class::New<Array, RTN::Array>(isolate_group);
|
||||
object_store->set_array_class(cls);
|
||||
|
||||
cls = Class::New<Array, RTN::Array>(kImmutableArrayCid, isolate_group);
|
||||
object_store->set_immutable_array_class(cls);
|
||||
|
||||
cls = Class::New<GrowableObjectArray, RTN::GrowableObjectArray>(
|
||||
isolate_group);
|
||||
object_store->set_growable_object_array_class(cls);
|
||||
|
||||
cls = Class::New<LinkedHashBase, RTN::LinkedHashBase>(
|
||||
kLinkedHashBaseCid, isolate_group, /*register_class=*/true,
|
||||
/*is_abstract=*/true);
|
||||
|
||||
cls = Class::New<Map, RTN::Map>(isolate_group);
|
||||
object_store->set_map_impl_class(cls);
|
||||
|
||||
cls = Class::New<Map, RTN::Map>(kConstMapCid, isolate_group);
|
||||
object_store->set_const_map_impl_class(cls);
|
||||
|
||||
cls = Class::New<Set, RTN::Set>(isolate_group);
|
||||
object_store->set_set_impl_class(cls);
|
||||
|
||||
cls = Class::New<Set, RTN::Set>(kConstSetCid, isolate_group);
|
||||
object_store->set_const_set_impl_class(cls);
|
||||
|
||||
cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
|
||||
object_store->set_float32x4_class(cls);
|
||||
|
||||
cls = Class::New<Int32x4, RTN::Int32x4>(isolate_group);
|
||||
object_store->set_int32x4_class(cls);
|
||||
|
||||
cls = Class::New<Float64x2, RTN::Float64x2>(isolate_group);
|
||||
object_store->set_float64x2_class(cls);
|
||||
|
||||
#define REGISTER_TYPED_DATA_CLASS(clazz) \
|
||||
cls = Class::NewTypedDataClass(kTypedData##clazz##Cid, isolate_group);
|
||||
CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
|
||||
#undef REGISTER_TYPED_DATA_CLASS
|
||||
#define REGISTER_TYPED_DATA_VIEW_CLASS(clazz) \
|
||||
cls = \
|
||||
Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid, isolate_group); \
|
||||
cls = Class::NewUnmodifiableTypedDataViewClass( \
|
||||
kUnmodifiableTypedData##clazz##ViewCid, isolate_group);
|
||||
CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_VIEW_CLASS);
|
||||
#undef REGISTER_TYPED_DATA_VIEW_CLASS
|
||||
cls = Class::NewTypedDataViewClass(kByteDataViewCid, isolate_group);
|
||||
cls = Class::NewUnmodifiableTypedDataViewClass(kUnmodifiableByteDataViewCid,
|
||||
isolate_group);
|
||||
#define REGISTER_EXT_TYPED_DATA_CLASS(clazz) \
|
||||
cls = Class::NewExternalTypedDataClass(kExternalTypedData##clazz##Cid, \
|
||||
isolate_group);
|
||||
CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
|
||||
#undef REGISTER_EXT_TYPED_DATA_CLASS
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kFfiNativeTypeCid, isolate_group);
|
||||
object_store->set_ffi_native_type_class(cls);
|
||||
|
||||
#define REGISTER_FFI_CLASS(clazz) \
|
||||
cls = Class::New<Instance, RTN::Instance>(kFfi##clazz##Cid, isolate_group);
|
||||
CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_CLASS);
|
||||
#undef REGISTER_FFI_CLASS
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kFfiNativeFunctionCid,
|
||||
isolate_group);
|
||||
|
||||
cls = Class::NewPointerClass(kPointerCid, isolate_group);
|
||||
object_store->set_ffi_pointer_class(cls);
|
||||
|
||||
cls = Class::New<DynamicLibrary, RTN::DynamicLibrary>(kDynamicLibraryCid,
|
||||
isolate_group);
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kByteBufferCid, isolate_group,
|
||||
/*register_class=*/false);
|
||||
cls.set_instance_size_in_words(0, 0);
|
||||
isolate_group->class_table()->Register(cls);
|
||||
|
||||
cls = Class::New<Integer, RTN::Integer>(isolate_group);
|
||||
object_store->set_integer_implementation_class(cls);
|
||||
|
||||
cls = Class::New<Smi, RTN::Smi>(isolate_group);
|
||||
object_store->set_smi_class(cls);
|
||||
|
||||
cls = Class::New<Mint, RTN::Mint>(isolate_group);
|
||||
object_store->set_mint_class(cls);
|
||||
|
||||
cls = Class::New<Double, RTN::Double>(isolate_group);
|
||||
object_store->set_double_class(cls);
|
||||
|
||||
cls = Class::New<Closure, RTN::Closure>(isolate_group);
|
||||
object_store->set_closure_class(cls);
|
||||
|
||||
cls = Class::New<Record, RTN::Record>(isolate_group);
|
||||
|
||||
cls = Class::NewStringClass(kOneByteStringCid, isolate_group);
|
||||
object_store->set_one_byte_string_class(cls);
|
||||
|
||||
cls = Class::NewStringClass(kTwoByteStringCid, isolate_group);
|
||||
object_store->set_two_byte_string_class(cls);
|
||||
|
||||
cls = Class::New<Bool, RTN::Bool>(isolate_group);
|
||||
object_store->set_bool_class(cls);
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kNullCid, isolate_group);
|
||||
object_store->set_null_class(cls);
|
||||
|
||||
cls = Class::New<Instance, RTN::Instance>(kNeverCid, isolate_group);
|
||||
object_store->set_never_class(cls);
|
||||
|
||||
cls = Class::New<Capability, RTN::Capability>(isolate_group);
|
||||
cls = Class::New<ReceivePort, RTN::ReceivePort>(isolate_group);
|
||||
cls = Class::New<SendPort, RTN::SendPort>(isolate_group);
|
||||
cls = Class::New<StackTrace, RTN::StackTrace>(isolate_group);
|
||||
cls = Class::New<SuspendState, RTN::SuspendState>(isolate_group);
|
||||
cls = Class::New<RegExp, RTN::RegExp>(isolate_group);
|
||||
cls = Class::New<Number, RTN::Number>(isolate_group);
|
||||
|
||||
cls = Class::New<WeakProperty, RTN::WeakProperty>(isolate_group);
|
||||
object_store->set_weak_property_class(cls);
|
||||
cls = Class::New<WeakReference, RTN::WeakReference>(isolate_group);
|
||||
object_store->set_weak_reference_class(cls);
|
||||
cls = Class::New<Finalizer, RTN::Finalizer>(isolate_group);
|
||||
object_store->set_finalizer_class(cls);
|
||||
cls = Class::New<NativeFinalizer, RTN::NativeFinalizer>(isolate_group);
|
||||
object_store->set_native_finalizer_class(cls);
|
||||
cls = Class::New<FinalizerEntry, RTN::FinalizerEntry>(isolate_group);
|
||||
object_store->set_finalizer_entry_class(cls);
|
||||
|
||||
cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
|
||||
cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
|
||||
cls = Class::New<FutureOr, RTN::FutureOr>(isolate_group);
|
||||
object_store->set_future_or_class(cls);
|
||||
cls = Class::New<TransferableTypedData, RTN::TransferableTypedData>(
|
||||
isolate_group);
|
||||
}
|
||||
return Error::null();
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
bool Object::InVMIsolateHeap() const {
|
||||
return ptr()->untag()->InVMIsolateHeap();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void Object::Print() const {
|
||||
THR_Print("%s\n", ToCString());
|
||||
}
|
||||
@@ -4617,7 +4360,6 @@ class CHACodeArray : public WeakCodeReferences {
|
||||
cls_(cls) {}
|
||||
|
||||
virtual void UpdateArrayTo(const WeakArray& value) {
|
||||
// TODO(fschneider): Fails for classes in the VM isolate.
|
||||
cls_.set_dependent_code(value);
|
||||
}
|
||||
|
||||
@@ -8393,9 +8135,7 @@ void Function::AttachBytecode(const Bytecode& value) const {
|
||||
ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
|
||||
ASSERT(!value.IsNull());
|
||||
// Finish setting up code before activating it.
|
||||
if (!value.InVMIsolateHeap()) {
|
||||
value.set_function(*this);
|
||||
}
|
||||
value.set_function(*this);
|
||||
ASSERT(untag()->ic_data_array_or_bytecode() == Object::null());
|
||||
untag()->set_ic_data_array_or_bytecode(value.ptr());
|
||||
|
||||
@@ -11876,8 +11616,7 @@ bool Function::CheckSourceFingerprint(int32_t fp, const char* kind) const {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IsolateGroup::Current()->obfuscate() || FLAG_precompiled_mode ||
|
||||
(Dart::vm_snapshot_kind() != Snapshot::kNone)) {
|
||||
if (IsolateGroup::Current()->obfuscate() || FLAG_precompiled_mode) {
|
||||
return true; // The kernel structure has been altered, skip checking.
|
||||
}
|
||||
|
||||
@@ -17167,7 +16906,6 @@ const char* ICData::ToCString() const {
|
||||
FunctionPtr ICData::Owner() const {
|
||||
Object& obj = Object::Handle(untag()->owner());
|
||||
if (obj.IsNull()) {
|
||||
ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
|
||||
return Function::null();
|
||||
} else if (obj.IsFunction()) {
|
||||
return Function::Cast(obj).ptr();
|
||||
@@ -17977,8 +17715,6 @@ void ICData::Init() {
|
||||
ICData::NewNonCachedEmptyICDataArray(1, true));
|
||||
}
|
||||
|
||||
void ICData::Cleanup() {}
|
||||
|
||||
ArrayPtr ICData::NewNonCachedEmptyICDataArray(intptr_t num_args_tested,
|
||||
bool tracking_exactness) {
|
||||
// IC data array must be null terminated (sentinel entry).
|
||||
@@ -18226,9 +17962,6 @@ ObjectPtr WeakSerializationReference::New(const Object& target,
|
||||
// Note that we _do_ wrap Smis if requested. Smis are serialized in the Mint
|
||||
// cluster, and so dropping them if not strongly referenced saves space in
|
||||
// the snapshot.
|
||||
if (target.ptr()->IsHeapObject() && target.InVMIsolateHeap()) {
|
||||
return target.ptr();
|
||||
}
|
||||
// If the target is a WSR that already uses the replacement, then return it.
|
||||
if (target.IsWeakSerializationReference() &&
|
||||
WeakSerializationReference::Cast(target).replacement() ==
|
||||
@@ -18458,7 +18191,6 @@ TypedDataPtr Code::GetDeoptInfoAtPc(uword pc,
|
||||
ICData::DeoptReasonId* deopt_reason,
|
||||
uint32_t* deopt_flags) const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
|
||||
return TypedData::null();
|
||||
#else
|
||||
ASSERT(is_optimized());
|
||||
@@ -18466,7 +18198,6 @@ TypedDataPtr Code::GetDeoptInfoAtPc(uword pc,
|
||||
uword code_entry = instrs.PayloadStart();
|
||||
const Array& table = Array::Handle(deopt_info_array());
|
||||
if (table.IsNull()) {
|
||||
ASSERT(Dart::vm_snapshot_kind() == Snapshot::kFullAOT);
|
||||
return TypedData::null();
|
||||
}
|
||||
// Linear search for the PC offset matching the target PC.
|
||||
@@ -18630,7 +18361,7 @@ void Code::set_comments(const CodeComments& comments) const {
|
||||
ASSERT(wrapper.comments_.IsOld());
|
||||
untag()->set_comments(wrapper.comments_.ptr());
|
||||
#else
|
||||
if (FLAG_code_comments && comments.Length() > 0) {
|
||||
if (IsolateGroup::Current()->code_comments() && comments.Length() > 0) {
|
||||
Thread::Current()->heap()->SetPeer(ptr(), new MallocCodeComments(comments));
|
||||
} else {
|
||||
Thread::Current()->heap()->SetPeer(ptr(), nullptr);
|
||||
@@ -18930,7 +18661,6 @@ CodePtr Code::FindCode(uword pc, int64_t timestamp) {
|
||||
|
||||
HeapIterationScope iteration(Thread::Current());
|
||||
SlowFindCodeVisitor visitor(pc, timestamp);
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
iteration.IterateOldObjectsNoImagePages(&visitor);
|
||||
return visitor.result();
|
||||
}
|
||||
@@ -18961,7 +18691,6 @@ CodePtr Code::FindCodeUnsafe(uword pc) {
|
||||
old_space->MakeIterable();
|
||||
FindCodeUnsafeVisitor visitor(pc);
|
||||
old_space->VisitObjectsUnsafe(&visitor);
|
||||
Dart::vm_isolate_group()->heap()->old_space()->VisitObjectsUnsafe(&visitor);
|
||||
return visitor.result();
|
||||
}
|
||||
|
||||
@@ -19094,8 +18823,8 @@ bool Code::IsFunctionCode() const {
|
||||
}
|
||||
|
||||
bool Code::IsUnknownDartCode(CodePtr code) {
|
||||
return StubCode::HasBeenInitialized() &&
|
||||
(code == StubCode::UnknownDartCode().ptr());
|
||||
ASSERT(StubCode::UnknownDartCode().ptr() != nullptr);
|
||||
return code == StubCode::UnknownDartCode().ptr();
|
||||
}
|
||||
|
||||
void Code::DisableDartCode() const {
|
||||
@@ -19442,7 +19171,6 @@ BytecodePtr Bytecode::FindBytecode(uword pc) {
|
||||
|
||||
HeapIterationScope iteration(Thread::Current());
|
||||
SlowFindBytecodeVisitor visitor(pc);
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
iteration.IterateOldObjectsNoImagePages(&visitor);
|
||||
return visitor.result();
|
||||
#else
|
||||
@@ -21430,7 +21158,6 @@ InstancePtr Instance::CanonicalizeLocked(Thread* thread) const {
|
||||
return result.ptr();
|
||||
}
|
||||
if (IsNew()) {
|
||||
ASSERT((thread->isolate() == Dart::vm_isolate()) || !InVMIsolateHeap());
|
||||
// Create a canonical object in old space.
|
||||
result ^= Object::Clone(*this, Heap::kOld);
|
||||
} else {
|
||||
@@ -23177,8 +22904,6 @@ AbstractTypePtr Type::Canonicalize(Thread* thread) const {
|
||||
ASSERT(!cls.IsNullClass() || IsNullable());
|
||||
Type& type = Type::Handle(zone, cls.declaration_type());
|
||||
if (type.IsNull()) {
|
||||
ASSERT(!cls.ptr()->untag()->InVMIsolateHeap() ||
|
||||
(isolate_group == Dart::vm_isolate_group()));
|
||||
// Canonicalize the type arguments of the supertype, if any.
|
||||
TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
||||
type_args = type_args.Canonicalize(thread);
|
||||
@@ -23396,6 +23121,7 @@ void Type::set_type_class_id(intptr_t id) const {
|
||||
ASSERT(!ClassTable::IsTopLevelCid(id));
|
||||
ASSERT(id != kIllegalCid);
|
||||
ASSERT(!IsInternalOnlyClassId(id));
|
||||
ASSERT(id >= kInstanceCid);
|
||||
untag()->set_type_class_id(id);
|
||||
}
|
||||
|
||||
@@ -25222,10 +24948,6 @@ OneByteStringPtr OneByteString::EscapeSpecialCharacters(const String& str) {
|
||||
}
|
||||
|
||||
OneByteStringPtr OneByteString::New(intptr_t len, Heap::Space space) {
|
||||
ASSERT((IsolateGroup::Current() == Dart::vm_isolate_group()) ||
|
||||
((IsolateGroup::Current()->object_store() != nullptr) &&
|
||||
(IsolateGroup::Current()->object_store()->one_byte_string_class() !=
|
||||
Class::null())));
|
||||
if (len < 0 || len > kMaxElements) {
|
||||
// This should be caught before we reach here.
|
||||
FATAL("Fatal error in OneByteString::New: invalid len %" Pd "\n", len);
|
||||
@@ -26999,8 +26721,7 @@ static bool TryPrintNonSymbolicStackFrameBodyRelative(
|
||||
image.instructions_relocated_address();
|
||||
buffer->Printf(" virt %" Pp "", relocated_section_start + offset);
|
||||
}
|
||||
const char* symbol = vm ? kVmSnapshotInstructionsAsmSymbol
|
||||
: kIsolateSnapshotInstructionsAsmSymbol;
|
||||
const char* symbol = kSnapshotTextAsmSymbol;
|
||||
buffer->Printf(" %s+0x%" Px "\n", symbol, offset);
|
||||
return true;
|
||||
}
|
||||
@@ -27012,12 +26733,6 @@ static void PrintNonSymbolicStackFrameBody(BaseTextBuffer* buffer,
|
||||
uword vm_instructions,
|
||||
const Array& loading_units,
|
||||
LoadingUnit* unit) {
|
||||
if (TryPrintNonSymbolicStackFrameBodyRelative(buffer, call_addr,
|
||||
vm_instructions,
|
||||
/*vm=*/true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loading_units.IsNull()) {
|
||||
// All non-VM stack frames should include the loading unit id.
|
||||
const intptr_t unit_count = loading_units.Length();
|
||||
@@ -27164,15 +26879,15 @@ const char* StackTrace::ToCString() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
GrowableArray<void*> addresses(10);
|
||||
const bool have_footnote_callback =
|
||||
FLAG_dwarf_stack_traces_mode &&
|
||||
T->isolate_group()->dwarf_stack_traces() &&
|
||||
Dart::dwarf_stacktrace_footnote_callback() != nullptr;
|
||||
#endif
|
||||
|
||||
ZoneTextBuffer buffer(zone, 1024);
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
auto const isolate_instructions = reinterpret_cast<uword>(
|
||||
T->isolate_group()->source()->snapshot_instructions);
|
||||
auto const isolate_instructions =
|
||||
reinterpret_cast<uword>(T->isolate_group()->source()->snapshot_text);
|
||||
#if defined(DEBUG)
|
||||
if (!loading_units.IsNull()) {
|
||||
*unit ^= loading_units.At(LoadingUnit::kRootId);
|
||||
@@ -27182,9 +26897,7 @@ const char* StackTrace::ToCString() const {
|
||||
isolate_instructions);
|
||||
}
|
||||
#endif
|
||||
auto const vm_instructions = reinterpret_cast<uword>(
|
||||
Dart::vm_isolate_group()->source()->snapshot_instructions);
|
||||
if (FLAG_dwarf_stack_traces_mode) {
|
||||
if (T->isolate_group()->dwarf_stack_traces()) {
|
||||
// This prologue imitates Android's debuggerd to make it possible to paste
|
||||
// the stack trace into ndk-stack.
|
||||
buffer.Printf(
|
||||
@@ -27223,10 +26936,9 @@ const char* StackTrace::ToCString() const {
|
||||
// as the VM and isolate may be loaded from different snapshot images.
|
||||
const uword isolate_dso_base = OS::GetAppDSOBase(isolate_instructions);
|
||||
buffer.Printf("isolate_dso_base: %" Px "", isolate_dso_base);
|
||||
const uword vm_dso_base = OS::GetAppDSOBase(vm_instructions);
|
||||
buffer.Printf(", vm_dso_base: %" Px "\n", vm_dso_base);
|
||||
buffer.Printf(", vm_dso_base: 0\n");
|
||||
buffer.Printf("isolate_instructions: %" Px "", isolate_instructions);
|
||||
buffer.Printf(", vm_instructions: %" Px "\n", vm_instructions);
|
||||
buffer.Printf(", vm_instructions: 0\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27306,7 +27018,7 @@ const char* StackTrace::ToCString() const {
|
||||
// pc_offset by 1 for such cases.
|
||||
const uword call_addr = pc - 1;
|
||||
|
||||
if (FLAG_dwarf_stack_traces_mode) {
|
||||
if (T->isolate_group()->dwarf_stack_traces()) {
|
||||
if (have_footnote_callback) {
|
||||
addresses.Add(reinterpret_cast<void*>(call_addr));
|
||||
}
|
||||
@@ -27315,7 +27027,8 @@ const char* StackTrace::ToCString() const {
|
||||
// prints call addresses instead of return addresses.
|
||||
buffer.Printf(" #%02" Pd " abs %" Pp "", frame_index, call_addr);
|
||||
PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
|
||||
vm_instructions, loading_units, unit);
|
||||
/*vm_instructions=*/0, loading_units,
|
||||
unit);
|
||||
frame_index++;
|
||||
continue;
|
||||
}
|
||||
@@ -27327,7 +27040,8 @@ const char* StackTrace::ToCString() const {
|
||||
// non-symbolic stack traces.
|
||||
PrintSymbolicStackFrameIndex(&buffer, frame_index);
|
||||
PrintNonSymbolicStackFrameBody(&buffer, call_addr, isolate_instructions,
|
||||
vm_instructions, loading_units, unit);
|
||||
/*vm_instructions=*/0, loading_units,
|
||||
unit);
|
||||
frame_index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
+1
-12
@@ -454,11 +454,6 @@ class Object {
|
||||
|
||||
bool IsNew() const { return ptr()->IsNewObject(); }
|
||||
bool IsOld() const { return ptr()->IsOldObject(); }
|
||||
#if defined(DEBUG)
|
||||
bool InVMIsolateHeap() const;
|
||||
#else
|
||||
bool InVMIsolateHeap() const { return ptr()->untag()->InVMIsolateHeap(); }
|
||||
#endif // DEBUG
|
||||
|
||||
// Print the object on stdout for debugging.
|
||||
void Print() const;
|
||||
@@ -574,7 +569,6 @@ class Object {
|
||||
V(LanguageError, no_debuggable_code_error) \
|
||||
V(LanguageError, out_of_memory_error) \
|
||||
V(UnhandledException, unhandled_oom_exception) \
|
||||
V(Array, vm_isolate_snapshot_object_table) \
|
||||
V(Type, dynamic_type) \
|
||||
V(Type, void_type) \
|
||||
V(AbstractType, null_abstract_type) \
|
||||
@@ -586,9 +580,6 @@ class Object {
|
||||
SHARED_READONLY_HANDLES_LIST(DEFINE_SHARED_READONLY_HANDLE_GETTER)
|
||||
#undef DEFINE_SHARED_READONLY_HANDLE_GETTER
|
||||
|
||||
static void set_vm_isolate_snapshot_object_table(const Array& table);
|
||||
|
||||
// Initialize the VM isolate.
|
||||
static void InitNullAndBool(IsolateGroup* isolate_group);
|
||||
static void Init(IsolateGroup* isolate_group);
|
||||
static void InitVtables();
|
||||
@@ -687,7 +678,7 @@ class Object {
|
||||
friend ObjectPtr AllocateObject(intptr_t, intptr_t, intptr_t);
|
||||
|
||||
// Used for extracting the C++ vtable during bringup.
|
||||
Object() : ptr_(Roots::null_obj()) {}
|
||||
Object() : ptr_(nullptr) {}
|
||||
|
||||
uword raw_value() const { return static_cast<uword>(ptr()); }
|
||||
|
||||
@@ -6954,7 +6945,6 @@ class Code : public Object {
|
||||
uword PayloadStart() const { return PayloadStartOf(ptr()); }
|
||||
static uword PayloadStartOf(const CodePtr code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (IsUnknownDartCode(code)) return 0;
|
||||
const uword entry_offset = HasMonomorphicEntry(code)
|
||||
? Instructions::kPolymorphicEntryOffsetAOT
|
||||
: 0;
|
||||
@@ -7026,7 +7016,6 @@ class Code : public Object {
|
||||
uword Size() const { return PayloadSizeOf(ptr()); }
|
||||
static uword PayloadSizeOf(const CodePtr code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (IsUnknownDartCode(code)) return kUwordMax;
|
||||
return code->untag()->instructions_length_;
|
||||
#else
|
||||
auto instr = InstructionsOf(code);
|
||||
|
||||
@@ -213,7 +213,7 @@ class ObjectGraph::Stack : public ObjectPointerVisitor {
|
||||
#endif
|
||||
|
||||
void Visit(void* ptr, ObjectPtr obj) {
|
||||
if (obj->IsHeapObject() && !obj->untag()->InVMIsolateHeap() &&
|
||||
if (obj->IsHeapObject() &&
|
||||
object_ids_->GetValueExclusive(obj) == 0) { // not visited yet
|
||||
if (!include_vm_objects_ && !IsUserClass(obj->GetClassIdOfHeapObject())) {
|
||||
return;
|
||||
@@ -408,11 +408,7 @@ static void IterateUserFields(ObjectPointerVisitor* visitor) {
|
||||
visitor->clear_gc_root_type();
|
||||
}
|
||||
|
||||
ObjectGraph::ObjectGraph(Thread* thread) : ThreadStackResource(thread) {
|
||||
// The VM isolate has all its objects pre-marked, so iterating over it
|
||||
// would be a no-op.
|
||||
ASSERT(thread->isolate() != Dart::vm_isolate());
|
||||
}
|
||||
ObjectGraph::ObjectGraph(Thread* thread) : ThreadStackResource(thread) {}
|
||||
|
||||
ObjectGraph::~ObjectGraph() {}
|
||||
|
||||
@@ -866,15 +862,7 @@ void HeapSnapshotWriter::Flush(bool last) {
|
||||
void HeapSnapshotWriter::SetupImagePageBoundaries() {
|
||||
MallocGrowableArray<ImagePageRange> ranges(4);
|
||||
|
||||
Page* image_page =
|
||||
Dart::vm_isolate_group()->heap()->old_space()->image_pages_;
|
||||
while (image_page != nullptr) {
|
||||
ImagePageRange range = {image_page->object_start(),
|
||||
image_page->object_end()};
|
||||
ranges.Add(range);
|
||||
image_page = image_page->next();
|
||||
}
|
||||
image_page = isolate_group()->heap()->old_space()->image_pages_;
|
||||
Page* image_page = isolate_group()->heap()->old_space()->image_pages_;
|
||||
while (image_page != nullptr) {
|
||||
ImagePageRange range = {image_page->object_start(),
|
||||
image_page->object_end()};
|
||||
@@ -1145,7 +1133,7 @@ class Pass2Visitor : public ObjectVisitor,
|
||||
|
||||
intptr_t cid = obj->GetClassIdOfHeapObject();
|
||||
writer_->WriteUnsigned(cid + kNumExtraCids);
|
||||
writer_->WriteUnsigned(discount_sizes_ ? 0 : obj->untag()->HeapSize());
|
||||
writer_->WriteUnsigned(obj->untag()->HeapSize());
|
||||
|
||||
if (cid == kNullCid) {
|
||||
writer_->WriteUnsigned(kNullData);
|
||||
@@ -1294,8 +1282,6 @@ class Pass2Visitor : public ObjectVisitor,
|
||||
}
|
||||
}
|
||||
|
||||
void set_discount_sizes(bool value) { discount_sizes_ = value; }
|
||||
|
||||
void DoCount() {
|
||||
writing_ = false;
|
||||
counted_ = 0;
|
||||
@@ -1376,7 +1362,6 @@ class Pass2Visitor : public ObjectVisitor,
|
||||
intptr_t counted_ = 0;
|
||||
intptr_t written_ = 0;
|
||||
intptr_t total_ = 0;
|
||||
bool discount_sizes_ = false;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Pass2Visitor);
|
||||
};
|
||||
@@ -1711,7 +1696,6 @@ void HeapSnapshotWriter::Write() {
|
||||
CountReferences(num_isolates); // Root -> Isolate
|
||||
|
||||
// Heap objects.
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
iteration.IterateObjects(&visitor);
|
||||
|
||||
// External properties.
|
||||
@@ -1787,9 +1771,6 @@ void HeapSnapshotWriter::Write() {
|
||||
/*at_safepoint=*/true);
|
||||
|
||||
// Heap objects.
|
||||
visitor.set_discount_sizes(true);
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
visitor.set_discount_sizes(false);
|
||||
iteration.IterateObjects(&visitor);
|
||||
|
||||
// Smis.
|
||||
@@ -1823,7 +1804,6 @@ void HeapSnapshotWriter::Write() {
|
||||
/*at_safepoint=*/true);
|
||||
|
||||
// Handle visit rest of the objects.
|
||||
iteration.IterateVMIsolateObjects(&visitor);
|
||||
iteration.IterateObjects(&visitor);
|
||||
for (SmiPtr smi : smis_) {
|
||||
USE(smi);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user