Bug 880538 - OdinMonkey: make a single pass over the parse tree (r=bbouvier)

--HG--
extra : rebase_source : c5aafde69f44906750d1d62d6878bfbab9e048ee
This commit is contained in:
Luke Wagner 2013-06-13 11:48:47 -07:00
parent 793a8f6b53
commit 53ff11b8ad
9 changed files with 1087 additions and 1041 deletions

File diff suppressed because it is too large Load Diff

View File

@ -65,18 +65,18 @@ TriggerOperationCallbackForAsmJSCode(JSRuntime *rt);
class AsmJSActivation
{
JSContext *cx_;
const AsmJSModule &module_;
AsmJSModule &module_;
AsmJSActivation *prev_;
void *errorRejoinSP_;
SPSProfiler *profiler_;
void *resumePC_;
public:
AsmJSActivation(JSContext *cx, const AsmJSModule &module);
AsmJSActivation(JSContext *cx, AsmJSModule &module);
~AsmJSActivation();
JSContext *cx() { return cx_; }
const AsmJSModule &module() const { return module_; }
AsmJSModule &module() const { return module_; }
// Read by JIT code:
static unsigned offsetOfContext() { return offsetof(AsmJSActivation, cx_); }
@ -139,20 +139,19 @@ struct AsmJSParallelTask
{
LifoAlloc lifo; // Provider of all heap memory used for compilation.
uint32_t funcNum; // Index |i| of function in |Module.function(i)|.
void *func; // Really, a ModuleCompiler::Func*
ion::MIRGenerator *mir; // Passed from main thread to worker.
ion::LIRGraph *lir; // Passed from worker to main thread.
unsigned compileTime;
AsmJSParallelTask(size_t defaultChunkSize)
: lifo(defaultChunkSize),
funcNum(0), mir(NULL), lir(NULL), compileTime(0)
: lifo(defaultChunkSize), func(NULL), mir(NULL), lir(NULL), compileTime(0)
{ }
void init(uint32_t newFuncNum, ion::MIRGenerator *newMir) {
funcNum = newFuncNum;
mir = newMir;
lir = NULL;
void init(void *func, ion::MIRGenerator *mir) {
this->func = func;
this->mir = mir;
this->lir = NULL;
}
};

View File

@ -253,7 +253,7 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
return true;
}
AsmJSActivation::AsmJSActivation(JSContext *cx, const AsmJSModule &module)
AsmJSActivation::AsmJSActivation(JSContext *cx, AsmJSModule &module)
: cx_(cx),
module_(module),
errorRejoinSP_(NULL),
@ -297,7 +297,7 @@ js::CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
// - a pointer to the module from which it was returned
// - its index in the ordered list of exported functions
RootedObject moduleObj(cx, &callee->getExtendedSlot(ASM_MODULE_SLOT).toObject());
const AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
// An exported function points to the code as well as the exported
// function's signature, which implies the dynamic coercions performed on

View File

@ -150,6 +150,7 @@ class AsmJSModule
class Exit
{
unsigned ffiIndex_;
unsigned globalDataOffset_;
union {
unsigned codeOffset_;
@ -162,8 +163,8 @@ class AsmJSModule
} ion;
public:
Exit(unsigned ffiIndex)
: ffiIndex_(ffiIndex)
Exit(unsigned ffiIndex, unsigned globalDataOffset)
: ffiIndex_(ffiIndex), globalDataOffset_(globalDataOffset)
{
interp.codeOffset_ = 0;
ion.codeOffset_ = 0;
@ -171,6 +172,9 @@ class AsmJSModule
unsigned ffiIndex() const {
return ffiIndex_;
}
unsigned globalDataOffset() const {
return globalDataOffset_;
}
void initInterpOffset(unsigned off) {
JS_ASSERT(!interp.codeOffset_);
interp.codeOffset_ = off;
@ -202,11 +206,7 @@ class AsmJSModule
class ExportedFunction
{
public:
private:
RelocatablePtr<JSFunction> fun_;
RelocatablePtr<PropertyName> name_;
RelocatablePtr<PropertyName> maybeFieldName_;
ArgCoercionVector argCoercions_;
ReturnType returnType_;
@ -218,11 +218,11 @@ class AsmJSModule
friend class AsmJSModule;
ExportedFunction(JSFunction *fun,
ExportedFunction(PropertyName *name,
PropertyName *maybeFieldName,
mozilla::MoveRef<ArgCoercionVector> argCoercions,
ReturnType returnType)
: fun_(fun),
: name_(name),
maybeFieldName_(maybeFieldName),
argCoercions_(argCoercions),
returnType_(returnType),
@ -232,14 +232,14 @@ class AsmJSModule
}
void trace(JSTracer *trc) {
MarkObject(trc, &fun_, "asm.js export name");
MarkString(trc, &name_, "asm.js export name");
if (maybeFieldName_)
MarkString(trc, &maybeFieldName_, "asm.js export field");
}
public:
ExportedFunction(mozilla::MoveRef<ExportedFunction> rhs)
: fun_(rhs->fun_),
: name_(rhs->name_),
maybeFieldName_(rhs->maybeFieldName_),
argCoercions_(mozilla::Move(rhs->argCoercions_)),
returnType_(rhs->returnType_),
@ -260,10 +260,7 @@ class AsmJSModule
}
PropertyName *name() const {
return fun_->name();
}
JSFunction *unclonedFunObj() const {
return fun_;
return name_;
}
PropertyName *maybeFieldName() const {
return maybeFieldName_;
@ -382,7 +379,7 @@ class AsmJSModule
uint32_t numGlobalVars_;
uint32_t numFFIs_;
uint32_t numFuncPtrTableElems_;
size_t funcPtrTableAndExitBytes_;
bool hasArrayView_;
ScopedReleasePtr<JSC::ExecutablePool> codePool_;
@ -407,7 +404,7 @@ class AsmJSModule
explicit AsmJSModule(JSContext *cx)
: numGlobalVars_(0),
numFFIs_(0),
numFuncPtrTableElems_(0),
funcPtrTableAndExitBytes_(0),
hasArrayView_(false),
code_(NULL),
operationCallbackExit_(NULL),
@ -443,6 +440,7 @@ class AsmJSModule
bool addGlobalVarInitConstant(const Value &v, uint32_t *globalIndex) {
JS_ASSERT(!v.isMarkable());
JS_ASSERT(funcPtrTableAndExitBytes_ == 0);
if (numGlobalVars_ == UINT32_MAX)
return false;
Global g(Global::Variable);
@ -452,6 +450,7 @@ class AsmJSModule
return globals_.append(g);
}
bool addGlobalVarImport(PropertyName *fieldName, AsmJSCoercion coercion, uint32_t *globalIndex) {
JS_ASSERT(funcPtrTableAndExitBytes_ == 0);
Global g(Global::Variable);
g.u.var.initKind_ = Global::InitImport;
g.u.var.init.coercion_ = coercion;
@ -459,12 +458,6 @@ class AsmJSModule
g.name_ = fieldName;
return globals_.append(g);
}
bool incrementNumFuncPtrTableElems(uint32_t numElems) {
if (UINT32_MAX - numFuncPtrTableElems_ < numElems)
return false;
numFuncPtrTableElems_ += numElems;
return true;
}
bool addFFI(PropertyName *field, uint32_t *ffiIndex) {
if (numFFIs_ == UINT32_MAX)
return false;
@ -492,19 +485,32 @@ class AsmJSModule
g.name_ = fieldName;
return globals_.append(g);
}
bool addFuncPtrTable(unsigned numElems, uint32_t *globalDataOffset) {
JS_ASSERT(IsPowerOfTwo(numElems));
if (SIZE_MAX - funcPtrTableAndExitBytes_ < numElems * sizeof(void*))
return false;
*globalDataOffset = globalDataBytes();
funcPtrTableAndExitBytes_ += numElems * sizeof(void*);
return true;
}
bool addExit(unsigned ffiIndex, unsigned *exitIndex) {
if (SIZE_MAX - funcPtrTableAndExitBytes_ < sizeof(ExitDatum))
return false;
uint32_t globalDataOffset = globalDataBytes();
JS_STATIC_ASSERT(sizeof(ExitDatum) % sizeof(void*) == 0);
funcPtrTableAndExitBytes_ += sizeof(ExitDatum);
*exitIndex = unsigned(exits_.length());
return exits_.append(Exit(ffiIndex));
return exits_.append(Exit(ffiIndex, globalDataOffset));
}
bool addFunctionCounts(ion::IonScriptCounts *counts) {
return functionCounts_.append(counts);
}
bool addExportedFunction(JSFunction *fun, PropertyName *maybeFieldName,
bool addExportedFunction(PropertyName *name, PropertyName *maybeFieldName,
mozilla::MoveRef<ArgCoercionVector> argCoercions,
ReturnType returnType)
{
ExportedFunction func(fun, maybeFieldName, argCoercions, returnType);
ExportedFunction func(name, maybeFieldName, argCoercions, returnType);
return exports_.append(mozilla::Move(func));
}
unsigned numExportedFunctions() const {
@ -568,9 +574,6 @@ class AsmJSModule
Global &global(unsigned i) {
return globals_[i];
}
unsigned numFuncPtrTableElems() const {
return numFuncPtrTableElems_;
}
unsigned numExits() const {
return exits_.length();
}
@ -603,11 +606,9 @@ class AsmJSModule
// are laid out in this order:
// 0. a pointer/descriptor for the heap that was linked to the module
// 1. global variable state (elements are sizeof(uint64_t))
// 2. function-pointer table elements (elements are sizeof(void*))
// 3. exits (elements are sizeof(ExitDatum))
//
// NB: The list of exits is extended while emitting function bodies and
// thus exits must be at the end of the list to avoid invalidating indices.
// 2. interleaved function-pointer tables and exits. These are allocated
// while type checking function bodies (as exits and uses of
// function-pointer tables are encountered).
uint8_t *globalData() const {
JS_ASSERT(code_);
return code_ + codeBytes_;
@ -616,8 +617,7 @@ class AsmJSModule
size_t globalDataBytes() const {
return sizeof(void*) +
numGlobalVars_ * sizeof(uint64_t) +
numFuncPtrTableElems_ * sizeof(void*) +
exits_.length() * sizeof(ExitDatum);
funcPtrTableAndExitBytes_;
}
unsigned heapOffset() const {
return 0;
@ -633,20 +633,12 @@ class AsmJSModule
void *globalVarIndexToGlobalDatum(unsigned i) const {
return (void *)(globalData() + globalVarIndexToGlobalDataOffset(i));
}
unsigned funcPtrIndexToGlobalDataOffset(unsigned i) const {
return sizeof(void*) +
numGlobalVars_ * sizeof(uint64_t) +
i * sizeof(void*);
}
void *&funcPtrIndexToGlobalDatum(unsigned i) const {
return *(void **)(globalData() + funcPtrIndexToGlobalDataOffset(i));
uint8_t **globalDataOffsetToFuncPtrTable(unsigned globalDataOffset) const {
JS_ASSERT(globalDataOffset < globalDataBytes());
return (uint8_t **)(globalData() + globalDataOffset);
}
unsigned exitIndexToGlobalDataOffset(unsigned exitIndex) const {
JS_ASSERT(exitIndex < exits_.length());
return sizeof(void*) +
numGlobalVars_ * sizeof(uint64_t) +
numFuncPtrTableElems_ * sizeof(void*) +
exitIndex * sizeof(ExitDatum);
return exits_[exitIndex].globalDataOffset();
}
ExitDatum &exitIndexToGlobalDatum(unsigned exitIndex) const {
return *(ExitDatum *)(globalData() + exitIndexToGlobalDataOffset(exitIndex));
@ -707,8 +699,6 @@ class AsmJSModule
}
#endif
void takeOwnership(JSC::ExecutablePool *pool, uint8_t *code, size_t codeBytes, size_t totalBytes) {
JS_ASSERT(uintptr_t(code) % AsmJSPageSize == 0);
codePool_ = pool;
@ -764,15 +754,8 @@ class AsmJSModule
return postLinkFailureInfo_;
}
size_t exitDatumToExitIndex(ExitDatum *exit) const {
ExitDatum *first = &exitIndexToGlobalDatum(0);
JS_ASSERT(exit >= first && exit < first + numExits());
return exit - first;
}
void detachIonCompilation(size_t exitIndex) const {
ExitDatum &exitDatum = exitIndexToGlobalDatum(exitIndex);
exitDatum.exit = exit(exitIndex).interpCode();
exitIndexToGlobalDatum(exitIndex).exit = exit(exitIndex).interpCode();
}
};

View File

@ -1351,21 +1351,3 @@ MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg,
break;
}
}
ABIArgIter::ABIArgIter(const MIRTypeVector &types)
: gen_(),
types_(types),
i_(0)
{
if (!done())
gen_.next(types_[i_]);
}
void
ABIArgIter::operator++(int)
{
JS_ASSERT(!done());
i_++;
if (!done())
gen_.next(types_[i_]);
}

View File

@ -1006,28 +1006,6 @@ JSOpToCondition(JSOp op, bool isSigned)
}
}
typedef Vector<MIRType, 8> MIRTypeVector;
class ABIArgIter
{
ABIArgGenerator gen_;
const MIRTypeVector &types_;
unsigned i_;
public:
ABIArgIter(const MIRTypeVector &argTypes);
void operator++(int);
bool done() const { return i_ == types_.length(); }
ABIArg *operator->() { JS_ASSERT(!done()); return &gen_.current(); }
ABIArg &operator*() { JS_ASSERT(!done()); return gen_.current(); }
unsigned index() const { JS_ASSERT(!done()); return i_; }
MIRType mirType() const { JS_ASSERT(!done()); return types_[i_]; }
uint32_t stackBytesConsumedSoFar() const { return gen_.stackBytesConsumedSoFar(); }
};
} // namespace ion
} // namespace js

View File

@ -160,8 +160,6 @@ class CodeGeneratorARM : public CodeGeneratorShared
bool generateInvalidateEpilogue();
protected:
bool generateAsmJSPrologue(const MIRTypeVector &argTypes, MIRType returnType,
Label *internalEntry);
void postAsmJSCall(LAsmJSCall *lir) {
#if !defined(JS_CPU_ARM_HARDFP)
if (lir->mir()->type() == MIRType_Double) {

View File

@ -367,7 +367,7 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state)
// On failure, signal parent for harvesting in CancelOutstandingJobs().
if (!success) {
asmData = NULL;
state.noteAsmJSFailure(asmData->funcNum);
state.noteAsmJSFailure(asmData->func);
state.notify(WorkerThreadState::MAIN);
return;
}

View File

@ -86,11 +86,11 @@ class WorkerThreadState
numAsmJSFailedJobs = 0;
return n;
}
void noteAsmJSFailure(int32_t func) {
void noteAsmJSFailure(void *func) {
// Be mindful to signal the main thread after calling this function.
JS_ASSERT(isLocked());
if (asmJSFailedFunctionIndex < 0)
asmJSFailedFunctionIndex = func;
if (!asmJSFailedFunction)
asmJSFailedFunction = func;
numAsmJSFailedJobs++;
}
bool asmJSWorkerFailed() const {
@ -98,10 +98,10 @@ class WorkerThreadState
}
void resetAsmJSFailureState() {
numAsmJSFailedJobs = 0;
asmJSFailedFunctionIndex = -1;
asmJSFailedFunction = NULL;
}
int32_t maybeGetAsmJSFailedFunctionIndex() const {
return asmJSFailedFunctionIndex;
void *maybeAsmJSFailedFunction() const {
return asmJSFailedFunction;
}
private:
@ -132,7 +132,7 @@ class WorkerThreadState
* Function index |i| in |Module.function(i)| of first failed AsmJS function.
* -1 if no function has failed.
*/
int32_t asmJSFailedFunctionIndex;
void *asmJSFailedFunction;
};
/* Individual helper thread, one allocated per core. */