mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:29:48 +00:00
[VM] Adds @pragma('vm:notify-debugger-on-exception')
TEST=runtime/tests/vm/dart{,_2}/notify_debugger_on_exception_test.dart Bug: https://github.com/flutter/flutter/issues/17007 Change-Id: I988d2385c3d0fc42c4eb769312278261720bb68d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176663 Commit-Queue: Clement Skau <cskau@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
parent
7e3b19e111
commit
9b45fcbd1f
|
@ -7,8 +7,12 @@ These pragmas are part of the VM's API and are safe for use in external code.
|
|||
| Pragma | Meaning |
|
||||
| --- | --- |
|
||||
| `vm:entry-point` | [Defining entry-points into Dart code for an embedder or native methods](compiler/aot/entry_point_pragma.md) |
|
||||
| `vm:never-inline` | [Never inline a function or method](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-never-be-inlined) |
|
||||
| `vm:prefer-inline` | [Inline a function or method when possible](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-be-inlined) |
|
||||
| `vm:never-inline` | [Never inline a function or method](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-never-be-inlined) |
|
||||
| `vm:prefer-inline` | [Inline a function or method when possible](compiler/pragmas_recognized_by_compiler.md#requesting-a-function-be-inlined) |
|
||||
| `vm:notify-debugger-on-exception` | Marks a function that catches exceptions,
|
||||
making the VM treat any caught exception as if they were uncaught.
|
||||
This can be used to notify an attached debugger during debugging, without
|
||||
pausing the app during regular execution. |
|
||||
|
||||
## Pragmas for internal use
|
||||
|
||||
|
|
37
runtime/tests/vm/dart/notify_debugger_on_exception_test.dart
Normal file
37
runtime/tests/vm/dart/notify_debugger_on_exception_test.dart
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// VMOptions=--verbose_debug
|
||||
|
||||
// See: https://github.com/flutter/flutter/issues/17007
|
||||
|
||||
import '../../../observatory/tests/service/service_test_common.dart';
|
||||
import '../../../observatory/tests/service/test_helper.dart';
|
||||
|
||||
const int LINE_A = 24;
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
void catchNotifyDebugger(Function() code) {
|
||||
try {
|
||||
code();
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
}
|
||||
|
||||
syncThrow() {
|
||||
throw 'Hello from syncThrow!'; // Line A.
|
||||
}
|
||||
|
||||
testMain() {
|
||||
catchNotifyDebugger(syncThrow);
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_A),
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) => runIsolateTests(args, tests,
|
||||
testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
//
|
||||
// VMOptions=--verbose_debug
|
||||
|
||||
// See: https://github.com/flutter/flutter/issues/17007
|
||||
|
||||
import '../../../observatory/tests/service/service_test_common.dart';
|
||||
import '../../../observatory/tests/service/test_helper.dart';
|
||||
|
||||
const int LINE_A = 24;
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
void catchNotifyDebugger(Function() code) {
|
||||
try {
|
||||
code();
|
||||
} catch (e) {
|
||||
// Ignore. Internals will notify debugger.
|
||||
}
|
||||
}
|
||||
|
||||
syncThrow() {
|
||||
throw 'Hello from syncThrow!'; // Line A.
|
||||
}
|
||||
|
||||
testMain() {
|
||||
catchNotifyDebugger(syncThrow);
|
||||
}
|
||||
|
||||
final tests = <IsolateTest>[
|
||||
hasStoppedWithUnhandledException,
|
||||
stoppedAtLine(LINE_A),
|
||||
];
|
||||
|
||||
main([args = const <String>[]]) => runIsolateTests(args, tests,
|
||||
testeeConcurrent: testMain, pause_on_unhandled_exceptions: true);
|
|
@ -2173,7 +2173,7 @@ bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
|
|||
return false;
|
||||
}
|
||||
ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
|
||||
if (handler_frame == NULL) {
|
||||
if (handler_frame == nullptr) {
|
||||
// Did not find an exception handler that catches this exception.
|
||||
// Note that this check is not precise, since we can't check
|
||||
// uninstantiated types, i.e. types containing type parameters.
|
||||
|
@ -2181,6 +2181,14 @@ bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
|
|||
// it will be caught once we unwind the stack.
|
||||
return true;
|
||||
}
|
||||
// If handler_frame's function is annotated with
|
||||
// @pragma('vm:notify-debugger-on-exception'), we specifically want to notify
|
||||
// the debugger of this otherwise ignored exception.
|
||||
if (Library::FindPragma(Thread::Current(), /*only_core=*/false,
|
||||
handler_frame->function(),
|
||||
Symbols::vm_notify_debugger_on_exception())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3638,7 +3638,9 @@ bool Library::FindPragma(Thread* T,
|
|||
pragma_name.raw()) {
|
||||
continue;
|
||||
}
|
||||
*options = Instance::Cast(pragma).GetField(pragma_options_field);
|
||||
if (options != nullptr) {
|
||||
*options = Instance::Cast(pragma).GetField(pragma_options_field);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -4773,7 +4773,7 @@ class Library : public Object {
|
|||
bool only_core,
|
||||
const Object& object,
|
||||
const String& pragma_name,
|
||||
Object* options);
|
||||
Object* options = nullptr);
|
||||
|
||||
ClassPtr toplevel_class() const { return raw_ptr()->toplevel_class(); }
|
||||
void set_toplevel_class(const Class& value) const;
|
||||
|
|
|
@ -494,6 +494,7 @@ class ObjectPointerVisitor;
|
|||
V(vm_inferred_type_metadata, "vm.inferred-type.metadata") \
|
||||
V(vm_never_inline, "vm:never-inline") \
|
||||
V(vm_non_nullable_result_type, "vm:non-nullable-result-type") \
|
||||
V(vm_notify_debugger_on_exception, "vm:notify-debugger-on-exception") \
|
||||
V(vm_recognized, "vm:recognized") \
|
||||
V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn") \
|
||||
V(vm_procedure_attributes_metadata, "vm.procedure-attributes.metadata") \
|
||||
|
|
Loading…
Reference in a new issue