[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>
This commit is contained in:
Derek Xu 2024-01-23 20:12:42 +00:00 committed by Commit Queue
parent 0dcef64e67
commit e727f4ecbd
3 changed files with 93 additions and 1 deletions

View file

@ -0,0 +1,85 @@
// Copyright (c) 2024, 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.
// Regression test for https://dartbug.com/53996.
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
// AUTOGENERATED START
//
// Update these constants by running:
//
// dart pkg/vm_service/test/update_line_numbers.dart <test.dart>
//
const LINE_A = 27;
// AUTOGENERATED END
bool debug = false;
bool bar(int i) {
if (i == 2) {
if (debug) {
print('woke up'); // LINE_A
}
return true;
}
return false;
}
void foo() {
final List<int> data = [1, 2, 3];
for (int i in data) {
if (bar(i)) {
break;
}
}
}
void testeeMain() {
// Trigger optimization of [foo].
for (int i = 0; i < 20; i++) {
foo();
}
debug = true;
foo();
}
final tests = <IsolateTest>[
hasPausedAtStart,
setBreakpointAtLine(LINE_A),
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_A),
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
try {
await service.evaluateInFrame(
isolateId,
1,
'data.length',
);
fail('Expected evaluateInFrame to throw an RPCError');
} on RPCError catch (e) {
expect(e.code, RPCErrorKind.kExpressionCompilationError.code);
expect(e.message, 'Expression compilation error');
}
},
];
void main([args = const <String>[]]) => runIsolateTests(
args,
tests,
'evaluate_optimized_out_variable_test.dart',
testeeConcurrent: testeeMain,
pauseOnStart: true,
extraArgs: const [
'--deterministic',
'--prune-dead-locals',
'--optimization-counter-threshold=10',
],
);

View file

@ -1111,7 +1111,8 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
type_arguments_available = true;
type_arguments ^= value.ptr();
} else if (!name.Equals(Symbols::This()) &&
!IsSyntheticVariableName(name)) {
!IsSyntheticVariableName(name) &&
value.ptr() != Object::optimized_out().ptr()) {
if (IsPrivateVariableName(name)) {
name = Symbols::New(Thread::Current(), String::ScrubName(name));
}

View file

@ -4853,6 +4853,11 @@ static ObjectPtr EvaluateCompiledExpressionHelper(
const TypeArguments& type_arguments) {
// type_arguments is null if all type arguments are dynamic.
if (type_definitions.Length() == 0 || type_arguments.IsNull()) {
#if defined(DEBUG)
for (intptr_t i = 0; i < arguments.Length(); ++i) {
ASSERT(arguments.At(i) != Object::optimized_out().ptr());
}
#endif // defined(DEBUG)
return DartEntry::InvokeFunction(eval_function, arguments);
}
@ -4863,6 +4868,7 @@ static ObjectPtr EvaluateCompiledExpressionHelper(
Object& arg = Object::Handle(zone);
for (intptr_t i = 0; i < arguments.Length(); ++i) {
arg = arguments.At(i);
ASSERT(arg.ptr() != Object::optimized_out().ptr());
real_arguments.SetAt(i + 1, arg);
}