mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Count instruction and spill code bytes in Ion basic blocks, bug 814489. r=pierron
This commit is contained in:
parent
54bc84b0b4
commit
c0353ffd5e
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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(']');
|
||||
|
Loading…
Reference in New Issue
Block a user