Reapply "[vm] Add tests for determinism of script and AppJIT snapshots."
- Fix assembler->Stop("My address is not deterministic").
- Skip tests on -cdartk + simulators as DFE is too slow.
Bug: https://github.com/dart-lang/sdk/issues/31427
Bug: https://github.com/dart-lang/sdk/issues/33264
Change-Id: Id79a8b8c8fc4b3842fcd1d3827d6d4551890b794
Reviewed-on: https://dart-review.googlesource.com/57483
Reviewed-by: Zach Anderson <zra@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 5bed503..c5db6b9 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -13,6 +13,8 @@
#include "include/dart_api.h"
#include "platform/utils.h"
+#define LOG_SECTION_BOUNDARIES false
+
namespace dart {
namespace bin {
@@ -288,12 +290,18 @@
ASSERT(file->Position() == kAppSnapshotHeaderSize);
file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+ if (LOG_SECTION_BOUNDARIES) {
+ Log::PrintErr("%" Px64 ": VM Data\n", file->Position());
+ }
if (!file->WriteFully(vm_data_buffer, vm_data_size)) {
ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
}
if (vm_instructions_size != 0) {
file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+ if (LOG_SECTION_BOUNDARIES) {
+ Log::PrintErr("%" Px64 ": VM Instructions\n", file->Position());
+ }
if (!file->WriteFully(vm_instructions_buffer, vm_instructions_size)) {
ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
filename);
@@ -301,12 +309,18 @@
}
file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+ if (LOG_SECTION_BOUNDARIES) {
+ Log::PrintErr("%" Px64 ": Isolate Data\n", file->Position());
+ }
if (!file->WriteFully(isolate_data_buffer, isolate_data_size)) {
ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n", filename);
}
if (isolate_instructions_size != 0) {
file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
+ if (LOG_SECTION_BOUNDARIES) {
+ Log::PrintErr("%" Px64 ": Isolate Instructions\n", file->Position());
+ }
if (!file->WriteFully(isolate_instructions_buffer,
isolate_instructions_size)) {
ErrorExit(kErrorExitCode, "Unable to write snapshot file '%s'\n",
diff --git a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
new file mode 100644
index 0000000..9c6f60f
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--optimization-counter-threshold=100
+
+// Verify that app-jit snapshot contains dependencies between classes and CHA
+// optimized code.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as p;
+
+import 'snapshot_test_helper.dart';
+
+const snapshotName = 'app.jit';
+
+Future<void> main() async {
+ final Directory temp = Directory.systemTemp.createTempSync();
+ final snapshotPath = p.join(temp.path, 'app.jit');
+ final testPath = Platform.script
+ .toFilePath()
+ .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
+
+ await temp.create();
+ try {
+ final trainingResult = await runDartBinary('TRAINING RUN', [
+ '--snapshot=$snapshotPath',
+ '--snapshot-kind=app-jit',
+ testPath,
+ '--train'
+ ]);
+ expectOutput("OK(Trained)", trainingResult);
+ final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
+ expectOutput("OK(Run)", runResult);
+ } finally {
+ await temp.delete(recursive: true);
+ }
+}
diff --git a/runtime/tests/vm/dart/appjit_test_body.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test_body.dart
similarity index 100%
rename from runtime/tests/vm/dart/appjit_test_body.dart
rename to runtime/tests/vm/dart/appjit_cha_deopt_test_body.dart
diff --git a/runtime/tests/vm/dart/appjit_determinism_test.dart b/runtime/tests/vm/dart/appjit_determinism_test.dart
new file mode 100644
index 0000000..f5116a8
--- /dev/null
+++ b/runtime/tests/vm/dart/appjit_determinism_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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.
+
+// Verify creating an app-jit snapshot twice generates the same bits.
+
+import 'dart:async';
+import 'snapshot_test_helper.dart';
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains('--child')) {
+ print(fib(35));
+ return;
+ }
+
+ await checkDeterministicSnapshot("app-jit", "14930352");
+}
diff --git a/runtime/tests/vm/dart/appjit_test.dart b/runtime/tests/vm/dart/appjit_test.dart
deleted file mode 100644
index 6fbe998..0000000
--- a/runtime/tests/vm/dart/appjit_test.dart
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--optimization-counter-threshold=100
-
-// Verify that app-jit snapshot contains dependencies between classes and CHA
-// optimized code.
-
-import 'dart:async';
-import 'dart:io';
-
-import 'package:expect/expect.dart';
-import 'package:path/path.dart' as p;
-
-class Result {
- final String cmdline;
- final ProcessResult processResult;
-
- Result(this.cmdline, this.processResult);
-}
-
-void reportError(Result result, String msg) {
- print('running ${result.cmdline}:');
- if (result.processResult.stdout.isNotEmpty) {
- print('''
-
-Command stdout:
-${result.processResult.stdout}''');
- }
-
- if (result.processResult.stderr.isNotEmpty) {
- print('''
-
-Command stderr:
-${result.processResult.stderr}''');
- }
-
- Expect.fail(msg);
-}
-
-void expectOutput(String what, Result result) {
- if (result.processResult.stdout.trim() != what) {
- reportError(result, 'Expected test to print \'${what}\' to stdout');
- }
-}
-
-Future<Result> runDartBinary(String prefix, List<String> arguments) async {
- final binary = Platform.executable;
- final actualArguments = <String>[]
- ..addAll(Platform.executableArguments)
- ..addAll(arguments);
- final processResult = await Process.run(binary, actualArguments);
- final result = new Result(
- '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
- if (result.processResult.exitCode != 0) {
- reportError(result,
- '[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
- }
- return result;
-}
-
-const snapshotName = 'app.jit';
-
-void main() async {
- final Directory temp = Directory.systemTemp.createTempSync();
- final snapshotPath = p.join(temp.path, 'app.jit');
- final testPath = Platform.script
- .toFilePath()
- .replaceAll(new RegExp(r'_test.dart$'), '_test_body.dart');
-
- await temp.create();
- try {
- final trainingResult = await runDartBinary('TRAINING RUN', [
- '--snapshot=$snapshotPath',
- '--snapshot-kind=app-jit',
- testPath,
- '--train'
- ]);
- expectOutput("OK(Trained)", trainingResult);
- final runResult = await runDartBinary('RUN FROM SNAPSHOT', [snapshotPath]);
- expectOutput("OK(Run)", runResult);
- } finally {
- await temp.delete(recursive: true);
- }
-}
diff --git a/runtime/tests/vm/dart/script_determinism_test.dart b/runtime/tests/vm/dart/script_determinism_test.dart
new file mode 100644
index 0000000..4b51b4f
--- /dev/null
+++ b/runtime/tests/vm/dart/script_determinism_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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.
+
+// Verify creating a script snapshot twice generates the same bits.
+
+import 'dart:async';
+import 'snapshot_test_helper.dart';
+
+int fib(int n) {
+ if (n <= 1) return 1;
+ return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main(List<String> args) async {
+ if (args.contains('--child')) {
+ print(fib(35));
+ return;
+ }
+
+ await checkDeterministicSnapshot("script", "");
+}
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
new file mode 100644
index 0000000..2de2bbf
--- /dev/null
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as p;
+
+class Result {
+ final String cmdline;
+ final ProcessResult processResult;
+
+ Result(this.cmdline, this.processResult);
+}
+
+void reportError(Result result, String msg) {
+ print('running ${result.cmdline}:');
+ if (result.processResult.stdout.isNotEmpty) {
+ print('''
+
+Command stdout:
+${result.processResult.stdout}''');
+ }
+
+ if (result.processResult.stderr.isNotEmpty) {
+ print('''
+
+Command stderr:
+${result.processResult.stderr}''');
+ }
+
+ Expect.fail(msg);
+}
+
+void expectOutput(String what, Result result) {
+ if (result.processResult.stdout.trim() != what) {
+ reportError(result, 'Expected test to print \'${what}\' to stdout');
+ }
+}
+
+Future<Result> runDartBinary(String prefix, List<String> arguments) async {
+ final binary = Platform.executable;
+ final actualArguments = <String>[]
+ ..addAll(Platform.executableArguments)
+ ..addAll(arguments);
+ print("+ $binary " + actualArguments.join(" "));
+ final processResult = await Process.run(binary, actualArguments);
+ final result = new Result(
+ '[$prefix] ${binary} ${actualArguments.join(' ')}', processResult);
+ if (result.processResult.exitCode != 0) {
+ reportError(result,
+ '[$prefix] Process finished with non-zero exit code ${result.processResult.exitCode}');
+ }
+ return result;
+}
+
+Future<Null> checkDeterministicSnapshot(
+ String snapshotKind, String expectedStdout) async {
+ final Directory temp = Directory.systemTemp.createTempSync();
+ final snapshot1Path = p.join(temp.path, 'snapshot1');
+ final snapshot2Path = p.join(temp.path, 'snapshot2');
+
+ try {
+ final generate1Result = await runDartBinary('GENERATE SNAPSHOT 1', [
+ '--deterministic',
+ '--snapshot=$snapshot1Path',
+ '--snapshot-kind=$snapshotKind',
+ Platform.script.toFilePath(),
+ '--child',
+ ]);
+ expectOutput(expectedStdout, generate1Result);
+
+ final generate2Result = await runDartBinary('GENERATE SNAPSHOT 2', [
+ '--deterministic',
+ '--snapshot=$snapshot2Path',
+ '--snapshot-kind=$snapshotKind',
+ Platform.script.toFilePath(),
+ '--child',
+ ]);
+ expectOutput(expectedStdout, generate2Result);
+
+ var snapshot1Bytes = await new File(snapshot1Path).readAsBytes();
+ var snapshot2Bytes = await new File(snapshot2Path).readAsBytes();
+
+ Expect.equals(snapshot1Bytes.length, snapshot2Bytes.length);
+ for (var i = 0; i < snapshot1Bytes.length; i++) {
+ if (snapshot1Bytes[i] != snapshot2Bytes[i]) {
+ Expect.fail("Snapshots are not bitwise equal!");
+ }
+ }
+ } finally {
+ await temp.delete(recursive: true);
+ }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 92c4f22..00161d8 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -23,6 +23,9 @@
[ $builder_tag == asan ]
cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
+[ $builder_tag == optimization_counter_threshold ]
+dart/appjit_cha_deopt_test: SkipByDesign # Test needs to a particular opt-counter value
+
[ $compiler == app_jit ]
dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
@@ -54,6 +57,7 @@
[ $compiler == dartk ]
cc/DartAPI_New: Fail # Issue #33041
cc/DartAPI_TypeGetParameterizedTypes: Crash # Issue 33042
+dart/appjit_cha_deopt_test: SkipSlow # Issue 33266
dart/redirection_type_shuffling_test/00: RuntimeError
dart/redirection_type_shuffling_test/none: RuntimeError
@@ -214,6 +218,11 @@
cc/ScriptSnapshot1: Fail, Crash, OK # Script snapshots not supported in Dart 2
cc/ScriptSnapshotsUpdateSubclasses: Fail, Crash, OK # Script snapshots not supported in Dart 2
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) ]
+dart/appjit_cha_deopt_test: SkipSlow # DFE too slow
+dart/appjit_determinism_test: SkipSlow # DFE too slow
+dart/script_determinism_test: SkipSlow # DFE too slow
+
# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
# are to be triaged. Isolate tests are skipped on purpose due to the usage of
# batch mode.
@@ -221,6 +230,11 @@
dart/data_uri_spawn_test: Skip # Please triage.
dart/snapshot_version_test: RuntimeError # Please triage.
+[ $compiler != dartk && $compiler != none ]
+dart/appjit_cha_deopt_test: SkipByDesign # Test needs to run from source
+dart/appjit_determinism_test: SkipByDesign # Test needs to run from source
+dart/script_determinism_test: SkipByDesign # Test needs to run from source
+
[ $compiler == dartkp && !$strong ]
dart/truncating_ints_test: Skip # This test cannot be run in dartkp/legacy mode (gen_kernel does not pass --limit-ints-to-64-bits in legacy mode).
@@ -287,9 +301,6 @@
cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
cc/RegenerateAllocStubs: Skip # This test is meaningless for DBC as allocation stubs are not used.
-[ $arch == simdbc64 || $builder_tag == optimization_counter_threshold || $compiler != none ]
-dart/appjit_test: Skip
-
[ $compiler == dart2analyzer || $compiler == dart2js ]
dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
@@ -336,5 +347,7 @@
dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
[ $hot_reload || $hot_reload_rollback ]
+dart/appjit_determinism_test: Skip # Reload affects determinisim
+dart/script_determinism_test: Skip # We can shutdown an isolate before it reloads.
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.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 2208c17..989960e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -19,6 +19,8 @@
#include "vm/timeline.h"
#include "vm/version.h"
+#define LOG_SECTION_BOUNDARIES false
+
namespace dart {
static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) {
@@ -49,6 +51,10 @@
}
void SerializationCluster::WriteAndMeasureAlloc(Serializer* serializer) {
+ if (LOG_SECTION_BOUNDARIES) {
+ OS::PrintErr("Data + %" Px ": Alloc %s\n", serializer->bytes_written(),
+ name_);
+ }
intptr_t start_size = serializer->bytes_written() + serializer->GetDataSize();
intptr_t start_objects = serializer->next_ref_index();
WriteAlloc(serializer);
@@ -59,6 +65,10 @@
}
void SerializationCluster::WriteAndMeasureFill(Serializer* serializer) {
+ if (LOG_SECTION_BOUNDARIES) {
+ OS::PrintErr("Data + %" Px ": Fill %s\n", serializer->bytes_written(),
+ name_);
+ }
intptr_t start = serializer->bytes_written();
WriteFill(serializer);
intptr_t stop = serializer->bytes_written();
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 86e7876..c418f4f 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3240,13 +3240,6 @@
BranchLink(&StubCode::PrintStopMessage_entry()->label());
PopList((1 << R0) | (1 << IP) | (1 << LR)); // Restore R0, IP, LR.
}
- // Emit the message address before the svc instruction, so that we can
- // 'unstop' and continue execution in the simulator or jump to the next
- // instruction in gdb.
- Label stop;
- b(&stop);
- Emit(reinterpret_cast<int32_t>(message));
- Bind(&stop);
bkpt(Instr::kStopMessageCode);
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index a322f7c..305b3a9 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -221,11 +221,6 @@
if (FLAG_print_stop_message) {
UNIMPLEMENTED();
}
- Label stop;
- b(&stop);
- Emit(Utils::Low32Bits(reinterpret_cast<int64_t>(message)));
- Emit(Utils::High32Bits(reinterpret_cast<int64_t>(message)));
- Bind(&stop);
brk(Instr::kStopMessageCode);
}
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 0ba938b..ae69a35 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2320,9 +2320,6 @@
movl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
Call(*StubCode::PrintStopMessage_entry()); // Passing message in EAX.
popl(EAX); // Restore EAX.
- } else {
- // Emit the message address as immediate operand in the test instruction.
- testl(EAX, Immediate(reinterpret_cast<int32_t>(message)));
}
// Emit the int3 instruction.
int3(); // Execution can be resumed with the 'cont' command in gdb.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index e08f526..7bcd4a0 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1307,8 +1307,8 @@
}
void Assembler::Stop(const char* message, bool fixed_length_encoding) {
- int64_t message_address = reinterpret_cast<int64_t>(message);
if (FLAG_print_stop_message) {
+ int64_t message_address = reinterpret_cast<int64_t>(message);
pushq(TMP); // Preserve TMP register.
pushq(RDI); // Preserve RDI register.
if (fixed_length_encoding) {
@@ -1322,14 +1322,6 @@
call(&StubCode::PrintStopMessage_entry()->label());
popq(RDI); // Restore RDI register.
popq(TMP); // Restore TMP register.
- } else {
- // Emit the lower half and the higher half of the message address as
- // immediate operands in the test rax instructions.
- testl(RAX, Immediate(Utils::Low32Bits(message_address)));
- uint32_t hi = Utils::High32Bits(message_address);
- if (hi != 0) {
- testl(RAX, Immediate(hi));
- }
}
// Emit the int3 instruction.
int3(); // Execution can be resumed with the 'cont' command in gdb.
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 5c718de..491a2b4 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -656,8 +656,11 @@
if ((instr->Bits(21, 2) == 0x1) && (instr->ConditionField() == AL)) {
Format(instr, "bkpt #'imm12_4");
if (instr->BkptField() == Instr::kStopMessageCode) {
- const char* message = *reinterpret_cast<const char**>(
- reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+ const char* message = "Stop messages not enabled";
+ if (FLAG_print_stop_message) {
+ message = *reinterpret_cast<const char**>(
+ reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+ }
buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
" ; \"%s\"", message);
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index f5b49f7..14fb8a6 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -886,8 +886,11 @@
(instr->Bits(21, 3) == 1)) {
Format(instr, "brk 'imm16");
if (instr->Imm16Field() == Instr::kStopMessageCode) {
- const char* message = *reinterpret_cast<const char**>(
- reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+ const char* message = "Stop messages not enabled";
+ if (FLAG_print_stop_message) {
+ message = *reinterpret_cast<const char**>(
+ reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+ }
buffer_pos_ +=
Utils::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(), " ; \"%s\"", message);
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 56b3878..a25530c 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -1234,8 +1234,11 @@
#if defined(TARGET_ARCH_IA32)
// Recognize stop pattern.
if (*data == 0xCC) {
- const char* text = *reinterpret_cast<const char**>(data - 4);
- Print(" STOP:'%s'", text);
+ const char* message = "Stop messages not enabled";
+ if (FLAG_print_stop_message) {
+ message = *reinterpret_cast<const char**>(data - 4);
+ }
+ Print(" STOP:'%s'", message);
}
#endif
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index db1f4a2..ae20a77 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -84,13 +84,15 @@
static void DeterministicModeHandler(bool value) {
if (value) {
- FLAG_background_compilation = false;
- FLAG_collect_code = false;
+ FLAG_background_compilation = false; // Timing dependent.
+ FLAG_collect_code = false; // Timing dependent.
FLAG_random_seed = 0x44617274; // "Dart"
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
FLAG_load_deferred_eagerly = true;
+ FLAG_print_stop_message = false; // Embedds addresses in instructions.
#else
COMPILE_ASSERT(FLAG_load_deferred_eagerly);
+ COMPILE_ASSERT(!FLAG_print_stop_message);
#endif
}
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d6a2533..bd98c07 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7070,6 +7070,7 @@
result.set_parameter_types(Object::empty_array());
result.set_parameter_names(Object::empty_array());
result.set_name(name);
+ result.set_kind_tag(0); // Ensure determinism of uninitialized bits.
result.set_kind(kind);
result.set_recognized_kind(MethodRecognizer::kUnknown);
result.set_modifier(RawFunction::kNoModifier);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 1efbaa8..9bb3ca9 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1559,8 +1559,11 @@
SimulatorDebugger dbg(this);
int32_t imm = instr->BkptField();
if (imm == Instr::kStopMessageCode) {
- const char* message = *reinterpret_cast<const char**>(
- reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+ const char* message = "Stop messages not enabled";
+ if (FLAG_print_stop_message) {
+ message = *reinterpret_cast<const char**>(
+ reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
+ }
set_pc(get_pc() + Instr::kInstrSize);
dbg.Stop(instr, message);
} else {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 5493d43..e482786 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1651,8 +1651,11 @@
SimulatorDebugger dbg(this);
int32_t imm = instr->Imm16Field();
if (imm == Instr::kStopMessageCode) {
- const char* message = *reinterpret_cast<const char**>(
- reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+ const char* message = "Stop messages not enabled";
+ if (FLAG_print_stop_message) {
+ message = *reinterpret_cast<const char**>(
+ reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
+ }
set_pc(get_pc() + Instr::kInstrSize);
dbg.Stop(instr, message);
} else {