Bug 1027885 - OdinMonkey: hoist the start/end function code (r=bbouvier)

--HG--
extra : rebase_source : 29de292af394eba001503d0a5fe68774924bf725
This commit is contained in:
Luke Wagner 2014-06-23 14:55:56 -05:00
parent 3eeb7645fa
commit e65c791de1

View File

@ -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;
}