The debugger assumes a null suspend state variable in an asynchronous
function means that the function is still in the prologue prior
to setting up the suspend state. However, the interpreter clears the
suspend state variable before returning, and the debugger needs to be
able to pause before returning when single stepping, so earlier a hack
was added to the debugger that detects being at the direct call of the
async return method and/or the return instruction with a null suspend
state variable.
However, there's a much simpler way of ensuring the debugger pauses
before returning: just emit the source position for the return prior to
clearing the suspend state variable. This also ensures that the debugger
still has access to the function's suspend state when pausing before
the return, instead of waiting until it has been cleared and thus is no
longer accessible.
TEST=ci (should not change the result of any current tests)
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try
Change-Id: I401cceb169d8692ac379cdc5a531e07cafbe9a65
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/500740
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Previously, the debugger used a boolean "skip next step" field that was
set when a breakpoint was hit. In compiled code, not skipping the next
step would cause a redundant pause to be emitted after a breakpoint, and
so that field caused the next run of PauseStepping to reset it to false
and then continue single stepping without the redundant pause.
However, skipping only the next call to PauseStepping isn't enough
when debugging bytecode. For bytecode, single stepping is performed on
each bytecode instruction and so there may be multiple instructions after a breakpoint until a new token position is reached.
Instead, remove the field and generalize the case being avoided by
recording the token position that should be ignored and single
stepping until the token position changes. This is done by recording
a real last_stepping_pos_ with a last_stepping_fp_ of 0, which now
means to skip any possible pauses until the token position changes.
Doing this means that in each case where there are possible skips to
be performed (skipping the same fp/pos after a pause, skipping the
pos after a breakpoint, skipping the await fp/pos after a resumption),
all such skips are handled via a single unified mechanism.
This CL also reworks the kStepOut behavior so that it steps into
the awaiter closest to the highest debuggable frame on the stack if
there is one, not just the first awaiter even if there are no
debuggable frames between that awaiter and the next.
TEST=pkg/vm_service/test/vm_timeline_flags
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: Ic897d7bea382589751777f4db39aa58bf9525604
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/474340
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Improves the readability of the tracing output by adding beginning and
ending markers for debugger stacktrace collection and using specific
spacing instead of \t in output, so that output is more naturally nested
via indention:
* beginning/ending markers are not indented,
* frames are indented by two spaces, and
* additional output while collecting a frame is indented by four spaces.
Adds tracing for DebuggerStackTrace::CollectAsyncAwaiters(). A different
ending marker is used in the case when the collected trace is discarded
due to a lack of async awaiters.
ActivationFrame::GetSavedCurrentContext now takes an optional out
parameter for the current context variable index, which is only used by
CollectDartFrame and used to print the index there. This eliminates
extra output when this method is used outside collecting stack traces.
When the current context variable index is requested,
GetSavedCurrentContext ignores the cached context if any so that the
index is appropriately set if an appropriate variable is found.
By default, skips tracing of non-collected frames and repeated async
suspensions in async awaiter traces. Use the new
--trace-debugger-stacktrace-verbose flag to add tracing for these cases.
TEST=ci (tested manually, only affects debugging output)
Change-Id: I2978d540f41b444251a61b62a57b6785a3dd8df0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/467300
Auto-Submit: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Since the only captured variable in the context for an implicit
instance closure is this, the allocation of a context object is
elided and instead the instance is stored directly as the "context".
In the debugger, create the elided context object for implicit instance
closures when retrieving the saved context from an implicit instance
closure activation frame.
Without this, any attempt to GetSavedCurrentContext() on an
ActivationFrame for an implicit instance closure (e.g., when
--trace-debugger-stacktrace is enabled) breaks due to the assert
in debug mode, and returns a null context (which isn't correct either)
in non-debug modes.
TEST=vm/dart/regress_cl_463021
Change-Id: I2ba22407695f432a30d23d342f33dfe2a00ba308
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/463021
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
There are two possible flags for each source position currently:
a flag that marks the source position as synthetic and a flag that
marks the source position as within a yield point.
Synthetic source positions in bytecode are treated the same as synthetic
source positions in compiled code. That is, they encode the source
position in the text that caused them to be synthesized, but denote that
the covered instructions are internal and not to be used for debugger
pause points or for call site/branch coverage information.
Adding these flags allow us to mark appropriate parts of the async
machinery as synthetic, and also allow us to mark all the bytecode
involved in yield points as having the same token position.
The latter fixes tests where the code would step over a previous
expression, thus being paused at the start of the await bytecode,
and would record the fp and token position there as the ones to
ignore. However, since a new source position wasn't emitted until the
direct call to the await method, the recorded token position would
be the token position prior to the await call, and so the change
in token position at the await call would trigger an early pause.
TEST=pkg/vm_service/test/async_single_step_exception_test
pkg/vm_service/test/async_single_step_into_test
pkg/vm_service/test/async_single_step_out_test
pkg/vm_service/test/async_star_single_step_into_test
pkg/vm_service/test/async_step_out_test
pkg/vm_service/test/positive_token_pos_test
pkg/vm_service/test/step_into_async_no_await_test
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-product-x64-try
Change-Id: Ic7642a74fb76227a473f461f360e84dd3d5a45a1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/453322
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
The end PC offset for the scope is inclusive, not exclusive.
Also rename PrintDescriptorsError -> PrintContextLevelError and
print the Bytecode local variable information since that is what
is searched for the context level for interpreted frames.
TEST=pkg/vm_service/test/step_through_closure
pkg/vm_service/test/step_through_function_expression
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: Ib53d0a7cff81de16c957b73ce9ec7dcb0e4aaa34
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449740
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Instead of using the computed LocalVarDescriptors when the
frame is interpreted, use the LocalVariableInfo in the serialized
bytecode to find which Scope is currently active.
Add printing of local variable information to the bytecode
disassembler.
TEST=pkg/vm_service/test
Change-Id: I7bd15056e4e2a947ad16ffb83a50447c2ba59994
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449340
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Since any instruction is a possible pause point when single stepping in
the interpreter, the debugger may pause too early when stepping over an
expression; for example, if the value returned from an expression is
ignored, stepping over the expression should also step over the
following Drop1 instruction (which will have the same source location),
but currently does not.
To avoid this, set last_stepping_fp_ and last_stepping_pos_ when
stepping over either a sync or async expression so that the debugger
won't pause until a new source position is reached.
TEST=pkg/vm_service/test
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-dyn-mac-debug-arm64-try
Change-Id: I0934f6bda3fc075a225a85b66eccf46b94cb4020
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449420
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Detects yield points in Debugger::IsAtAsyncJump for bytecode by seeing
if the currently executing instruction is a direct call to an await
or yield compiled stub.
Adds a ResumptionBreakpointHandler runtime entry that is called
during Interpreter::Resume() if the current isolate has resumption
breakpoints.
Similarly, all the places where a DebugCheck could be emitted if
debugging stops are requested now include an explicit source position
emission when source positions are requested but debugger stops are not,
to ensure the debugger has appropriate information.
Fixes CompareTopDartFrameTo returning kSelf for non-top frames when
the top frame was interpreted but the stepping frame was not or
vice versa.
TEST=pkg/vm_service/test
Change-Id: I88cdc37cf745f30e8dfb6b14c19fc9b2c4cbaf2d
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/446300
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Adds a set of new VMInternal_Breakpoint instructions, one for each
possible instruction size, and adds a bytecode_ and saved_opcode_
field to code breakpoints.
When enabling a breakpoint, the original opcode of the instruction is
replaced with the same-sized VmInternal_Breakpoint opcode and stored in
the saved_opcode_ field of the CodeBreakpoint. When disabling it, the
original opcode is replaced.
New labels are added to the dispatch loop for single stepping
purposes. Both the computed goto and switch dispatch versions
of the dispatch loop are appropriately altered to dispatch to
the single stepping labels instead of the original ones if single
stepping is currently enabled.
Fix up more parts of the debugger that assumed functions had Code
objects to handle functions with Bytecode objects as well. In
particular, instead of using the PcDescriptors to find safepoint
source locations in Bytecode objects, the source positions information
is used instead (since the PcDescriptors for Bytecode objects only
stores information about the start and end of try blocks at the moment).
Todo (from looking at the remaining failing tests):
* Handle async jumps.
* Handle coverage information.
TEST=now-passing tests from pkg/vm_service like
pkg/vm_service/test/break_on_function_test
Change-Id: Icbd4b818e00508d9a4e74c81520aad2363b26d41
Cq-Include-Trybots: luci.dart.try:vm-dyn-linux-debug-x64-try,vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-mac-debug-arm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444880
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Also, support reading local variables information from bytecode.
TEST=pkg/vm_service
Change-Id: Iab482316891f0e474af0011e9b1765c4e8312bc9
Cq-Include-Trybots: luci.dart.try:vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-linux-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/437281
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This is a reland of commit cb9ecbc363
This reland only turns on the entry point verification flag by
default in AOT mode. After Flutter tests that use native access
in JIT mode have been appropriately updated, a followup CL will
turn this flag on by default in JIT mode as well.
Original change's description:
> [vm] Enforce that entry points must be annotated by default.
>
> Changes the default value of the --verify-entry-points flag
> to true.
>
> Changes the default value for the check_is_entrypoint argument to
> to the Invoke/InvokeGetter/InvokeSetter flags to true. The mirrors
> library implementation and calls via vm-service explicitly pass
> false for this argument now.
>
> Add annotations as needed, such as annotating classes with
> annotated generative constructors. In some cases, the annotations
> were more general than needed (e.g., annotating with a no-argument
> entry point annotation when only the setter is needed), so make
> those annotations more specific.
>
> As this pattern is already common in downstream code, allow
> Dart_Invoke on fields as long as the field is annotated for getter
> access. (That is, calling Dart_Invoke for a field is equivalent to
> retrieving the closure value via Dart_GetField and then calling
> Dart_InvokeClosure.)
>
> TEST=vm/cc/DartAPI_MissingEntryPoints
> vm/dart/entrypoints_verification_test
>
> Issue: https://github.com/dart-lang/sdk/issues/50649
> Issue: https://github.com/flutter/flutter/issues/118608
>
> Change-Id: Ibb3bf15632ab2958d8791b449af8651d47f871a5
> Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try
> CoreLibraryReviewExempt: adding/editing vm-only pragma annotations
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363566
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Tess Strickland <sstrickl@google.com>
TEST=vm/cc/DartAPI_MissingEntryPoints
vm/dart/entrypoints_verification_test
Change-Id: I24919c32ab4760c7c5435c378879791086256f02
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try,flutter-linux-try,vm-linux-debug-x64-try,vm-linux-release-x64-try,vm-appjit-linux-product-x64-try
CoreLibraryReviewExempt: adding/editing vm-only pragma annotations
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391620
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This reverts commit cb9ecbc363.
Reason for revert: causes failures during Dart->Flutter roll and on Flutter HHH bots (see comments on the original CL).
Original change's description:
> [vm] Enforce that entry points must be annotated by default.
>
> Changes the default value of the --verify-entry-points flag
> to true.
>
> Changes the default value for the check_is_entrypoint argument to
> to the Invoke/InvokeGetter/InvokeSetter flags to true. The mirrors
> library implementation and calls via vm-service explicitly pass
> false for this argument now.
>
> Add annotations as needed, such as annotating classes with
> annotated generative constructors. In some cases, the annotations
> were more general than needed (e.g., annotating with a no-argument
> entry point annotation when only the setter is needed), so make
> those annotations more specific.
>
> As this pattern is already common in downstream code, allow
> Dart_Invoke on fields as long as the field is annotated for getter
> access. (That is, calling Dart_Invoke for a field is equivalent to
> retrieving the closure value via Dart_GetField and then calling
> Dart_InvokeClosure.)
>
> TEST=vm/cc/DartAPI_MissingEntryPoints
> vm/dart/entrypoints_verification_test
>
> Issue: https://github.com/dart-lang/sdk/issues/50649
> Issue: https://github.com/flutter/flutter/issues/118608
>
> Change-Id: Ibb3bf15632ab2958d8791b449af8651d47f871a5
> Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try
> CoreLibraryReviewExempt: adding/editing vm-only pragma annotations
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363566
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Tess Strickland <sstrickl@google.com>
Issue: https://github.com/dart-lang/sdk/issues/50649
Issue: https://github.com/flutter/flutter/issues/118608
Change-Id: Idba168f77b0636a50ad93309e29dc9989cc1f388
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/391460
Auto-Submit: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Changes the default value of the --verify-entry-points flag
to true.
Changes the default value for the check_is_entrypoint argument to
to the Invoke/InvokeGetter/InvokeSetter flags to true. The mirrors
library implementation and calls via vm-service explicitly pass
false for this argument now.
Add annotations as needed, such as annotating classes with
annotated generative constructors. In some cases, the annotations
were more general than needed (e.g., annotating with a no-argument
entry point annotation when only the setter is needed), so make
those annotations more specific.
As this pattern is already common in downstream code, allow
Dart_Invoke on fields as long as the field is annotated for getter
access. (That is, calling Dart_Invoke for a field is equivalent to
retrieving the closure value via Dart_GetField and then calling
Dart_InvokeClosure.)
TEST=vm/cc/DartAPI_MissingEntryPoints
vm/dart/entrypoints_verification_test
Issue: https://github.com/dart-lang/sdk/issues/50649
Issue: https://github.com/flutter/flutter/issues/118608
Change-Id: Ibb3bf15632ab2958d8791b449af8651d47f871a5
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-mac-release-arm64-try,vm-aot-mac-product-arm64-try,vm-aot-dwarf-linux-product-x64-try
CoreLibraryReviewExempt: adding/editing vm-only pragma annotations
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363566
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
In this CL, Debugger::FindCompiledFunctions always just returns
Error::null(), but when eager compilation of functions is implemented
(https://dart-review.googlesource.com/c/sdk/+/338740), it will introduce
the possibility of Debugger::FindCompiledFunctions truly returning
errors. So, this CL adds the error propagation logic in advance to
avoid making the eager function compilation CL too large.
TEST=this is effectively just a refactor, so CI
Change-Id: Ibedbebf19fed306c8b93c98ba71b7cc57b90e174
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369161
Reviewed-by: Alexander Aprelev <aam@google.com>
It is dead code. Breakpoint requests that only have a line number are just handled by passing column_number=-1 to SetBreakpointAtLineCol.
TEST=CI
Change-Id: I44fb9f805c364edb074bf9cdbd3fcbe3888b3bff
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369160
Reviewed-by: Alexander Aprelev <aam@google.com>
TEST=verified that
pkg/vm_service/test/breakpoint_resolves_immediately_in_compiled_field_initializer_test.dart
fails without the changes in this CL and passes with them, verified that
none of the existing debugger tests got broken by this CL
Change-Id: I6acb5576a80e5d633b012c866fe90bf13d2c1ba6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369162
Commit-Queue: Derek Xu <derekx@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
compiled prior to the latest reload
TEST=verified that
pkg/vm_service/test/breakpoint_resolution_after_reloading_test.dart
fails without the changes in this CL and passes with them, verified that
none of the existing debugger tests got broken by this CL
Change-Id: Ie816a3ad65a17ef9f497f209f2203d679728cb75
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366860
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Derek Xu <derekx@google.com>
This CL adds @pragma('vm:awaiter-link') in various places in
Stream implementation to facilitate unwinding and expands
async unwinding logic with more information about
Stream internals.
At the same time be more conservative when checking if an
exception thrown from async method handled: failing to unwind
the stack fully creates situations when we incorrectly report
caught exceptions as uncaught, which frustrates users.
To distinguish stream subscriptions with and without error
handlers we add a state bit. Otherwise, it looks like all
subscriptions have error handlers because if no error
handler is installed we eagerly install error handler forwarding
the error to `Zone.handleUncaughtError`.
Fixes https://github.com/dart-lang/sdk/issues/53334
Fixes https://github.com/dart-lang/sdk/issues/54788
Fixes https://github.com/dart-lang/sdk/issues/47985
TEST=runtime/vm/dart/awaiter_stacks/stream_methods_test.dart,pkg/vm_service/test/pause_on_unhandled_async_exceptions6_test.dart,pkg/vm_service/test/pause_on_unhandled_async_exceptions7_test.dart
CoreLibraryReviewExempt: No behavioral change. Async changes reviewed by lrhn@
Cq-Include-Trybots: luci.dart.try:vm-aot-android-release-arm64c-try,vm-aot-android-release-arm_x64-try,vm-aot-dwarf-linux-product-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try
Change-Id: Ic51f926867092dd0adbe801b753f57c357c7ace2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322720
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
Previously, when taking a tear-off, a separate Context object was
allocated in order to capture receiver. Now, receiver is stored directly
in the Closure object in the 'context' field. This saves 1 object
allocation per tear-off and makes tear-offs cheaper compared to
explicit closures which can share context with other closures.
Benchmarks in AOT mode:
x64:
TearOff.NotInlined +40%
TearOff.NotInlined.InTry +43%
TearOff.Inlined.InTry +47%
arm64:
TearOff.NotInlined +27-43%
TearOff.NotInlined.InTry +29-43%
TearOff.Inlined.InTry +58-94%
arm64c:
TearOff.NotInlined +71%
TearOff.NotInlined.InTry +72%
TearOff.Inlined.InTry +96%
TEST=ci
Issue: https://github.com/dart-lang/sdk/issues/54808
Change-Id: I3ad95e8a8a4fc23f856bbc0fe238da58a9d25b8d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350945
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Our async unwinding code used to only respect `catchError`
which occured between async frames and ignored trailing
`catchError` like in the code below
Future(...).catchError((_) { /* handle error */ });
This CL also simplifies how we communicate the presence of the
exception handler to the debugger: the code in the debugger did
not actually care about which frame catches the error (for async
handlers), so we don't need to precisely mark async gaps with
`has_catch_error` flag. Instead we have a single boolean
produced by unwinding which signals whether there we encountered
an asynchronous error handler or not.
Fixes https://github.com/flutter/flutter/issues/141882
TEST=service/pause_on_unhandled_async_exceptions5
Change-Id: Id6f6a97ee5444c197b2c621f68d1e47082fc8997
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350320
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This is a reland of commit e727f4ecbd
We allow the arguments array in
EvaluateCompiledExpressionHelper to contain
Object::optimized_out().ptr() when we have determined that the receiver
has been optimized out but isn't used by the compiled expression. So, I
have moved the assertion that checks for optimized out arguments from
EvaluateCompiledExpressionHelper to
Instance::EvaluateCompiledExpression.
TEST=vm-linux-debug-x64 tryjob
Original change's description:
> [VM/Debugger] Ignore optimized out variables when building scope in ActivationFrame::BuildParameters
>
> TEST=pkg/vm_service/test/evaluate_optimized_out_variable_test.dart
>
> Issue: https://github.com/dart-lang/sdk/issues/53996
> Change-Id: I5e6f0b2c02455af73c2108e6996039c95d3f1f31
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/347940
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
> Commit-Queue: Derek Xu <derekx@google.com>
Change-Id: Id6df0b0b3e0d26239068041126b034e9469b87af
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/347945
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Derek Xu <derekx@google.com>
Acquire reload opreation scope when deoptimizing the world to ensure locks can be acquired for compilation.
Set up scope for operations that can be run while the world is deoptimized and stopped to avoid races.
Ensure code stays unoptizimed when single stepping, prevent other isolates to reoptimize it.
TEST=DeoptimizeFramesWhenSettingBreakpoint
BUG=https://github.com/flutter/flutter/issues/140878
Change-Id: Id4c891bd585d42365fd3a60cfb9a4869892c2b03
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345743
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
The value of best_token_pos was
exact_token_pos.Pos() - (requested_column - *best_column), but this
value is guaranteed to be the same as best_fit_pos.
TEST=CI
Change-Id: I96f21cc45ebbac94dfe35fa39af922a227e1fde6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/338080
Commit-Queue: Derek Xu <derekx@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
RwLock, rather that SafepointRwLock, is okay to use for these two breakpoint_locations and single_stepping_set locks because they are short-lived, should not spawn over the safepoint.
TEST=ci
Change-Id: Iba83291978ba7980d0c6fd0a0a2cf2174c801359
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323202
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
When evaluating an expressino at a breakpoint that's inside a closure,
the closure may refer to anything it closes over. That includes the
`this` from an enclosing method.
So depending on whether a closure's parent chain is an instance method
or a static method, the expression evaluation function is going to be an
instance method or a static method.
=> We walk up the parent chain to determine the correct enclosing class.
=> This avoids making a Type object with a cid from a top-level class (see [0])
Handling this correctly will now try to get the `this` when invoking an
eval function that has an enclosing instance method. Though we may often
have "<optimized out>" the `this` (e.g. due to not capturing it in
closure context chain).
=> We still allow running the expression evaluation function in this
case, but only if the expression being evaluated doesn't access `this`.
A similar issue occurs when trying to use variables in the eval
expression that the closure didn't capture. This results in a confusing
CFE compile-time error. This is a separate issue and tracked in [1].
=> We update the test to distinuish the cases that this CL makes passing
and those that are failing due to [1].
Fixes [0] https://github.com/dart-lang/sdk/issues/53061
See also [1] https://github.com/dart-lang/sdk/issues/53087
TEST=Fixes part of service/evaluate_activation_test failures
Change-Id: I3bb24e7338c7b2f12d5340311d944cb59a455641
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317540
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
The main contribution of this CL is unification of disparate
handling of various functions like `Future.timeout`,
`Future.wait`, `_SuspendState.createAsyncCallbacks` and
`_SuspendState._createAsyncStarCallback` into a single
`@pragma('vm:awaiter-link')` which allows Dart developers
to specify where awaiter unwinder should look for the next
awaiter.
For example this allows unwinding to succeed for the code like this:
Future<int> outer(Future<int> inner) {
@pragma('vm:awaiter-link')
final completer = Completer<int>();
inner.then((v) => completer.complete(v));
return completer.future;
}
This refactoring also ensures that we preserve information
(including Function & Code objects) required for awaiter
unwinding across all modes (JIT, AOT and AOT with DWARF stack
traces). This guarantees users will get the same information
no matter which mode they are running in. Previously
we have been disabling awaiter_stacks tests in some AOT
modes - which led to regressions in the quality of produced
stacks.
This CL also cleans up relationship between debugger and awaiter
stack returned by StackTrace.current - which makes stack trace
displayed by debugger (used for stepping out and determinining
whether exception is caught or not) and `StackTrace.current`
consistent.
Finally we make one user visible change to the stack trace:
awaiter stack will no always include intermediate listeners
created through `Future.then`. Previously we would sometimes
include these listeners at the tail of the stack trace,
which was inconsistent.
Ultimately this means that code like this:
Future<int> inner() async {
await null; // asynchronous gap
print(StackTrace.current); // (*)
return 0;
}
Future<int> outer() async {
int process(int v) {
return v + 1;
}
return await inner().then(process);
}
void main() async {
await outer();
}
Produces stack trace like this:
inner
<asynchronous suspension>
outer.process
<asynchronous suspension>
outer
<asynchronous suspension>
main
<asynchronous suspension>
And when stepping out of `inner` execution will stop at `outer.process`
first and the next step out will bring execution to `outer` next.
Fixes https://github.com/dart-lang/sdk/issues/52797
Fixes https://github.com/dart-lang/sdk/issues/52203
Issue https://github.com/dart-lang/sdk/issues/47985
TEST=ci
Bug: b/279929839
CoreLibraryReviewExempt: CL just adds @pragma to facilitate unwinding
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-product-x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-dwarf-linux-product-x64-try
Change-Id: If377d5329d6a11c86effb9369dc603a7ae616fe7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311680
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
The [PatchClass] no longer needs to refer to a original [Class] and a
patched [Class] objects: Since the CFE does handling of patches the VM
only has a single [Class] object, so those two fields are always the
same.
=> Change `PatchClass::{origin_class,patched_class} -> `PatchClass::wrapped_class`
We also remove the `Field::Origin()` / `Function::origin()` methods
as they return the same as the `Owner()` would return.
TEST=ci
Change-Id: Iec0849f6ffc2026760dad89a9bcf07e9469bc8b6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311840
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
The name is more accurately reflects what this stack trace
contains: despite what causal implies it does *not* actually
reflect the stack which initiated the async operation. Instead
it contains the chain of listeners which will run when
the async operation completes - its awaiters.
TEST=ci
Change-Id: Ie7309c9b1c39246e0fd4c14f7b9c515bcdfbbe10
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311384
Reviewed-by: Derek Xu <derekx@google.com>