Skip to content

Commit 2b8ada7

Browse files
arnabde03facebook-github-bot
authored andcommitted
Set breakpoints on multiple non-contiguous bytecode blocks per line
Summary: One line in source code may be translated to multiple blocks of bytecodes. For example, the local iterator optimization in HackC creates two copies of the foreach loop body. We need to set breakpoints on each of these blocks as long as they are not overlapping or contiguous. Unfortunately, there are some cases where this may lead to spurious breakpoints being set. For example, multiline call expressions produce two bytecode blocks for the same line that are not contiguous, so there will be two breakpoints set. Reviewed By: paulbiss Differential Revision: D68462841 fbshipit-source-id: 824e55946b9a18babad658b1f926f5e26721a46f
1 parent 543caf6 commit 2b8ada7

File tree

5 files changed

+35
-10
lines changed

5 files changed

+35
-10
lines changed

hphp/runtime/ext/vsdebug/breakpoint_command.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ bool SetBreakpointsCommand::executeImpl(
125125
// Make a map of line -> breakpoint for all breakpoints in this file before
126126
// this set breakpoints operation.
127127
std::unordered_map<int, Breakpoint*> oldBpLines;
128-
const auto oldBpIds = bpMgr->getBreakpointIdsForPath(filePath);
128+
const auto oldBpIds = bpMgr->getBreakpointIdsForPath(path);
129129
for (auto it = oldBpIds.begin(); it != oldBpIds.end(); it++) {
130130
Breakpoint* bp = bpMgr->getBreakpointById(*it);
131131
std::pair<int, Breakpoint*> pair;

hphp/runtime/vm/debugger-hook.cpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -528,24 +528,30 @@ bool phpAddBreakPointLine(const Unit* unit, int line) {
528528
return false;
529529
}
530530

531-
// One source line may refer to multiple bytecodes. We want to set the
532-
// breakpoint only on the first bytecode. There is one exeption:
533-
// If the bytecodes refer to different functions, set breakpoints on
534-
// one bytecode of each function. This can happen for lambdas.
531+
// One source line may refer to multiple blocks of bytecodes, possibly in
532+
// different functions (in case of lambdas).
533+
// We want to set the breakpoint only on the first bytecode of each block,
534+
// unless they are overlapping or contiguous.
535535
// Add to the breakpoint filter and the line filter.
536536
assertx(funcOffsets.size() > 0);
537-
DEBUG_ONLY std::unordered_set<const Func*> seenFuncs;
538537
for (auto const& offsets : funcOffsets) {
539538
auto f = offsets.first;
540-
assertx(seenFuncs.find(f) == seenFuncs.end());
541-
if (!offsets.second.empty()) {
542-
auto bpOffset = offsets.second.front().base;
539+
auto currPast = -1;
540+
// offsets are sorted.
541+
for (auto const& offset : offsets.second) {
542+
auto bpOffset = offset.base;
543+
if (bpOffset <= currPast) {
544+
// Overlapping or contiguous bytecode blocks for the same source line.
545+
// Do not add a breakpoint, only update the currPast.
546+
currPast = offset.past > currPast ? offset.past : currPast;
547+
continue;
548+
}
549+
currPast = offset.past;
543550
TRACE(3, "Adding breakpoint at %s::%d, Op %s.\n",
544551
f->name()->data(), bpOffset, opcodeToName(f->getOp(bpOffset)));
545552
phpAddBreakPoint(f, bpOffset);
546553
auto pc = f->at(bpOffset);
547554
RID().m_lineBreakPointFilter.addPC(pc);
548-
if (debug) seenFuncs.insert(f);
549555
}
550556
}
551557
return true;

hphp/test/slow/ext_vsdebug/breakpoints.php

+12
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@
150150
"body" => dict[
151151
"breakpoints" => vec[]
152152
]]);
153+
154+
$breakpoints = vec[
155+
dict[
156+
"path" => __FILE__ . ".test",
157+
"breakpoints" => vec[
158+
dict["line" => 34, "calibratedLine" => 34, "condition" => ""],
159+
]]
160+
];
161+
setBreakpoints($breakpoints, true);
162+
resumeTarget();
163+
164+
verifyBpHit($breakpoints[0]['path'], $breakpoints[0]['breakpoints'][0]);
153165
resumeTarget();
154166

155167
// Verify hard break was hit.

hphp/test/slow/ext_vsdebug/breakpoints.php.test

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ for ($i = 0; $i < 10; $i++) {
2929
$y++;
3030
}
3131

32+
$v = vec[1, 2, 3];
33+
$a = 0;
34+
foreach($v as $u) {
35+
$a = $a + $u;
36+
}
37+
3238
hphp_debug_break();
3339

3440
$dir = dirname(__FILE__);

hphp/test/slow/ext_vsdebug/common.inc

+1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ function vsDebugLaunch($scriptPath, $sendDefaultInit = true, $breakpoints = vec[
330330
'-vEval.JitDisabledByVSDebug='.$disable_jit,
331331
'-vEval.JitPGO=false',
332332
'-vHack.Lang.OptimizeLocalLifetimes=0',
333+
'-vHack.Lang.OptimizeLocalIterators = true',
333334
$scriptPath,
334335
];
335336
} else {

0 commit comments

Comments
 (0)