зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1304569 - JS Code Coverage: Simplify checks for the last found case-statement body. r=bhackett
This commit is contained in:
Родитель
cd15c1d8a0
Коммит
30db580939
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
s = newGlobal()
|
||||||
|
evalcx("\
|
||||||
|
switch (0) {\
|
||||||
|
default: break;\
|
||||||
|
case 1:\
|
||||||
|
this.s += this.s;\
|
||||||
|
g(h(\"\", 2));\
|
||||||
|
break;\
|
||||||
|
break\
|
||||||
|
}\
|
||||||
|
", s)
|
||||||
|
evalcx("getLcovInfo()", s)
|
|
@ -171,6 +171,7 @@ LCovSource::writeScript(JSScript* script)
|
||||||
size_t branchId = 0;
|
size_t branchId = 0;
|
||||||
size_t tableswitchExitOffset = 0;
|
size_t tableswitchExitOffset = 0;
|
||||||
for (jsbytecode* pc = script->code(); pc != end; pc = GetNextPc(pc)) {
|
for (jsbytecode* pc = script->code(); pc != end; pc = GetNextPc(pc)) {
|
||||||
|
MOZ_ASSERT(script->code() <= pc && pc < end);
|
||||||
JSOp op = JSOp(*pc);
|
JSOp op = JSOp(*pc);
|
||||||
bool jump = IsJumpOpcode(op) || op == JSOP_TABLESWITCH;
|
bool jump = IsJumpOpcode(op) || op == JSOP_TABLESWITCH;
|
||||||
bool fallsthrough = BytecodeFallsThrough(op) && op != JSOP_GOSUB;
|
bool fallsthrough = BytecodeFallsThrough(op) && op != JSOP_GOSUB;
|
||||||
|
@ -257,6 +258,8 @@ LCovSource::writeScript(JSScript* script)
|
||||||
// Get the default and exit pc
|
// Get the default and exit pc
|
||||||
jsbytecode* exitpc = pc + tableswitchExitOffset;
|
jsbytecode* exitpc = pc + tableswitchExitOffset;
|
||||||
jsbytecode* defaultpc = pc + GET_JUMP_OFFSET(pc);
|
jsbytecode* defaultpc = pc + GET_JUMP_OFFSET(pc);
|
||||||
|
MOZ_ASSERT(script->code() <= exitpc && exitpc <= end);
|
||||||
|
MOZ_ASSERT(script->code() <= defaultpc && defaultpc < end);
|
||||||
MOZ_ASSERT(defaultpc > pc && defaultpc <= exitpc);
|
MOZ_ASSERT(defaultpc > pc && defaultpc <= exitpc);
|
||||||
|
|
||||||
// Get the low and high from the tableswitch
|
// Get the low and high from the tableswitch
|
||||||
|
@ -269,6 +272,7 @@ LCovSource::writeScript(JSScript* script)
|
||||||
jsbytecode* firstcasepc = exitpc;
|
jsbytecode* firstcasepc = exitpc;
|
||||||
for (size_t j = 0; j < numCases; j++) {
|
for (size_t j = 0; j < numCases; j++) {
|
||||||
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
||||||
|
MOZ_ASSERT(script->code() <= testpc && testpc < end);
|
||||||
if (testpc < firstcasepc)
|
if (testpc < firstcasepc)
|
||||||
firstcasepc = testpc;
|
firstcasepc = testpc;
|
||||||
}
|
}
|
||||||
|
@ -284,19 +288,26 @@ LCovSource::writeScript(JSScript* script)
|
||||||
size_t caseId = 0;
|
size_t caseId = 0;
|
||||||
for (size_t i = 0; i < numCases; i++) {
|
for (size_t i = 0; i < numCases; i++) {
|
||||||
jsbytecode* casepc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * i);
|
jsbytecode* casepc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * i);
|
||||||
|
MOZ_ASSERT(script->code() <= casepc && casepc < end);
|
||||||
// The case is not present, and jumps to the default pc if used.
|
// The case is not present, and jumps to the default pc if used.
|
||||||
if (casepc == pc)
|
if (casepc == pc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// PCs might not be in increasing order of case indexes.
|
// PCs might not be in increasing order of case indexes.
|
||||||
jsbytecode* lastcasepc = firstcasepc - 1;
|
jsbytecode* lastcasepc = firstcasepc - 1;
|
||||||
|
bool foundLastCase = false;
|
||||||
for (size_t j = 0; j < numCases; j++) {
|
for (size_t j = 0; j < numCases; j++) {
|
||||||
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
||||||
if (lastcasepc < testpc && (testpc < casepc || (j < i && testpc == casepc)))
|
MOZ_ASSERT(script->code() <= testpc && testpc < end);
|
||||||
|
if (lastcasepc < testpc && (testpc < casepc || (j < i && testpc == casepc))) {
|
||||||
lastcasepc = testpc;
|
lastcasepc = testpc;
|
||||||
|
foundLastCase = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (casepc != lastcasepc) {
|
// If multiple case instruction have the same code block, only
|
||||||
|
// register the code coverage the first time we hit this case.
|
||||||
|
if (!foundLastCase || casepc != lastcasepc) {
|
||||||
// Case (i + low)
|
// Case (i + low)
|
||||||
uint64_t caseHits = 0;
|
uint64_t caseHits = 0;
|
||||||
if (sc) {
|
if (sc) {
|
||||||
|
@ -306,10 +317,15 @@ LCovSource::writeScript(JSScript* script)
|
||||||
|
|
||||||
// Remove fallthrough.
|
// Remove fallthrough.
|
||||||
fallsThroughHits = 0;
|
fallsThroughHits = 0;
|
||||||
if (casepc != firstcasepc) {
|
if (foundLastCase) {
|
||||||
|
// Walk from the previous case to the current one to
|
||||||
|
// check if it fallthrough into the current block.
|
||||||
|
MOZ_ASSERT(lastcasepc != firstcasepc - 1);
|
||||||
jsbytecode* endpc = lastcasepc;
|
jsbytecode* endpc = lastcasepc;
|
||||||
while (GetNextPc(endpc) < casepc)
|
while (GetNextPc(endpc) < casepc) {
|
||||||
endpc = GetNextPc(endpc);
|
endpc = GetNextPc(endpc);
|
||||||
|
MOZ_ASSERT(script->code() <= endpc && endpc < end);
|
||||||
|
}
|
||||||
|
|
||||||
if (BytecodeFallsThrough(JSOp(*endpc)))
|
if (BytecodeFallsThrough(JSOp(*endpc)))
|
||||||
fallsThroughHits = script->getHitCount(endpc);
|
fallsThroughHits = script->getHitCount(endpc);
|
||||||
|
@ -340,22 +356,35 @@ LCovSource::writeScript(JSScript* script)
|
||||||
|
|
||||||
// Look for the last case entry before the default pc.
|
// Look for the last case entry before the default pc.
|
||||||
jsbytecode* lastcasepc = firstcasepc - 1;
|
jsbytecode* lastcasepc = firstcasepc - 1;
|
||||||
|
bool foundLastCase = false;
|
||||||
for (size_t j = 0; j < numCases; j++) {
|
for (size_t j = 0; j < numCases; j++) {
|
||||||
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
jsbytecode* testpc = pc + GET_JUMP_OFFSET(jumpTable + JUMP_OFFSET_LEN * j);
|
||||||
if (lastcasepc < testpc && testpc <= defaultpc)
|
MOZ_ASSERT(script->code() <= testpc && testpc < end);
|
||||||
|
if (lastcasepc < testpc && testpc <= defaultpc) {
|
||||||
lastcasepc = testpc;
|
lastcasepc = testpc;
|
||||||
|
foundLastCase = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastcasepc == defaultpc)
|
// Set defaultHasOwnClause to false, if one of the case
|
||||||
|
// statement has the same pc as the default block. Which implies
|
||||||
|
// that the previous loop already encoded the coverage
|
||||||
|
// information for the current block.
|
||||||
|
if (foundLastCase && lastcasepc == defaultpc)
|
||||||
defaultHasOwnClause = false;
|
defaultHasOwnClause = false;
|
||||||
|
|
||||||
// Look if the last case entry fallthrough to the default case,
|
// Look if the last case entry fallthrough to the default case,
|
||||||
// in which case we have to remove the number of fallthrough
|
// in which case we have to remove the number of fallthrough
|
||||||
// hits out of the default case hits.
|
// hits out of the default case hits.
|
||||||
if (sc && lastcasepc != pc) {
|
if (sc && foundLastCase) {
|
||||||
|
// Walk from the previous case to the current one to check
|
||||||
|
// if it fallthrough into the default block.
|
||||||
|
MOZ_ASSERT(lastcasepc != firstcasepc - 1);
|
||||||
jsbytecode* endpc = lastcasepc;
|
jsbytecode* endpc = lastcasepc;
|
||||||
while (GetNextPc(endpc) < defaultpc)
|
while (GetNextPc(endpc) < defaultpc) {
|
||||||
endpc = GetNextPc(endpc);
|
endpc = GetNextPc(endpc);
|
||||||
|
MOZ_ASSERT(script->code() <= endpc && endpc < end);
|
||||||
|
}
|
||||||
|
|
||||||
if (BytecodeFallsThrough(JSOp(*endpc)))
|
if (BytecodeFallsThrough(JSOp(*endpc)))
|
||||||
fallsThroughHits = script->getHitCount(endpc);
|
fallsThroughHits = script->getHitCount(endpc);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче