Count instruction and spill code bytes in Ion basic blocks, bug 814489. r=pierron

This commit is contained in:
Brian Hackett 2012-11-23 23:18:59 -05:00
parent 54bc84b0b4
commit c0353ffd5e
3 changed files with 99 additions and 13 deletions

View File

@ -1435,6 +1435,70 @@ CodeGenerator::maybeCreateScriptCounts()
return counts;
}
// Structure for managing the state tracked for a block by script counters.
struct ScriptCountBlockState
{
IonBlockCounts █
MacroAssembler &masm;
Sprinter printer;
uint32 instructionBytes;
uint32 spillBytes;
// Pointer to instructionBytes, spillBytes, or NULL, depending on the last
// instruction processed.
uint32 *last;
uint32 lastLength;
public:
ScriptCountBlockState(IonBlockCounts *block, MacroAssembler *masm)
: block(*block), masm(*masm),
printer(GetIonContext()->cx),
instructionBytes(0), spillBytes(0), last(NULL), lastLength(0)
{
}
bool init()
{
if (!printer.init())
return false;
// Bump the hit count for the block at the start. This code is not
// included in either the text for the block or the instruction byte
// counts.
masm.inc64(AbsoluteAddress(block.addressOfHitCount()));
// Collect human readable assembly for the code generated in the block.
masm.setPrinter(&printer);
return true;
}
void visitInstruction(LInstruction *ins)
{
if (last)
*last += masm.size() - lastLength;
lastLength = masm.size();
last = ins->isMoveGroup() ? &spillBytes : &instructionBytes;
// Prefix stream of assembly instructions with their LIR instruction name.
printer.printf("[%s]\n", ins->opName());
}
~ScriptCountBlockState()
{
masm.setPrinter(NULL);
if (last)
*last += masm.size() - lastLength;
block.setCode(printer.string());
block.setInstructionBytes(instructionBytes);
block.setSpillBytes(spillBytes);
}
};
bool
CodeGenerator::generateBody()
{
@ -1451,19 +1515,18 @@ CodeGenerator::generateBody()
return false;
iter++;
mozilla::Maybe<Sprinter> printer;
mozilla::Maybe<ScriptCountBlockState> blockCounts;
if (counts) {
masm.inc64(AbsoluteAddress(counts->block(i).addressOfHitCount()));
printer.construct(GetIonContext()->cx);
if (!printer.ref().init())
blockCounts.construct(&counts->block(i), &masm);
if (!blockCounts.ref().init())
return false;
masm.setPrinter(printer.addr());
}
for (; iter != current->end(); iter++) {
IonSpew(IonSpew_Codegen, "instruction %s", iter->opName());
if (counts)
printer.ref().printf("[%s]\n", iter->opName());
blockCounts.ref().visitInstruction(*iter);
if (iter->safepoint() && pushedArgumentSlots_.length()) {
if (!markArgumentSlots(iter->safepoint()))
@ -1475,11 +1538,6 @@ CodeGenerator::generateBody()
}
if (masm.oom())
return false;
if (counts) {
counts->block(i).setCode(printer.ref().string());
masm.setPrinter(NULL);
}
}
JS_ASSERT(pushedArgumentSlots_.empty());

View File

@ -420,9 +420,14 @@ struct IonBlockCounts
// Hit count for this block.
uint64 hitCount_;
// Information about the code generated for this block.
// Text information about the code generated for this block.
char *code_;
// Number of bytes of code generated in this block. Spill code is counted
// separately from other, instruction implementing code.
uint32 instructionBytes_;
uint32 spillBytes_;
public:
bool init(uint32 id, uint32 offset, uint32 numSuccessors) {
@ -485,6 +490,22 @@ struct IonBlockCounts
const char *code() const {
return code_;
}
void setInstructionBytes(uint32 bytes) {
instructionBytes_ = bytes;
}
uint32 instructionBytes() const {
return instructionBytes_;
}
void setSpillBytes(uint32 bytes) {
spillBytes_ = bytes;
}
uint32 spillBytes() const {
return spillBytes_;
}
};
// Execution information for a compiled script which may persist after the

View File

@ -328,7 +328,8 @@ js_DumpPCCounts(JSContext *cx, HandleScript script, js::Sprinter *sp)
Sprint(sp, "BB #%lu [%05u]", block.id(), block.offset());
for (size_t j = 0; j < block.numSuccessors(); j++)
Sprint(sp, " -> #%lu", block.successor(j));
Sprint(sp, " :: %llu hits\n", block.hitCount());
Sprint(sp, " :: %llu hits %u instruction bytes %u spill bytes\n",
block.hitCount(), block.instructionBytes(), block.spillBytes());
Sprint(sp, "%s\n", block.code());
}
ionCounts = ionCounts->previous();
@ -7209,6 +7210,12 @@ GetPCCountJSON(JSContext *cx, const ScriptAndCounts &sac, StringBuffer &buf)
return false;
buf.append(str);
AppendJSONProperty(buf, "instructionBytes");
NumberValueToStringBuffer(cx, Int32Value(block.instructionBytes()), buf);
AppendJSONProperty(buf, "spillBytes");
NumberValueToStringBuffer(cx, Int32Value(block.spillBytes()), buf);
buf.append('}');
}
buf.append(']');