mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 06:45:42 +00:00
Bug 1027885 - OdinMonkey: hoist the start/end function code (r=bbouvier)
--HG-- extra : rebase_source : 29de292af394eba001503d0a5fe68774924bf725
This commit is contained in:
parent
3eeb7645fa
commit
e65c791de1
@ -831,13 +831,18 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
{}
|
||||
|
||||
PropertyName *name() const { return name_; }
|
||||
|
||||
bool defined() const { return defined_; }
|
||||
void finish(uint32_t start, uint32_t end) {
|
||||
|
||||
void define(ModuleCompiler &m, ParseNode *fn) {
|
||||
JS_ASSERT(!defined_);
|
||||
defined_ = true;
|
||||
srcOffset_ = start;
|
||||
endOffset_ = end;
|
||||
|
||||
// The begin/end char range is relative to the beginning of the module.
|
||||
// hence the assertions.
|
||||
JS_ASSERT(fn->pn_pos.begin > m.moduleStart());
|
||||
JS_ASSERT(fn->pn_pos.begin <= fn->pn_pos.end);
|
||||
srcOffset_ = fn->pn_pos.begin - m.moduleStart();
|
||||
endOffset_ = fn->pn_pos.end - m.moduleStart();
|
||||
}
|
||||
|
||||
uint32_t srcOffset() const { JS_ASSERT(defined_); return srcOffset_; }
|
||||
@ -1420,33 +1425,54 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
return moduleLifo_;
|
||||
}
|
||||
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
bool addProfiledFunction(const Func &func, unsigned endCodeOffset) {
|
||||
unsigned lineno = 0U, columnIndex = 0U;
|
||||
tokenStream().srcCoords.lineNumAndColumnIndex(func.srcOffset(), &lineno, &columnIndex);
|
||||
unsigned startCodeOffset = func.code()->offset();
|
||||
return module_->addProfiledFunction(func.name(), startCodeOffset, endCodeOffset,
|
||||
lineno, columnIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
bool addPerfProfiledBlocks(AsmJSPerfSpewer &perfSpewer, const Func &func, unsigned endCodeOffset) {
|
||||
unsigned startCodeOffset = func.code()->offset();
|
||||
perfSpewer.noteBlocksOffsets();
|
||||
unsigned endInlineCodeOffset = perfSpewer.endInlineCode.offset();
|
||||
return module_->addPerfProfiledBlocks(func.name(), startCodeOffset, endInlineCodeOffset,
|
||||
endCodeOffset, perfSpewer.basicBlocks());
|
||||
}
|
||||
#endif
|
||||
|
||||
bool addFunctionCounts(IonScriptCounts *counts) {
|
||||
return module_->addFunctionCounts(counts);
|
||||
}
|
||||
|
||||
void startFunctionBodies() {
|
||||
module_->startFunctionBodies();
|
||||
}
|
||||
|
||||
void startGeneratingFunction(Func &func, MIRGenerator &mir) {
|
||||
// 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
|
||||
// after each function is compiled. This method is responsible for cleaning
|
||||
// out any dangling pointers that the MacroAssembler may have kept.
|
||||
masm_.resetForNewCodeGenerator(mir.alloc());
|
||||
masm_.align(CodeAlignment);
|
||||
masm_.bind(func.code());
|
||||
}
|
||||
|
||||
bool finishGeneratingFunction(Func &func, MIRGenerator &mir, CodeGenerator &codegen) {
|
||||
JS_ASSERT(func.defined() && func.code()->bound());
|
||||
|
||||
jit::IonScriptCounts *counts = codegen.extractScriptCounts();
|
||||
if (counts && !module_->addFunctionCounts(counts)) {
|
||||
js_delete(counts);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
unsigned line = 0, column = 0;
|
||||
tokenStream().srcCoords.lineNumAndColumnIndex(func.srcOffset(), &line, &column);
|
||||
unsigned startCodeOffset = func.code()->offset();
|
||||
unsigned endCodeOffset = masm_.currentOffset();
|
||||
if (!module_->addProfiledFunction(func.name(), startCodeOffset, endCodeOffset, line, column))
|
||||
return false;
|
||||
# ifdef JS_ION_PERF
|
||||
if (PerfBlockEnabled()) {
|
||||
// Per-block profiling info uses significantly more memory so only
|
||||
// store this information if it is actively requested.
|
||||
mir.perfSpewer().noteBlocksOffsets();
|
||||
unsigned endInlineCodeOffset = mir.perfSpewer().endInlineCode.offset();
|
||||
if (!module_->addPerfProfiledBlocks(func.name(), startCodeOffset, endInlineCodeOffset,
|
||||
endCodeOffset, mir.perfSpewer().basicBlocks()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void finishFunctionBodies() {
|
||||
JS_ASSERT(!finishedFunctionBodies_);
|
||||
masm_.align(AsmJSPageSize);
|
||||
@ -5326,16 +5352,7 @@ CheckFunction(ModuleCompiler &m, LifoAlloc &lifo, MIRGenerator **mir, ModuleComp
|
||||
if (func->defined())
|
||||
return m.failName(fn, "function '%s' already defined", FunctionName(fn));
|
||||
|
||||
uint32_t funcBegin = fn->pn_pos.begin;
|
||||
uint32_t funcEnd = fn->pn_pos.end;
|
||||
// The begin/end char range is relative to the beginning of the module,
|
||||
// hence the assertions.
|
||||
JS_ASSERT(funcBegin > m.moduleStart());
|
||||
JS_ASSERT(funcEnd > m.moduleStart());
|
||||
funcBegin -= m.moduleStart();
|
||||
funcEnd -= m.moduleStart();
|
||||
func->finish(funcBegin, funcEnd);
|
||||
|
||||
func->define(m, fn);
|
||||
func->accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
|
||||
|
||||
m.parser().release(mark);
|
||||
@ -5357,45 +5374,14 @@ GenerateCode(ModuleCompiler &m, ModuleCompiler::Func &func, MIRGenerator &mir, L
|
||||
{
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
// 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
|
||||
// after each function is compiled. This method is responsible for cleaning
|
||||
// out any dangling pointers that the MacroAssembler may have kept.
|
||||
m.masm().resetForNewCodeGenerator(mir.alloc());
|
||||
|
||||
m.masm().bind(func.code());
|
||||
m.startGeneratingFunction(func, mir);
|
||||
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(js_new<CodeGenerator>(&mir, &lir, &m.masm()));
|
||||
if (!codegen || !codegen->generateAsmJS(&m.stackOverflowLabel()))
|
||||
return m.fail(nullptr, "internal codegen failure (probably out of memory)");
|
||||
|
||||
jit::IonScriptCounts *counts = codegen->extractScriptCounts();
|
||||
if (counts && !m.addFunctionCounts(counts)) {
|
||||
js_delete(counts);
|
||||
if (!m.finishGeneratingFunction(func, mir, *codegen))
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
// Profiling might not be active now, but it may be activated later (perhaps
|
||||
// after the module has been cached and reloaded from the cache). Function
|
||||
// profiling info isn't huge, so store it always (in --enable-profiling
|
||||
// builds, which is only Nightly builds, but default).
|
||||
if (!m.addProfiledFunction(func, m.masm().currentOffset()))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
// Per-block profiling info uses significantly more memory so only store
|
||||
// this information if it is actively requested.
|
||||
if (PerfBlockEnabled()) {
|
||||
if (!m.addPerfProfiledBlocks(mir.perfSpewer(), func, m.masm().currentOffset()))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Align internal function headers.
|
||||
m.masm().align(CodeAlignment);
|
||||
|
||||
func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
|
||||
if (!m.maybeReportCompileTime(func))
|
||||
@ -5404,7 +5390,7 @@ GenerateCode(ModuleCompiler &m, ModuleCompiler::Func &func, MIRGenerator &mir, L
|
||||
// Unlike regular IonMonkey which links and generates a new JitCode for
|
||||
// every function, we accumulate all the functions in the module in a
|
||||
// single MacroAssembler and link at end. Linking asm.js doesn't require a
|
||||
// CodeGenerator so we can destroy it now.
|
||||
// CodeGenerator so we can destroy it now (via ScopedJSDeletePtr).
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user