mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 864216 - Allow generating IonScriptCounts for asm.js compiled functions, r=luke.
This commit is contained in:
parent
75a7f384d9
commit
c82520f2a0
@ -1321,7 +1321,9 @@ class ModuleCompiler
|
||||
return false;
|
||||
return exits_.add(p, Move(exitDescriptor), *exitIndex);
|
||||
}
|
||||
|
||||
bool addFunctionCounts(IonScriptCounts *counts) {
|
||||
return module_->addFunctionCounts(counts);
|
||||
}
|
||||
|
||||
void setSecondPassComplete() {
|
||||
JS_ASSERT(currentPass_ == 2);
|
||||
@ -2311,6 +2313,12 @@ js::AsmJSModuleObjectToModule(JSObject *obj)
|
||||
return *(AsmJSModule *)obj->getReservedSlot(ASM_CODE_RESERVED_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
bool
|
||||
js::IsAsmJSModuleObject(JSObject *obj)
|
||||
{
|
||||
return obj->getClass() == &AsmJSModuleClass;
|
||||
}
|
||||
|
||||
static const unsigned ASM_MODULE_FUNCTION_MODULE_OBJECT_SLOT = 0;
|
||||
|
||||
JSObject &
|
||||
@ -4431,6 +4439,12 @@ GenerateAsmJSCode(ModuleCompiler &m, ModuleCompiler::Func &func,
|
||||
if (!m.collectAccesses(mirGen))
|
||||
return false;
|
||||
|
||||
ion::IonScriptCounts *counts = codegen->extractUnassociatedScriptCounts();
|
||||
if (counts && !m.addFunctionCounts(counts)) {
|
||||
js_delete(counts);
|
||||
return false;
|
||||
}
|
||||
|
||||
// A single MacroAssembler is reused for all function compilations so
|
||||
// that there is a single linear code segment for each module. To avoid
|
||||
// spiking memory, a LifoAllocScope in the caller frees all MIR/LIR
|
||||
@ -5564,3 +5578,8 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
AsmJSModule::~AsmJSModule()
|
||||
{
|
||||
for (size_t i = 0; i < numFunctionCounts(); i++)
|
||||
js_delete(functionCounts(i));
|
||||
}
|
||||
|
@ -305,6 +305,7 @@ class AsmJSModule
|
||||
#if defined(JS_CPU_ARM)
|
||||
typedef Vector<ion::AsmJSBoundsCheck, 0, SystemAllocPolicy> BoundsCheckVector;
|
||||
#endif
|
||||
typedef Vector<ion::IonScriptCounts *, 0, SystemAllocPolicy> FunctionCountsVector;
|
||||
|
||||
GlobalVector globals_;
|
||||
ExitVector exits_;
|
||||
@ -334,6 +335,8 @@ class AsmJSModule
|
||||
|
||||
PostLinkFailureInfo postLinkFailureInfo_;
|
||||
|
||||
FunctionCountsVector functionCounts_;
|
||||
|
||||
public:
|
||||
explicit AsmJSModule(JSContext *cx)
|
||||
: numGlobalVars_(0),
|
||||
@ -350,6 +353,8 @@ class AsmJSModule
|
||||
postLinkFailureInfo_(cx)
|
||||
{}
|
||||
|
||||
~AsmJSModule();
|
||||
|
||||
void trace(JSTracer *trc) {
|
||||
for (unsigned i = 0; i < globals_.length(); i++)
|
||||
globals_[i].trace(trc);
|
||||
@ -425,6 +430,9 @@ class AsmJSModule
|
||||
*exitIndex = unsigned(exits_.length());
|
||||
return exits_.append(Exit(ffiIndex));
|
||||
}
|
||||
bool addFunctionCounts(ion::IonScriptCounts *counts) {
|
||||
return functionCounts_.append(counts);
|
||||
}
|
||||
|
||||
bool addExportedFunction(RawFunction fun, PropertyName *maybeFieldName,
|
||||
MoveRef<ArgCoercionVector> argCoercions, ReturnType returnType)
|
||||
@ -468,6 +476,12 @@ class AsmJSModule
|
||||
const Exit &exit(unsigned i) const {
|
||||
return exits_[i];
|
||||
}
|
||||
unsigned numFunctionCounts() const {
|
||||
return functionCounts_.length();
|
||||
}
|
||||
ion::IonScriptCounts *functionCounts(unsigned i) {
|
||||
return functionCounts_[i];
|
||||
}
|
||||
|
||||
// An Exit holds bookkeeping information about an exit; the ExitDatum
|
||||
// struct overlays the actual runtime data stored in the global data
|
||||
@ -661,6 +675,9 @@ class AsmJSModule
|
||||
extern AsmJSModule &
|
||||
AsmJSModuleObjectToModule(JSObject *obj);
|
||||
|
||||
extern bool
|
||||
IsAsmJSModuleObject(JSObject *obj);
|
||||
|
||||
extern JSObject &
|
||||
AsmJSModuleObject(JSFunction *moduleFun);
|
||||
|
||||
|
@ -127,10 +127,16 @@ MNewStringObject::templateObj() const {
|
||||
}
|
||||
|
||||
CodeGenerator::CodeGenerator(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
|
||||
: CodeGeneratorSpecific(gen, graph, masm)
|
||||
: CodeGeneratorSpecific(gen, graph, masm),
|
||||
unassociatedScriptCounts_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CodeGenerator::~CodeGenerator()
|
||||
{
|
||||
js_delete(unassociatedScriptCounts_);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitValueToInt32(LValueToInt32 *lir)
|
||||
{
|
||||
@ -2093,15 +2099,12 @@ CodeGenerator::maybeCreateScriptCounts()
|
||||
CompileInfo *outerInfo = &gen->info();
|
||||
RawScript script = outerInfo->script();
|
||||
|
||||
if (!script)
|
||||
return NULL;
|
||||
|
||||
if (cx->runtime->profilingScripts && !script->hasScriptCounts) {
|
||||
if (!script->initScriptCounts(cx))
|
||||
if (cx->runtime->profilingScripts) {
|
||||
if (script && !script->hasScriptCounts && !script->initScriptCounts(cx))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!script->hasScriptCounts)
|
||||
if (script && !script->hasScriptCounts)
|
||||
return NULL;
|
||||
|
||||
counts = js_new<IonScriptCounts>();
|
||||
@ -2110,19 +2113,23 @@ CodeGenerator::maybeCreateScriptCounts()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
script->addIonCounts(counts);
|
||||
if (script)
|
||||
script->addIonCounts(counts);
|
||||
|
||||
for (size_t i = 0; i < graph.numBlocks(); i++) {
|
||||
MBasicBlock *block = graph.getBlock(i)->mir();
|
||||
|
||||
// Find a PC offset in the outermost script to use. If this block is
|
||||
// from an inlined script, find a location in the outer script to
|
||||
// associate information about the inling with.
|
||||
MResumePoint *resume = block->entryResumePoint();
|
||||
while (resume->caller())
|
||||
resume = resume->caller();
|
||||
uint32_t offset = resume->pc() - script->code;
|
||||
JS_ASSERT(offset < script->length);
|
||||
uint32_t offset = 0;
|
||||
if (script) {
|
||||
// Find a PC offset in the outermost script to use. If this block
|
||||
// is from an inlined script, find a location in the outer script
|
||||
// to associate information about the inlining with.
|
||||
MResumePoint *resume = block->entryResumePoint();
|
||||
while (resume->caller())
|
||||
resume = resume->caller();
|
||||
uint32_t offset = resume->pc() - script->code;
|
||||
JS_ASSERT(offset < script->length);
|
||||
}
|
||||
|
||||
if (!counts->block(i).init(block->id(), offset, block->numSuccessors()))
|
||||
return NULL;
|
||||
@ -2130,6 +2137,12 @@ CodeGenerator::maybeCreateScriptCounts()
|
||||
counts->block(i).setSuccessor(j, block->getSuccessor(j)->id());
|
||||
}
|
||||
|
||||
if (!script) {
|
||||
// Compiling code for Asm.js. Leave the counts on the CodeGenerator to
|
||||
// be picked up by the AsmJSModule after generation finishes.
|
||||
unassociatedScriptCounts_ = counts;
|
||||
}
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
|
||||
public:
|
||||
CodeGenerator(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm = NULL);
|
||||
~CodeGenerator();
|
||||
|
||||
public:
|
||||
bool generate();
|
||||
@ -260,6 +261,12 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitNameIC(OutOfLineUpdateCache *ool, NameIC *ic);
|
||||
bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, CallsiteCloneIC *ic);
|
||||
|
||||
IonScriptCounts *extractUnassociatedScriptCounts() {
|
||||
IonScriptCounts *counts = unassociatedScriptCounts_;
|
||||
unassociatedScriptCounts_ = NULL; // prevent delete in dtor
|
||||
return counts;
|
||||
}
|
||||
|
||||
private:
|
||||
bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, TypedOrValueRegister output,
|
||||
@ -301,6 +308,9 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
|
||||
// Bailout if an element about to be written to is a hole.
|
||||
bool emitStoreHoleCheck(Register elements, const LAllocation *index, LSnapshot *snapshot);
|
||||
|
||||
// Script counts created when compiling code with no associated JSScript.
|
||||
IonScriptCounts *unassociatedScriptCounts_;
|
||||
};
|
||||
|
||||
} // namespace ion
|
||||
|
@ -36,6 +36,10 @@
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/Shape.h"
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
#include "ion/AsmJSModule.h"
|
||||
#endif
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
@ -917,6 +921,34 @@ JS_DumpCompartmentPCCounts(JSContext *cx)
|
||||
if (script->hasScriptCounts && script->enclosingScriptsCompiledSuccessfully())
|
||||
JS_DumpPCCounts(cx, script);
|
||||
}
|
||||
|
||||
#if defined(JS_ASMJS) && defined(DEBUG)
|
||||
for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
|
||||
for (CellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) {
|
||||
JSObject *obj = i.get<JSObject>();
|
||||
if (obj->compartment() != cx->compartment)
|
||||
continue;
|
||||
|
||||
if (IsAsmJSModuleObject(obj)) {
|
||||
AsmJSModule &module = AsmJSModuleObjectToModule(obj);
|
||||
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init())
|
||||
return;
|
||||
|
||||
fprintf(stdout, "--- Asm.js Module ---\n");
|
||||
|
||||
for (size_t i = 0; i < module.numFunctionCounts(); i++) {
|
||||
ion::IonScriptCounts *counts = module.functionCounts(i);
|
||||
DumpIonScriptCounts(&sprinter, counts);
|
||||
}
|
||||
|
||||
fputs(sprinter.string(), stdout);
|
||||
fprintf(stdout, "--- END Asm.js Module ---\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -268,6 +268,23 @@ PCCounts::countName(JSOp op, size_t which)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
js::DumpIonScriptCounts(Sprinter *sp, ion::IonScriptCounts *ionCounts)
|
||||
{
|
||||
Sprint(sp, "IonScript [%lu blocks]:\n", ionCounts->numBlocks());
|
||||
for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
|
||||
const ion::IonBlockCounts &block = ionCounts->block(i);
|
||||
if (block.hitCount() < 10)
|
||||
continue;
|
||||
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 %u instruction bytes %u spill bytes\n",
|
||||
block.hitCount(), block.instructionBytes(), block.spillBytes());
|
||||
Sprint(sp, "%s\n", block.code());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js_DumpPCCounts(JSContext *cx, HandleScript script, js::Sprinter *sp)
|
||||
{
|
||||
@ -305,18 +322,7 @@ js_DumpPCCounts(JSContext *cx, HandleScript script, js::Sprinter *sp)
|
||||
ion::IonScriptCounts *ionCounts = script->getIonCounts();
|
||||
|
||||
while (ionCounts) {
|
||||
Sprint(sp, "IonScript [%lu blocks]:\n", ionCounts->numBlocks());
|
||||
for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
|
||||
const ion::IonBlockCounts &block = ionCounts->block(i);
|
||||
if (block.hitCount() < 10)
|
||||
continue;
|
||||
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 %u instruction bytes %u spill bytes\n",
|
||||
block.hitCount(), block.instructionBytes(), block.spillBytes());
|
||||
Sprint(sp, "%s\n", block.code());
|
||||
}
|
||||
DumpIonScriptCounts(sp, ionCounts);
|
||||
ionCounts = ionCounts->previous();
|
||||
}
|
||||
}
|
||||
|
@ -632,6 +632,15 @@ js_Disassemble1(JSContext *cx, JS::Handle<JSScript*> script, jsbytecode *pc, uns
|
||||
|
||||
void
|
||||
js_DumpPCCounts(JSContext *cx, JS::Handle<JSScript*> script, js::Sprinter *sp);
|
||||
|
||||
#ifdef JS_ION
|
||||
namespace js {
|
||||
namespace ion { struct IonScriptCounts; }
|
||||
void
|
||||
DumpIonScriptCounts(js::Sprinter *sp, ion::IonScriptCounts *ionCounts);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* jsopcode_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user