v8/test/mjsunit/debug-stepframe-clearing.js
mvstanton 35c3d47e88 Vector ICs: Clear the vector ic slots appropriately during debugging.
When the debugger is active, a host of connected functions get an associated
DebugInfo structure, and their code is copied. The debugger uses the original
code to occasionally patch ICs with their initial value. Although IC learning
can occur, it's thrown away often, depending on the constellation of
breakpoints active or deactivating. Finally, feedback is discarded when the
debugger is turned off.

The type feedback vector needs to be brought into line with this behavior, so
now the debugger clears it's IC slots at appropriate bottlenecks in debug.cc.

R=yangguo@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#27289}
2015-03-19 08:04:06 +00:00

98 lines
3.2 KiB
JavaScript

// Copyright 2015 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
// This test ensures that IC learning doesn't interfere with stepping into
// property accessor. f1()'s ICs are allowed to learn to a monomorphic state,
// and the breakpoints flooding get() are allowed to expire, then we ensure
// that we can step into get() again later (when k == 1).
function f1() {
for (var k = 0; k < 2; k++) { // Break 1
var v10 = 0; // Line 2
for (var i = 0; i < 10; i++) { // Line 3
var v12 = o.slappy; // Line 4
var v13 = 3 // Line 5
} // Line 6
print("break here"); // Break 3
} // Line 8
print("exiting f1"); // Line 9 (dummy break)
}
function get() {
var g0 = 0; // Break 2
var g1 = 1;
return 3;
}
var o = {};
Object.defineProperty(o, "slappy", { get : get });
Debug = debug.Debug;
var break_count = 0
var exception = null;
var bp_f1_line7;
var bp_f1_line9;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var line = exec_state.frame(0).sourceLineText();
print(line);
var match = line.match(/\/\/ Break (\d+)$/);
assertEquals(2, match.length);
var match_value = parseInt(match[1]);
if (break_count >= 0 && break_count < 2) {
// 0, 1: Keep stepping through frames.
assertEquals(break_count, match_value);
exec_state.prepareStep(Debug.StepAction.StepFrame, 1);
} else if (break_count === 2) {
// 2: let the code run to a breakpoint we set. The load should
// go monomorphic.
assertEquals(break_count, match_value);
} else if (break_count === 3) {
// 3: back to frame stepping. Does the monomorphic slappy accessor
// call still have the ability to break like before?
assertEquals(break_count, match_value);
Debug.clearBreakPoint(bp_f1_line7);
exec_state.prepareStep(Debug.StepAction.StepFrame, 1);
} else {
assertEquals(4, break_count);
assertEquals(2, match_value);
// Apparently we can still stop in the accessor even though we cleared
// breakpoints earlier and there was a monomorphic step.
// Allow running to completion now.
Debug.clearBreakPoint(bp_f1_line9);
}
break_count++;
} catch (e) {
print(e + e.stack);
exception = e;
}
}
for (var j = 1; j < 3; j++) {
break_count = 0;
Debug.setListener(listener);
// Breakpoints are added here rather than in the listener because their
// addition causes a full (clearing) gc that clears type feedback when we
// want to let it build up. Also, bp_f1_line9 is set simply because if we
// handled then deleted bp_f1_line7, then the debugger clears DebugInfo from
// f1 while we are still using it, again, resetting type feedback which is
// undesirable.
bp_f1_line7 = Debug.setBreakPoint(f1, 7);
bp_f1_line9 = Debug.setBreakPoint(f1, 9);
debugger; // Break 0
f1();
Debug.setListener(null);
assertTrue(break_count === 5);
}
assertNull(exception);