mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] Add --print-object-layout-to option to gen_snapshot
This option dumps offsets of Dart fields and sizes of Dart instances into the specified file in JSON format. Could be useful for debugging or memory usage investigations. Typical output: {"class":"_JsonUtf8Parser","size":80,"fields":[{"field":"emptyChunk","static":true},{"field":"decoder","offset":56},{"field":"chunk","offset":64},{"field":"chunkEnd","offset":72}]} TEST=runtime/tests/vm/dart/print_object_layout_test.dart Fixes https://github.com/dart-lang/sdk/issues/47892 Change-Id: I0b2f7ed9e4991e5fcd18517d5a06aa826c6d7125 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/223662 Reviewed-by: Dan Field <dnfield@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
36c051687c
commit
591b2bd724
25
runtime/tests/vm/dart/print_object_layout_script.dart
Normal file
25
runtime/tests/vm/dart/print_object_layout_script.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Test script for print_object_layout_test.dart
|
||||
|
||||
class ClassA {
|
||||
String fieldA1 = 'a';
|
||||
int fieldA2 = 1;
|
||||
}
|
||||
|
||||
class ClassB extends ClassA {
|
||||
String fieldB1 = 'b';
|
||||
int fieldB2 = 2;
|
||||
int unusedB3 = 3;
|
||||
static int staticB4 = 4;
|
||||
}
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
useFields(ClassB obj) =>
|
||||
"${obj.fieldA1}${obj.fieldA2}${obj.fieldB1}${obj.fieldB2}${ClassB.staticB4}";
|
||||
|
||||
main() {
|
||||
useFields(ClassB());
|
||||
}
|
92
runtime/tests/vm/dart/print_object_layout_test.dart
Normal file
92
runtime/tests/vm/dart/print_object_layout_test.dart
Normal file
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// OtherResources=print_object_layout_script.dart
|
||||
|
||||
// Test for --print-object-layout-to option of gen_snapshot.
|
||||
|
||||
import 'dart:convert' show jsonDecode;
|
||||
import 'dart:math' show max;
|
||||
import 'dart:io' show File, Platform;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'snapshot_test_helper.dart';
|
||||
|
||||
verifyObjectLayout(String path) {
|
||||
final classes = jsonDecode(File(path).readAsStringSync());
|
||||
var sizeA, fieldsA;
|
||||
var sizeB, fieldsB;
|
||||
for (var cls in classes) {
|
||||
if (cls['class'] == 'ClassA') {
|
||||
sizeA = cls['size'].toInt();
|
||||
fieldsA = cls['fields'];
|
||||
print(cls);
|
||||
} else if (cls['class'] == 'ClassB') {
|
||||
sizeB = cls['size'].toInt();
|
||||
fieldsB = cls['fields'];
|
||||
print(cls);
|
||||
}
|
||||
}
|
||||
Expect.isNotNull(sizeA);
|
||||
Expect.isTrue(sizeA > 0);
|
||||
Expect.isTrue(fieldsA.length == 2);
|
||||
int maxOffsetA = 0;
|
||||
for (var field in fieldsA) {
|
||||
String fieldName = field['field'];
|
||||
Expect.isTrue(fieldName == 'fieldA1' || fieldName == 'fieldA2');
|
||||
int offset = field['offset'].toInt();
|
||||
Expect.isTrue((offset > 0) && (offset < sizeA));
|
||||
maxOffsetA = max(offset, maxOffsetA);
|
||||
}
|
||||
|
||||
Expect.isNotNull(sizeB);
|
||||
Expect.isTrue(sizeB > 0);
|
||||
Expect.isTrue(sizeA < sizeB);
|
||||
Expect.isTrue(fieldsB.length == 3);
|
||||
for (var field in fieldsB) {
|
||||
String fieldName = field['field'];
|
||||
if (fieldName == 'staticB4') {
|
||||
Expect.isTrue(field['static']);
|
||||
} else {
|
||||
Expect.isTrue(fieldName == 'fieldB1' || fieldName == 'fieldB2');
|
||||
int offset = field['offset'].toInt();
|
||||
Expect.isTrue((offset > 0) && (offset < sizeB));
|
||||
Expect.isTrue(offset > maxOffsetA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main() async {
|
||||
// We don't have access to the SDK on Android.
|
||||
if (Platform.isAndroid) {
|
||||
print('Skipping test on Android');
|
||||
return;
|
||||
}
|
||||
|
||||
final testScriptUri =
|
||||
Platform.script.resolve('print_object_layout_script.dart');
|
||||
|
||||
await withTempDir((String temp) async {
|
||||
final appDillPath = path.join(temp, 'app.dill');
|
||||
final snapshotPath = path.join(temp, 'aot.snapshot');
|
||||
final objectLayoutPath = path.join(temp, 'layout.json');
|
||||
|
||||
await runGenKernel('BUILD DILL FILE', [
|
||||
'--aot',
|
||||
'--link-platform',
|
||||
'--output=$appDillPath',
|
||||
testScriptUri.toFilePath(),
|
||||
]);
|
||||
|
||||
await runGenSnapshot('GENERATE SNAPSHOT', [
|
||||
'--snapshot-kind=app-aot-elf',
|
||||
'--elf=$snapshotPath',
|
||||
'--print-object-layout-to=$objectLayoutPath',
|
||||
appDillPath,
|
||||
]);
|
||||
|
||||
verifyObjectLayout(objectLayoutPath);
|
||||
});
|
||||
}
|
27
runtime/tests/vm/dart_2/print_object_layout_script.dart
Normal file
27
runtime/tests/vm/dart_2/print_object_layout_script.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
// Test script for print_object_layout_test.dart
|
||||
|
||||
class ClassA {
|
||||
String fieldA1 = 'a';
|
||||
int fieldA2 = 1;
|
||||
}
|
||||
|
||||
class ClassB extends ClassA {
|
||||
String fieldB1 = 'b';
|
||||
int fieldB2 = 2;
|
||||
int unusedB3 = 3;
|
||||
static int staticB4 = 4;
|
||||
}
|
||||
|
||||
@pragma('vm:never-inline')
|
||||
useFields(ClassB obj) =>
|
||||
"${obj.fieldA1}${obj.fieldA2}${obj.fieldB1}${obj.fieldB2}${ClassB.staticB4}";
|
||||
|
||||
main() {
|
||||
useFields(ClassB());
|
||||
}
|
94
runtime/tests/vm/dart_2/print_object_layout_test.dart
Normal file
94
runtime/tests/vm/dart_2/print_object_layout_test.dart
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
// OtherResources=print_object_layout_script.dart
|
||||
|
||||
// Test for --print-object-layout-to option of gen_snapshot.
|
||||
|
||||
import 'dart:convert' show jsonDecode;
|
||||
import 'dart:math' show max;
|
||||
import 'dart:io' show File, Platform;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'snapshot_test_helper.dart';
|
||||
|
||||
verifyObjectLayout(String path) {
|
||||
final classes = jsonDecode(File(path).readAsStringSync());
|
||||
var sizeA, fieldsA;
|
||||
var sizeB, fieldsB;
|
||||
for (var cls in classes) {
|
||||
if (cls['class'] == 'ClassA') {
|
||||
sizeA = cls['size'].toInt();
|
||||
fieldsA = cls['fields'];
|
||||
print(cls);
|
||||
} else if (cls['class'] == 'ClassB') {
|
||||
sizeB = cls['size'].toInt();
|
||||
fieldsB = cls['fields'];
|
||||
print(cls);
|
||||
}
|
||||
}
|
||||
Expect.isNotNull(sizeA);
|
||||
Expect.isTrue(sizeA > 0);
|
||||
Expect.isTrue(fieldsA.length == 2);
|
||||
int maxOffsetA = 0;
|
||||
for (var field in fieldsA) {
|
||||
String fieldName = field['field'];
|
||||
Expect.isTrue(fieldName == 'fieldA1' || fieldName == 'fieldA2');
|
||||
int offset = field['offset'].toInt();
|
||||
Expect.isTrue((offset > 0) && (offset < sizeA));
|
||||
maxOffsetA = max(offset, maxOffsetA);
|
||||
}
|
||||
|
||||
Expect.isNotNull(sizeB);
|
||||
Expect.isTrue(sizeB > 0);
|
||||
Expect.isTrue(sizeA < sizeB);
|
||||
Expect.isTrue(fieldsB.length == 3);
|
||||
for (var field in fieldsB) {
|
||||
String fieldName = field['field'];
|
||||
if (fieldName == 'staticB4') {
|
||||
Expect.isTrue(field['static']);
|
||||
} else {
|
||||
Expect.isTrue(fieldName == 'fieldB1' || fieldName == 'fieldB2');
|
||||
int offset = field['offset'].toInt();
|
||||
Expect.isTrue((offset > 0) && (offset < sizeB));
|
||||
Expect.isTrue(offset > maxOffsetA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main() async {
|
||||
// We don't have access to the SDK on Android.
|
||||
if (Platform.isAndroid) {
|
||||
print('Skipping test on Android');
|
||||
return;
|
||||
}
|
||||
|
||||
final testScriptUri =
|
||||
Platform.script.resolve('print_object_layout_script.dart');
|
||||
|
||||
await withTempDir((String temp) async {
|
||||
final appDillPath = path.join(temp, 'app.dill');
|
||||
final snapshotPath = path.join(temp, 'aot.snapshot');
|
||||
final objectLayoutPath = path.join(temp, 'layout.json');
|
||||
|
||||
await runGenKernel('BUILD DILL FILE', [
|
||||
'--aot',
|
||||
'--link-platform',
|
||||
'--output=$appDillPath',
|
||||
testScriptUri.toFilePath(),
|
||||
]);
|
||||
|
||||
await runGenSnapshot('GENERATE SNAPSHOT', [
|
||||
'--snapshot-kind=app-aot-elf',
|
||||
'--elf=$snapshotPath',
|
||||
'--print-object-layout-to=$objectLayoutPath',
|
||||
appDillPath,
|
||||
]);
|
||||
|
||||
verifyObjectLayout(objectLayoutPath);
|
||||
});
|
||||
}
|
|
@ -20,6 +20,7 @@ dart/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
|
|||
dart/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
|
||||
dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/print_object_layout_test: Pass, Slow # Spawns several subprocesses
|
||||
dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
|
||||
dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
|
@ -32,6 +33,7 @@ dart_2/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
|
|||
dart_2/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
|
||||
dart_2/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
|
||||
dart_2/print_object_layout_test: Pass, Slow # Spawns several subprocesses
|
||||
dart_2/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
dart_2/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
|
||||
dart_2/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
|
||||
|
@ -55,10 +57,12 @@ dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
|
|||
dart/kernel_determinism_test: SkipSlow
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart/print_object_layout_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart_2/appjit*: SkipByDesign # Test needs to a particular opt-counter value
|
||||
dart_2/kernel_determinism_test: SkipSlow
|
||||
dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
dart_2/print_object_layout_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
|
||||
|
||||
[ $builder_tag == tsan ]
|
||||
dart/appjit_cha_deopt_test: SkipSlow
|
||||
|
@ -127,12 +131,14 @@ dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimi
|
|||
dart/b162922506_test: SkipSlow # Generates very large input file
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/print_object_layout_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
|
||||
dart/type_casts_with_null_safety_autodetection_test: Pass, Slow # Very slow in debug mode, uses --optimization-counter-threshold=10
|
||||
dart_2/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
|
||||
dart_2/b162922506_test: SkipSlow # Generates very large input file
|
||||
dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart_2/print_object_layout_test: SkipSlow # gen_kernel is too slow in debug mode
|
||||
dart_2/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
|
||||
|
||||
[ $mode == product ]
|
||||
|
@ -245,12 +251,14 @@ dart/b162922506_test: SkipSlow # Generates large input file
|
|||
dart/data_uri_spawn_test: Skip # Please triage.
|
||||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/print_object_layout_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart/snapshot_version_test: RuntimeError # Please triage.
|
||||
dart_2/appjit*: SkipSlow # DFE too slow
|
||||
dart_2/b162922506_test: SkipSlow # Generates large input file
|
||||
dart_2/data_uri_spawn_test: Skip # Please triage.
|
||||
dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart_2/print_object_layout_test: SkipSlow # gen_kernel is too slow on simulated architectures
|
||||
dart_2/snapshot_version_test: RuntimeError # Please triage.
|
||||
|
||||
[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
|
||||
|
@ -264,6 +272,7 @@ dart/appjit*: SkipByDesign # Test needs to run from source
|
|||
dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
|
||||
dart/minimal_kernel_test: SkipByDesign # Test needs to run from source
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
|
||||
dart/print_object_layout_test: SkipByDesign # Test needs to run from source
|
||||
dart/regress_44026_test: SkipByDesign # Test needs to run from source
|
||||
dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
|
||||
dart/type_casts_with_null_safety_autodetection_test: SkipByDesign # Test needs to run from source
|
||||
|
@ -271,6 +280,7 @@ dart_2/appjit*: SkipByDesign # Test needs to run from source
|
|||
dart_2/kernel_determinism_test: SkipByDesign # Test needs to run from source
|
||||
dart_2/minimal_kernel_test: SkipByDesign # Test needs to run from source
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
|
||||
dart_2/print_object_layout_test: SkipByDesign # Test needs to run from source
|
||||
dart_2/snapshot_depfile_test: SkipByDesign # Test needs to run from source
|
||||
|
||||
[ $compiler == dartkp && ($arch == simarm || $arch == simarm64 || $arch == simarm64c) ]
|
||||
|
@ -430,6 +440,7 @@ dart/issue_31959_31960_test: SkipSlow
|
|||
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/print_flow_graph_determinism_test: SkipSlow
|
||||
dart/print_object_layout_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart/slow_path_shared_stub_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
|
||||
dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
|
||||
dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
|
||||
|
@ -441,6 +452,7 @@ dart_2/issue_31959_31960_test: SkipSlow
|
|||
dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart_2/print_flow_graph_determinism_test: SkipSlow
|
||||
dart_2/print_object_layout_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
|
||||
dart_2/slow_path_shared_stub_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
|
||||
dart_2/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
|
||||
dart_2/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
|
||||
|
|
|
@ -534,6 +534,70 @@ void ClassTable::UpdateClassSize(intptr_t cid, ClassPtr raw_cls) {
|
|||
shared_class_table_->SetSizeAt(cid, size);
|
||||
}
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
void ClassTable::PrintObjectLayout(const char* filename) {
|
||||
Class& cls = Class::Handle();
|
||||
Array& fields = Array::Handle();
|
||||
Field& field = Field::Handle();
|
||||
|
||||
JSONWriter js;
|
||||
js.OpenArray();
|
||||
for (intptr_t i = ClassId::kObjectCid; i < top_; i++) {
|
||||
if (!HasValidClassAt(i)) {
|
||||
continue;
|
||||
}
|
||||
cls = At(i);
|
||||
ASSERT(!cls.IsNull());
|
||||
ASSERT(cls.id() != kIllegalCid);
|
||||
ASSERT(cls.is_finalized()); // Precompiler already finalized all classes.
|
||||
ASSERT(!cls.IsTopLevel());
|
||||
js.OpenObject();
|
||||
js.PrintProperty("class", cls.UserVisibleNameCString());
|
||||
js.PrintProperty("size", cls.target_instance_size());
|
||||
js.OpenArray("fields");
|
||||
fields = cls.fields();
|
||||
if (!fields.IsNull()) {
|
||||
for (intptr_t i = 0, n = fields.Length(); i < n; ++i) {
|
||||
field ^= fields.At(i);
|
||||
js.OpenObject();
|
||||
js.PrintProperty("field", field.UserVisibleNameCString());
|
||||
if (field.is_static()) {
|
||||
js.PrintPropertyBool("static", true);
|
||||
} else {
|
||||
js.PrintProperty("offset", field.TargetOffset());
|
||||
}
|
||||
js.CloseObject();
|
||||
}
|
||||
}
|
||||
js.CloseArray();
|
||||
js.CloseObject();
|
||||
}
|
||||
js.CloseArray();
|
||||
|
||||
auto file_open = Dart::file_open_callback();
|
||||
auto file_write = Dart::file_write_callback();
|
||||
auto file_close = Dart::file_close_callback();
|
||||
if ((file_open == nullptr) || (file_write == nullptr) ||
|
||||
(file_close == nullptr)) {
|
||||
OS::PrintErr("warning: Could not access file callbacks.");
|
||||
return;
|
||||
}
|
||||
|
||||
void* file = file_open(filename, /*write=*/true);
|
||||
if (file == nullptr) {
|
||||
OS::PrintErr("warning: Failed to write object layout: %s\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
char* output = nullptr;
|
||||
intptr_t output_length = 0;
|
||||
js.Steal(&output, &output_length);
|
||||
file_write(output, output_length, file);
|
||||
free(output);
|
||||
file_close(file);
|
||||
}
|
||||
#endif // defined(DART_PRECOMPILER)
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ClassTable::PrintToJSONObject(JSONObject* object) {
|
||||
Class& cls = Class::Handle();
|
||||
|
|
|
@ -394,6 +394,10 @@ class ClassTable {
|
|||
|
||||
void Print();
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
void PrintObjectLayout(const char* filename);
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Describes layout of heap stats for code generation. See offset_extractor.cc
|
||||
struct ArrayTraits {
|
||||
|
|
|
@ -67,6 +67,10 @@ DEFINE_FLAG(bool,
|
|||
"Print per-phase breakdown of time spent precompiling");
|
||||
DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynamic targets");
|
||||
DEFINE_FLAG(bool, print_gop, false, "Print global object pool");
|
||||
DEFINE_FLAG(charp,
|
||||
print_object_layout_to,
|
||||
nullptr,
|
||||
"Print layout of Dart objects to the given file");
|
||||
DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler.");
|
||||
DEFINE_FLAG(
|
||||
int,
|
||||
|
@ -469,6 +473,10 @@ void Precompiler::DoCompileAll() {
|
|||
FinalizeAllClasses();
|
||||
ASSERT(Error::Handle(Z, T->sticky_error()).IsNull());
|
||||
|
||||
if (FLAG_print_object_layout_to != nullptr) {
|
||||
IG->class_table()->PrintObjectLayout(FLAG_print_object_layout_to);
|
||||
}
|
||||
|
||||
ClassFinalizer::SortClasses();
|
||||
|
||||
// Collects type usage information which allows us to decide when/how to
|
||||
|
|
Loading…
Reference in a new issue