[debugger] break at each initialization in a multiple var declaration.

R=rossberg@chromium.org
BUG=v8:4807
LOG=N

Review URL: https://codereview.chromium.org/1768973002

Cr-Commit-Position: refs/heads/master@{#34531}
This commit is contained in:
yangguo 2016-03-07 03:59:10 -08:00 committed by Commit bot
parent e3a041c5d3
commit ee98147ea0
9 changed files with 105 additions and 36 deletions

View File

@ -230,22 +230,20 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
if (IsImmutableVariableMode(descriptor_->mode)) {
arguments->Add(value, zone());
value = NULL; // zap the value to avoid the unnecessary assignment
// Construct the call to Runtime_InitializeConstGlobal
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (1 or 2).
initialize =
factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments,
descriptor_->initialization_pos);
initialize = factory()->NewCallRuntime(Runtime::kInitializeConstGlobal,
arguments, value->position());
value = NULL; // zap the value to avoid the unnecessary assignment
} else {
// Add language mode.
// We may want to pass singleton to avoid Literal allocations.
LanguageMode language_mode = initialization_scope->language_mode();
arguments->Add(factory()->NewNumberLiteral(language_mode,
descriptor_->declaration_pos),
zone());
arguments->Add(
factory()->NewNumberLiteral(language_mode, RelocInfo::kNoPosition),
zone());
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@ -253,12 +251,11 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
// which is why we need to generate a separate assignment node.
if (value != NULL && !descriptor_->scope->inside_with()) {
arguments->Add(value, zone());
value = NULL; // zap the value to avoid the unnecessary assignment
// Construct the call to Runtime_InitializeVarGlobal
// and add it to the initialization statement block.
initialize =
factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments,
descriptor_->declaration_pos);
initialize = factory()->NewCallRuntime(Runtime::kInitializeVarGlobal,
arguments, value->position());
value = NULL; // zap the value to avoid the unnecessary assignment
} else {
initialize = NULL;
}
@ -282,8 +279,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
DCHECK_NOT_NULL(proxy->var());
DCHECK_NOT_NULL(value);
// Add break location for destructured sub-pattern.
int pos =
IsSubPattern() ? pattern->position() : descriptor_->initialization_pos;
int pos = IsSubPattern() ? pattern->position() : value->position();
Assignment* assignment =
factory()->NewAssignment(Token::INIT, proxy, value, pos);
block_->statements()->Add(
@ -300,8 +296,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
// property).
VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
// Add break location for destructured sub-pattern.
int pos =
IsSubPattern() ? pattern->position() : descriptor_->initialization_pos;
int pos = IsSubPattern() ? pattern->position() : value->position();
Assignment* assignment =
factory()->NewAssignment(Token::INIT, proxy, value, pos);
block_->statements()->Add(

View File

@ -2747,7 +2747,7 @@ TEST(DebugStepKeyedLoadLoop) {
foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
// With stepping all break locations are hit.
CHECK_EQ(44, break_point_hit_count);
CHECK_EQ(45, break_point_hit_count);
v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded(env->GetIsolate());
@ -2797,7 +2797,7 @@ TEST(DebugStepKeyedStoreLoop) {
foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
// With stepping all break locations are hit.
CHECK_EQ(44, break_point_hit_count);
CHECK_EQ(45, break_point_hit_count);
v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded(env->GetIsolate());
@ -2842,7 +2842,7 @@ TEST(DebugStepNamedLoadLoop) {
foo->Call(context, env->Global(), 0, NULL).ToLocalChecked();
// With stepping all break locations are hit.
CHECK_EQ(65, break_point_hit_count);
CHECK_EQ(66, break_point_hit_count);
v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
CheckDebuggerUnloaded(env->GetIsolate());
@ -2886,8 +2886,7 @@ static void DoDebugStepNamedStoreLoop(int expected) {
// Test of the stepping mechanism for named load in a loop.
TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(35); }
// Test the stepping mechanism with different ICs.
TEST(DebugStepLinearMixedICs) {
@ -3294,7 +3293,7 @@ TEST(DebugStepForContinue) {
v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
CHECK_EQ(5, result->Int32Value(context).FromJust());
CHECK_EQ(62, break_point_hit_count);
CHECK_EQ(63, break_point_hit_count);
// Looping 100 times.
step_action = StepIn;
@ -3302,7 +3301,7 @@ TEST(DebugStepForContinue) {
v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
CHECK_EQ(50, result->Int32Value(context).FromJust());
CHECK_EQ(557, break_point_hit_count);
CHECK_EQ(558, break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(isolate, nullptr);
@ -3348,7 +3347,7 @@ TEST(DebugStepForBreak) {
v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
CHECK_EQ(9, result->Int32Value(context).FromJust());
CHECK_EQ(64, break_point_hit_count);
CHECK_EQ(65, break_point_hit_count);
// Looping 100 times.
step_action = StepIn;
@ -3356,7 +3355,7 @@ TEST(DebugStepForBreak) {
v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
CHECK_EQ(99, result->Int32Value(context).FromJust());
CHECK_EQ(604, break_point_hit_count);
CHECK_EQ(605, break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(isolate, nullptr);

View File

@ -0,0 +1,74 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-debug-as debug
// Test we break at every assignment in a var-statement with multiple
// variable declarations.
var exception = null;
var log = []
function f() {
var l1 = 1, // l
l2, // m
l3 = 3; // n
let l4, // o
l5 = 5, // p
l6 = 6; // q
const l7 = 7, // r
l8 = 8, // s
l9 = 9; // t
return 0; // u
} // v
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var line = exec_state.frame(0).sourceLineText();
var col = exec_state.frame(0).sourceColumn();
print(line);
var match = line.match(/\/\/ (\w)$/);
assertEquals(2, match.length);
log.push(match[1] + col);
if (match[1] != "v") {
exec_state.prepareStep(Debug.StepAction.StepIn);
}
} catch (e) {
exception = e;
}
}
var Debug = debug.Debug;
Debug.setListener(listener);
debugger; // a
var g1 = 1, // b
g2 = 2, // c
g3; // d
let g4 = 4, // e
g5, // f
g6 = 6; // g
const g7 = 7, // h
g8 = 8, // i
g9 = f(); // j
Debug.setListener(null);
assertNull(exception);
// Note that let declarations, if not explicitly initialized, implicitly
// initialize to undefined.
var expected = [
"a0", // debugger statement
"b9","c9", // global var
"e9","f4","g9", // global let
"h11","i11","j11", // global const
"l11","n11", // local var
"o6","p11","q11", // local let
"r13","s13","t13", // local const
"u2","v0", // return
];
assertEquals(expected, log);

View File

@ -45,5 +45,5 @@ debugger; // Break
f(); // Break
Debug.setListener(null); // Break
assertEquals(86, break_count);
assertEquals(87, break_count);
assertNull(exception);

View File

@ -48,7 +48,8 @@ assertNull(exception);
assertEquals([
"a0",
"b0",
"b44",
"b13",
"d2b13",
"e0b13",
"b25",

View File

@ -108,12 +108,12 @@ var expected = [
"i12","i10","i11","I4","i11","I4","i11","I4","i11",
// For-of-let: [Symbol.iterator](), next(), body, next(), ...
"j16","j14","j15","J4","j15","J4","j15","J4","j15",
// For-var: var decl, condition, body, next, condition, body, ...
"k7","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
// For-var: var decl, init, condition, body, next, condition, body, ...
"k7","k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
// For: init, condition, body, next, condition, body, ...
"l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16",
// For-let: init, condition, body, next, condition, body, ...
"m7","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
"m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
// Exit.
"y0","z0",
]

View File

@ -42,5 +42,5 @@ Debug.setListener(null); // c
assertNull(exception);
assertEquals("default", result);
assertEquals(["a0","b0","f18b13","d2f18b13","e0f18b13","g2b13","h0b13","c0"],
assertEquals(["a0","b13","f18b13","d2f18b13","e0f18b13","g2b13","h0b13","c0"],
log);

View File

@ -54,8 +54,8 @@ assertEquals(42, get);
assertEquals([
"a0",
"b0", "h4b20", "i2b20", // [[Has]]
"c0", "j4c15", "k2c15", // [[Get]]
"d0", "l4d11", "m2d11", // [[Set]]
"b17", "h4b20", "i2b20", // [[Has]]
"c15", "j4c15", "k2c15", // [[Get]]
"d0", "l4d11", "m2d11", // [[Set]]
"g0"
], log);

View File

@ -77,8 +77,8 @@ f();
g();
// Assert that break point is set at expected location.
assertTrue(Debug.showBreakPoints(f).indexOf("[B0]var baz = bar;") > 0);
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]var baz = bar;") > 0);
assertTrue(Debug.showBreakPoints(f).indexOf("var baz = [B0]bar;") > 0);
assertTrue(Debug.showBreakPoints(g).indexOf("var baz = [B0]bar;") > 0);
assertEquals(2, listened);
assertNull(exception);