mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:19:49 +00:00
[vm, compiler] Fix incorrect register save in breakpoint stub.
Bug introduced in 1e24fe7d69
.
Symbolize stub frames.
TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/47039
Change-Id: Ida3535a01923085cd48a2801ed9b868bfef7418b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/212026
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
parent
4e660ab787
commit
baa1ebb377
53
runtime/observatory/tests/service/breakpoint_gc_test.dart
Normal file
53
runtime/observatory/tests/service/breakpoint_gc_test.dart
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
import 'test_helper.dart';
|
||||
import 'service_test_common.dart';
|
||||
|
||||
const int LINE_A = 16;
|
||||
const int LINE_B = 19;
|
||||
const int LINE_C = 22;
|
||||
const String file = "breakpoint_gc_test.dart";
|
||||
|
||||
foo() => 42;
|
||||
|
||||
testeeMain() {
|
||||
foo(); // static call
|
||||
|
||||
dynamic list = [1, 2, 3];
|
||||
list.clear(); // instance call
|
||||
print(list);
|
||||
|
||||
dynamic local = list; // debug step check = runtime call
|
||||
return local;
|
||||
}
|
||||
|
||||
Future forceGC(isolate) async {
|
||||
await isolate.invokeRpcNoUpgrade("_collectAllGarbage", {});
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasPausedAtStart,
|
||||
setBreakpointAtUriAndLine(file, LINE_A), // at `foo()`
|
||||
setBreakpointAtUriAndLine(file, LINE_B), // at `list.clear()`
|
||||
setBreakpointAtUriAndLine(file, LINE_C), // at `local = list`
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_A),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_B),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_C),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
];
|
||||
|
||||
main(args) {
|
||||
runIsolateTestsSynchronous(args, tests,
|
||||
testeeConcurrent: testeeMain, pause_on_start: true);
|
||||
}
|
|
@ -52,6 +52,7 @@ break_on_function_child_isolate_test: SkipByDesign # Debugger is disabled in AOT
|
|||
break_on_function_many_child_isolates_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
break_on_function_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_async_break_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_gc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_package_parts_class_file_uri_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_package_parts_class_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_parts_class_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
import 'test_helper.dart';
|
||||
import 'service_test_common.dart';
|
||||
|
||||
const int LINE_A = 16;
|
||||
const int LINE_B = 19;
|
||||
const int LINE_C = 22;
|
||||
const String file = "breakpoint_gc_test.dart";
|
||||
|
||||
foo() => 42;
|
||||
|
||||
testeeMain() {
|
||||
foo(); // static call
|
||||
|
||||
dynamic list = [1, 2, 3];
|
||||
list.clear(); // instance call
|
||||
print(list);
|
||||
|
||||
dynamic local = list; // debug step check = runtime call
|
||||
return local;
|
||||
}
|
||||
|
||||
Future forceGC(isolate) async {
|
||||
await isolate.invokeRpcNoUpgrade("_collectAllGarbage", {});
|
||||
}
|
||||
|
||||
var tests = <IsolateTest>[
|
||||
hasPausedAtStart,
|
||||
setBreakpointAtUriAndLine(file, LINE_A), // at `foo()`
|
||||
setBreakpointAtUriAndLine(file, LINE_B), // at `list.clear()`
|
||||
setBreakpointAtUriAndLine(file, LINE_C), // at `local = list`
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_A),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_B),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
hasStoppedAtBreakpoint,
|
||||
stoppedAtLine(LINE_C),
|
||||
forceGC, // Should not crash
|
||||
resumeIsolate,
|
||||
];
|
||||
|
||||
main(args) {
|
||||
runIsolateTestsSynchronous(args, tests,
|
||||
testeeConcurrent: testeeMain, pause_on_start: true);
|
||||
}
|
|
@ -52,6 +52,7 @@ break_on_function_child_isolate_test: SkipByDesign # Debugger is disabled in AOT
|
|||
break_on_function_many_child_isolates_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
break_on_function_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_async_break_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_gc_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_package_parts_class_file_uri_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_package_parts_class_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
breakpoint_in_parts_class_test: SkipByDesign # Debugger is disabled in AOT mode.
|
||||
|
|
|
@ -2726,13 +2726,11 @@ void StubCodeCompiler::GenerateUnoptStaticCallBreakpointStub(
|
|||
__ Stop("No debugging in PRODUCT mode");
|
||||
#else
|
||||
__ EnterStubFrame();
|
||||
__ pushq(RDX); // Preserve receiver.
|
||||
__ pushq(RBX); // Preserve IC data.
|
||||
__ pushq(Immediate(0)); // Result slot.
|
||||
__ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
|
||||
__ popq(CODE_REG); // Original stub.
|
||||
__ popq(RBX); // Restore IC data.
|
||||
__ popq(RDX); // Restore receiver.
|
||||
__ LeaveStubFrame();
|
||||
|
||||
__ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
|
||||
|
|
|
@ -162,24 +162,12 @@ bool StackFrame::IsStubFrame() const {
|
|||
const char* StackFrame::ToCString() const {
|
||||
ASSERT(thread_ == Thread::Current());
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
if (IsDartFrame()) {
|
||||
const Code& code = Code::Handle(zone, LookupDartCode());
|
||||
ASSERT(!code.IsNull());
|
||||
const auto& owner = Object::Handle(
|
||||
zone, WeakSerializationReference::UnwrapIfTarget(code.owner()));
|
||||
ASSERT(!owner.IsNull());
|
||||
auto const opt = code.IsFunctionCode() && code.is_optimized() ? "*" : "";
|
||||
auto const owner_name =
|
||||
owner.IsFunction() ? Function::Cast(owner).ToFullyQualifiedCString()
|
||||
: owner.ToCString();
|
||||
return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
|
||||
") %s%s ]",
|
||||
GetName(), sp(), fp(), pc(), opt, owner_name);
|
||||
} else {
|
||||
return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
|
||||
")]",
|
||||
GetName(), sp(), fp(), pc());
|
||||
}
|
||||
const Code& code = Code::Handle(zone, GetCodeObject());
|
||||
ASSERT(!code.IsNull());
|
||||
const char* name =
|
||||
code.QualifiedName(NameFormattingParams(Object::kInternalName));
|
||||
return zone->PrintToString(" pc 0x%" Pp " fp 0x%" Pp " sp 0x%" Pp " %s",
|
||||
pc(), fp(), sp(), name);
|
||||
}
|
||||
|
||||
void ExitFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
||||
|
|
Loading…
Reference in a new issue