Bug 917441 - Remove dependence of IonBuilder on ScriptAnalysis, r=jandem.

This commit is contained in:
Brian Hackett 2013-09-18 09:43:21 -06:00
Родитель 89075a8c47
Коммит 67b88e4fd7
16 изменённых файлов: 140 добавлений и 63 удалений

Просмотреть файл

@ -4817,6 +4817,16 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
return tailCallVM(DoSetElemFallbackInfo, masm); return tailCallVM(DoSetElemFallbackInfo, masm);
} }
void
BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
{
ICEntry &entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub *stub = entry.fallbackStub();
if (stub->isSetElem_Fallback())
stub->toSetElem_Fallback()->noteArrayWriteHole();
}
// //
// SetElem_Dense // SetElem_Dense
// //

Просмотреть файл

@ -3375,6 +3375,13 @@ class ICSetElem_Fallback : public ICFallbackStub
return space->allocate<ICSetElem_Fallback>(code); return space->allocate<ICSetElem_Fallback>(code);
} }
void noteArrayWriteHole() {
extra_ = 1;
}
bool hasArrayWriteHole() const {
return extra_;
}
// Compiler for this stub kind. // Compiler for this stub kind.
class Compiler : public ICStubCompiler { class Compiler : public ICStubCompiler {
protected: protected:

Просмотреть файл

@ -26,6 +26,12 @@ SetElemICInspector::sawOOBDenseWrite() const
if (stub->isSetElem_DenseAdd()) if (stub->isSetElem_DenseAdd())
return true; return true;
} }
// Check for a write hole bit on the SetElem_Fallback stub.
ICStub *stub = icEntry_->fallbackStub();
if (stub->isSetElem_Fallback())
return stub->toSetElem_Fallback()->hasArrayWriteHole();
return false; return false;
} }

Просмотреть файл

@ -267,6 +267,7 @@ struct BaselineScript
void toggleSPS(bool enable); void toggleSPS(bool enable);
void noteAccessedGetter(uint32_t pcOffset); void noteAccessedGetter(uint32_t pcOffset);
void noteArrayWriteHole(uint32_t pcOffset);
static size_t offsetOfFlags() { static size_t offsetOfFlags() {
return offsetof(BaselineScript, flags_); return offsetof(BaselineScript, flags_);

Просмотреть файл

@ -15,7 +15,9 @@ using namespace js::jit;
BytecodeAnalysis::BytecodeAnalysis(JSScript *script) BytecodeAnalysis::BytecodeAnalysis(JSScript *script)
: script_(script), : script_(script),
infos_() infos_(),
usesScopeChain_(false),
hasTryFinally_(false)
{ {
} }
@ -144,6 +146,26 @@ BytecodeAnalysis::init(JSContext *cx)
} }
break; break;
case JSOP_NAME:
case JSOP_CALLNAME:
case JSOP_BINDNAME:
case JSOP_SETNAME:
case JSOP_DELNAME:
case JSOP_GETALIASEDVAR:
case JSOP_CALLALIASEDVAR:
case JSOP_SETALIASEDVAR:
case JSOP_LAMBDA:
case JSOP_DEFFUN:
case JSOP_DEFVAR:
case JSOP_DEFCONST:
case JSOP_SETCONST:
usesScopeChain_ = true;
break;
case JSOP_FINALLY:
hasTryFinally_ = true;
break;
default: default:
break; break;
} }

Просмотреть файл

@ -39,6 +39,9 @@ class BytecodeAnalysis
JSScript *script_; JSScript *script_;
Vector<BytecodeInfo, 0, IonAllocPolicy> infos_; Vector<BytecodeInfo, 0, IonAllocPolicy> infos_;
bool usesScopeChain_;
bool hasTryFinally_;
public: public:
explicit BytecodeAnalysis(JSScript *script); explicit BytecodeAnalysis(JSScript *script);
@ -54,6 +57,14 @@ class BytecodeAnalysis
return &infos_[pc - script_->code]; return &infos_[pc - script_->code];
return NULL; return NULL;
} }
bool usesScopeChain() {
return usesScopeChain_;
}
bool hasTryFinally() {
return hasTryFinally_;
}
}; };

Просмотреть файл

@ -1606,9 +1606,6 @@ IonCompile(JSContext *cx, JSScript *script,
script); script);
#endif #endif
if (!script->ensureRanAnalysis(cx))
return AbortReason_Alloc;
LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE); LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
if (!alloc) if (!alloc)
return AbortReason_Alloc; return AbortReason_Alloc;

Просмотреть файл

@ -42,6 +42,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
cx(cx), cx(cx),
baselineFrame_(baselineFrame), baselineFrame_(baselineFrame),
abortReason_(AbortReason_Disable), abortReason_(AbortReason_Disable),
analysis_(info->script()),
loopDepth_(loopDepth), loopDepth_(loopDepth),
callerResumePoint_(NULL), callerResumePoint_(NULL),
callerBuilder_(NULL), callerBuilder_(NULL),
@ -231,10 +232,10 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
JSScript *targetScript = target->nonLazyScript(); JSScript *targetScript = target->nonLazyScript();
if (!targetScript->ensureRanAnalysis(cx)) if (targetScript->uninlineable)
return false; return false;
if (targetScript->uninlineable) if (!targetScript->analyzedArgsUsage())
return false; return false;
if (targetScript->needsArgsObj()) if (targetScript->needsArgsObj())
@ -370,7 +371,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecod
continue; continue;
if (slot >= info().firstStackSlot()) if (slot >= info().firstStackSlot())
continue; continue;
if (!script()->analysis()->maybeCode(pc)) if (!analysis().maybeInfo(pc))
continue; continue;
MPhi *phi = entry->getSlot(slot)->toPhi(); MPhi *phi = entry->getSlot(slot)->toPhi();
@ -491,11 +492,23 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e
} }
bool bool
IonBuilder::build() IonBuilder::init()
{ {
if (!script()->ensureHasBytecodeTypeMap(cx)) if (!script()->ensureHasBytecodeTypeMap(cx))
return false; return false;
if (!analysis().init(cx))
return false;
return true;
}
bool
IonBuilder::build()
{
if (!init())
return false;
setCurrentAndSpecializePhis(newBlock(pc)); setCurrentAndSpecializePhis(newBlock(pc));
if (!current) if (!current)
return false; return false;
@ -633,11 +646,11 @@ bool
IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint, IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
CallInfo &callInfo) CallInfo &callInfo)
{ {
inlineCallInfo_ = &callInfo; if (!init())
if (!script()->ensureHasBytecodeTypeMap(cx))
return false; return false;
inlineCallInfo_ = &callInfo;
IonSpew(IonSpew_Scripts, "Inlining script %s:%d (%p)", IonSpew(IonSpew_Scripts, "Inlining script %s:%d (%p)",
script()->filename(), script()->lineno, (void *)script()); script()->filename(), script()->lineno, (void *)script());
@ -842,7 +855,7 @@ IonBuilder::initScopeChain(MDefinition *callee)
// from earlier. However, always make a scope chain when |needsArgsObj| is true // from earlier. However, always make a scope chain when |needsArgsObj| is true
// for the script, since arguments object construction requires the scope chain // for the script, since arguments object construction requires the scope chain
// to be passed in. // to be passed in.
if (!info().needsArgsObj() && !script()->analysis()->usesScopeChain()) if (!info().needsArgsObj() && !analysis().usesScopeChain())
return true; return true;
// The scope chain is only tracked in scripts that have NAME opcodes which // The scope chain is only tracked in scripts that have NAME opcodes which
@ -3355,7 +3368,7 @@ IonBuilder::jsop_try()
return abort("Try-catch support disabled"); return abort("Try-catch support disabled");
// Try-finally is not yet supported. // Try-finally is not yet supported.
if (script()->analysis()->hasTryFinally()) if (analysis().hasTryFinally())
return abort("Has try-finally"); return abort("Has try-finally");
// Try-catch within inline frames is not yet supported. // Try-catch within inline frames is not yet supported.
@ -3401,7 +3414,7 @@ IonBuilder::jsop_try()
return false; return false;
MBasicBlock *successor; MBasicBlock *successor;
if (script()->analysis()->maybeCode(afterTry)) { if (analysis().maybeInfo(afterTry)) {
successor = newBlock(current, afterTry); successor = newBlock(current, afterTry);
if (!successor) if (!successor)
return false; return false;
@ -3748,7 +3761,10 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
BaselineInspector inspector(cx, calleeScript); BaselineInspector inspector(cx, calleeScript);
// Improve type information of |this| when not set. // Improve type information of |this| when not set.
if (callInfo.constructing() && !callInfo.thisArg()->resultTypeSet()) { if (callInfo.constructing() &&
!callInfo.thisArg()->resultTypeSet() &&
calleeScript->types)
{
types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript); types::StackTypeSet *types = types::TypeScript::ThisTypes(calleeScript);
if (!types->unknown()) { if (!types->unknown()) {
MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types), Bailout_Normal); MTypeBarrier *barrier = MTypeBarrier::New(callInfo.thisArg(), cloneTypeSet(types), Bailout_Normal);
@ -3773,7 +3789,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
IonBuilder inlineBuilder(cx, &temp(), &graph(), &inspector, info, NULL, IonBuilder inlineBuilder(cx, &temp(), &graph(), &inspector, info, NULL,
inliningDepth_ + 1, loopDepth_); inliningDepth_ + 1, loopDepth_);
if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) { if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
JS_ASSERT(calleeScript->hasAnalysis());
if (cx->isExceptionPending()) { if (cx->isExceptionPending()) {
IonSpew(IonSpew_Abort, "Inline builder raised exception."); IonSpew(IonSpew_Abort, "Inline builder raised exception.");
abortReason_ = AbortReason_Error; abortReason_ = AbortReason_Error;
@ -3931,7 +3946,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo)
return false; return false;
} }
if (targetScript->analysis()->hasLoops()) { if (targetScript->hasLoops()) {
IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: big function that contains a loop", IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: big function that contains a loop",
targetScript->filename(), targetScript->lineno); targetScript->filename(), targetScript->lineno);
return false; return false;
@ -5087,7 +5102,7 @@ IonBuilder::testNeedsArgumentCheck(JSContext *cx, JSFunction *target, CallInfo &
return true; return true;
JSScript *targetScript = target->nonLazyScript(); JSScript *targetScript = target->nonLazyScript();
if (!targetScript->hasAnalysis()) if (!targetScript->types)
return true; return true;
if (!ArgumentTypesMatch(callInfo.thisArg(), cloneTypeSet(types::TypeScript::ThisTypes(targetScript)))) if (!ArgumentTypesMatch(callInfo.thisArg(), cloneTypeSet(types::TypeScript::ThisTypes(targetScript))))
@ -5661,7 +5676,8 @@ IonBuilder::addBlock(MBasicBlock *block, uint32_t loopDepth)
MBasicBlock * MBasicBlock *
IonBuilder::newBlock(MBasicBlock *predecessor, jsbytecode *pc) IonBuilder::newBlock(MBasicBlock *predecessor, jsbytecode *pc)
{ {
MBasicBlock *block = MBasicBlock::New(graph(), info(), predecessor, pc, MBasicBlock::NORMAL); MBasicBlock *block = MBasicBlock::New(graph(), &analysis(), info(),
predecessor, pc, MBasicBlock::NORMAL);
return addBlock(block, loopDepth_); return addBlock(block, loopDepth_);
} }
@ -5683,7 +5699,8 @@ IonBuilder::newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popp
MBasicBlock * MBasicBlock *
IonBuilder::newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc) IonBuilder::newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode *pc)
{ {
MBasicBlock *block = MBasicBlock::New(graph(), info(), predecessor, pc, MBasicBlock::NORMAL); MBasicBlock *block = MBasicBlock::New(graph(), &analysis(), info(),
predecessor, pc, MBasicBlock::NORMAL);
if (!block) if (!block)
return NULL; return NULL;
graph().insertBlockAfter(at, block); graph().insertBlockAfter(at, block);
@ -5693,7 +5710,8 @@ IonBuilder::newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode
MBasicBlock * MBasicBlock *
IonBuilder::newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth) IonBuilder::newBlock(MBasicBlock *predecessor, jsbytecode *pc, uint32_t loopDepth)
{ {
MBasicBlock *block = MBasicBlock::New(graph(), info(), predecessor, pc, MBasicBlock::NORMAL); MBasicBlock *block = MBasicBlock::New(graph(), &analysis(), info(),
predecessor, pc, MBasicBlock::NORMAL);
return addBlock(block, loopDepth); return addBlock(block, loopDepth);
} }
@ -5719,7 +5737,7 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry)
uint32_t slot = info().scopeChainSlot(); uint32_t slot = info().scopeChainSlot();
MInstruction *scopev; MInstruction *scopev;
if (script()->analysis()->usesScopeChain()) { if (analysis().usesScopeChain()) {
scopev = MOsrScopeChain::New(entry); scopev = MOsrScopeChain::New(entry);
} else { } else {
// Use an undefined value if the script does not need its scope // Use an undefined value if the script does not need its scope
@ -6470,7 +6488,7 @@ IonBuilder::jsop_intrinsic(PropertyName *name)
bool bool
IonBuilder::jsop_bindname(PropertyName *name) IonBuilder::jsop_bindname(PropertyName *name)
{ {
JS_ASSERT(script()->analysis()->usesScopeChain()); JS_ASSERT(analysis().usesScopeChain());
MDefinition *scopeChain = current->scopeChain(); MDefinition *scopeChain = current->scopeChain();
MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script(), pc); MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script(), pc);
@ -7348,13 +7366,10 @@ IonBuilder::jsop_setelem_dense(types::TemporaryTypeSet::DoubleConversion convers
MOZ_ASSUME_UNREACHABLE("Unknown double conversion"); MOZ_ASSUME_UNREACHABLE("Unknown double conversion");
} }
bool writeHole; bool writeHole = false;
if (safety == SetElem_Normal) { if (safety == SetElem_Normal) {
writeHole = script()->analysis()->getCode(pc).arrayWriteHole;
SetElemICInspector icInspect(inspector->setElemICInspector(pc)); SetElemICInspector icInspect(inspector->setElemICInspector(pc));
writeHole |= icInspect.sawOOBDenseWrite(); writeHole = icInspect.sawOOBDenseWrite();
} else {
writeHole = false;
} }
// Use MStoreElementHole if this SETELEM has written to out-of-bounds // Use MStoreElementHole if this SETELEM has written to out-of-bounds
@ -8399,9 +8414,7 @@ IonBuilder::getPropTryCache(bool *emitted, PropertyName *name, jsid id,
bool barrier, types::TemporaryTypeSet *types) bool barrier, types::TemporaryTypeSet *types)
{ {
JS_ASSERT(*emitted == false); JS_ASSERT(*emitted == false);
bool accessGetter = bool accessGetter = inspector->hasSeenAccessedGetter(pc);
script()->analysis()->getCode(pc).accessGetter ||
inspector->hasSeenAccessedGetter(pc);
MDefinition *obj = current->peek(-1); MDefinition *obj = current->peek(-1);
@ -8831,7 +8844,7 @@ IonBuilder::jsop_lambda(JSFunction *fun)
if (fun->isInterpreted() && !fun->getOrCreateScript(cx)) if (fun->isInterpreted() && !fun->getOrCreateScript(cx))
return false; return false;
JS_ASSERT(script()->analysis()->usesScopeChain()); JS_ASSERT(analysis().usesScopeChain());
if (fun->isArrow()) if (fun->isArrow())
return abort("bound arrow function"); return abort("bound arrow function");
if (fun->isNative() && IsAsmJSModuleNative(fun->native())) if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
@ -8857,7 +8870,7 @@ IonBuilder::jsop_defvar(uint32_t index)
attrs |= JSPROP_READONLY; attrs |= JSPROP_READONLY;
// Pass the ScopeChain. // Pass the ScopeChain.
JS_ASSERT(script()->analysis()->usesScopeChain()); JS_ASSERT(analysis().usesScopeChain());
// Bake the name pointer into the MDefVar. // Bake the name pointer into the MDefVar.
MDefVar *defvar = MDefVar::New(name, attrs, current->scopeChain()); MDefVar *defvar = MDefVar::New(name, attrs, current->scopeChain());
@ -8873,7 +8886,7 @@ IonBuilder::jsop_deffun(uint32_t index)
if (fun->isNative() && IsAsmJSModuleNative(fun->native())) if (fun->isNative() && IsAsmJSModuleNative(fun->native()))
return abort("asm.js module function"); return abort("asm.js module function");
JS_ASSERT(script()->analysis()->usesScopeChain()); JS_ASSERT(analysis().usesScopeChain());
MDefFun *deffun = MDefFun::New(fun, current->scopeChain()); MDefFun *deffun = MDefFun::New(fun, current->scopeChain());
current->add(deffun); current->add(deffun);

Просмотреть файл

@ -12,6 +12,7 @@
// This file declares the data structures for building a MIRGraph from a // This file declares the data structures for building a MIRGraph from a
// JSScript. // JSScript.
#include "jit/BytecodeAnalysis.h"
#include "jit/MIR.h" #include "jit/MIR.h"
#include "jit/MIRGraph.h" #include "jit/MIRGraph.h"
@ -640,10 +641,18 @@ class IonBuilder : public MIRGenerator
AbortReason abortReason() { return abortReason_; } AbortReason abortReason() { return abortReason_; }
private: private:
bool init();
JSContext *cx; JSContext *cx;
BaselineFrame *baselineFrame_; BaselineFrame *baselineFrame_;
AbortReason abortReason_; AbortReason abortReason_;
// Basic analysis information about the script.
BytecodeAnalysis analysis_;
BytecodeAnalysis &analysis() {
return analysis_;
}
jsbytecode *pc; jsbytecode *pc;
MBasicBlock *current; MBasicBlock *current;
uint32_t loopDepth_; uint32_t loopDepth_;

Просмотреть файл

@ -158,7 +158,7 @@ MIRGraph::forkJoinSlice()
} }
MBasicBlock * MBasicBlock *
MBasicBlock::New(MIRGraph &graph, CompileInfo &info, MBasicBlock::New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info,
MBasicBlock *pred, jsbytecode *entryPc, Kind kind) MBasicBlock *pred, jsbytecode *entryPc, Kind kind)
{ {
JS_ASSERT(entryPc != NULL); JS_ASSERT(entryPc != NULL);
@ -167,7 +167,7 @@ MBasicBlock::New(MIRGraph &graph, CompileInfo &info,
if (!block->init()) if (!block->init())
return NULL; return NULL;
if (!block->inherit(pred, 0)) if (!block->inherit(analysis, pred, 0))
return NULL; return NULL;
return block; return block;
@ -181,7 +181,7 @@ MBasicBlock::NewPopN(MIRGraph &graph, CompileInfo &info,
if (!block->init()) if (!block->init())
return NULL; return NULL;
if (!block->inherit(pred, popped)) if (!block->inherit(NULL, pred, popped))
return NULL; return NULL;
return block; return block;
@ -210,14 +210,14 @@ MBasicBlock *
MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info,
MBasicBlock *pred, jsbytecode *entryPc) MBasicBlock *pred, jsbytecode *entryPc)
{ {
return MBasicBlock::New(graph, info, pred, entryPc, PENDING_LOOP_HEADER); return MBasicBlock::New(graph, NULL, info, pred, entryPc, PENDING_LOOP_HEADER);
} }
MBasicBlock * MBasicBlock *
MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred) MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred)
{ {
return pred->pc() return pred->pc()
? MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE) ? MBasicBlock::New(graph, NULL, info, pred, pred->pc(), SPLIT_EDGE)
: MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE); : MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
} }
@ -323,7 +323,7 @@ MBasicBlock::copySlots(MBasicBlock *from)
} }
bool bool
MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) MBasicBlock::inherit(BytecodeAnalysis *analysis, MBasicBlock *pred, uint32_t popped)
{ {
if (pred) { if (pred) {
stackPosition_ = pred->stackPosition_; stackPosition_ = pred->stackPosition_;
@ -332,7 +332,7 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped)
if (kind_ != PENDING_LOOP_HEADER) if (kind_ != PENDING_LOOP_HEADER)
copySlots(pred); copySlots(pred);
} else { } else {
uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth; uint32_t stackDepth = analysis->info(pc()).stackDepth;
stackPosition_ = info().firstStackSlot() + stackDepth; stackPosition_ = info().firstStackSlot() + stackDepth;
JS_ASSERT(stackPosition_ >= popped); JS_ASSERT(stackPosition_ >= popped);
stackPosition_ -= popped; stackPosition_ -= popped;

Просмотреть файл

@ -18,6 +18,7 @@
namespace js { namespace js {
namespace jit { namespace jit {
class BytecodeAnalysis;
class MBasicBlock; class MBasicBlock;
class MIRGraph; class MIRGraph;
class MStart; class MStart;
@ -46,7 +47,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind); MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind);
bool init(); bool init();
void copySlots(MBasicBlock *from); void copySlots(MBasicBlock *from);
bool inherit(MBasicBlock *pred, uint32_t popped); bool inherit(BytecodeAnalysis *analysis, MBasicBlock *pred, uint32_t popped);
bool inheritResumePoint(MBasicBlock *pred); bool inheritResumePoint(MBasicBlock *pred);
void assertUsesAreNotWithin(MUseIterator use, MUseIterator end); void assertUsesAreNotWithin(MUseIterator use, MUseIterator end);
@ -67,7 +68,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
// Creates a new basic block for a MIR generator. If |pred| is not NULL, // Creates a new basic block for a MIR generator. If |pred| is not NULL,
// its slots and stack depth are initialized from |pred|. // its slots and stack depth are initialized from |pred|.
static MBasicBlock *New(MIRGraph &graph, CompileInfo &info, static MBasicBlock *New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info,
MBasicBlock *pred, jsbytecode *entryPc, Kind kind); MBasicBlock *pred, jsbytecode *entryPc, Kind kind);
static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info, static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info,
MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn); MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn);

Просмотреть файл

@ -78,13 +78,6 @@ class Bytecode
/* Whether this is a catch/finally entry point. */ /* Whether this is a catch/finally entry point. */
bool exceptionEntry : 1; bool exceptionEntry : 1;
/*
* Dynamically observed state about the execution of this opcode. These are
* hints about the script for use during compilation.
*/
bool arrayWriteHole: 1; /* SETELEM which has written to an array hole. */
bool accessGetter: 1; /* Property read on a shape with a getter hook. */
/* Stack depth before this opcode. */ /* Stack depth before this opcode. */
uint32_t stackDepth; uint32_t stackDepth;

Просмотреть файл

@ -4040,12 +4040,6 @@ NativeGetInline(JSContext *cx,
{ {
jsbytecode *pc; jsbytecode *pc;
JSScript *script = cx->currentScript(&pc); JSScript *script = cx->currentScript(&pc);
if (script && script->hasAnalysis()) {
analyze::Bytecode *code = script->analysis()->maybeCode(pc);
if (code)
code->accessGetter = true;
}
#ifdef JS_ION #ifdef JS_ION
if (script && script->hasBaselineScript()) { if (script && script->hasBaselineScript()) {
switch (JSOp(*pc)) { switch (JSOp(*pc)) {

Просмотреть файл

@ -2959,6 +2959,20 @@ JSScript::updateBaselineOrIonRaw()
#endif #endif
} }
bool
JSScript::hasLoops()
{
if (!hasTrynotes())
return false;
JSTryNote *tn = trynotes()->vector;
JSTryNote *tnlimit = tn + trynotes()->length;
for (; tn < tnlimit; tn++) {
if (tn->kind == JSTRY_ITER || tn->kind == JSTRY_LOOP)
return true;
}
return false;
}
static inline void static inline void
LazyScriptHash(uint32_t lineno, uint32_t column, uint32_t begin, uint32_t end, LazyScriptHash(uint32_t lineno, uint32_t column, uint32_t begin, uint32_t end,
HashNumber hashes[3]) HashNumber hashes[3])

Просмотреть файл

@ -932,6 +932,8 @@ class JSScript : public js::gc::Cell
return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset()); return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
} }
bool hasLoops();
js::HeapPtrAtom &getAtom(size_t index) const { js::HeapPtrAtom &getAtom(size_t index) const {
JS_ASSERT(index < natoms); JS_ASSERT(index < natoms);
return atoms[index]; return atoms[index];

Просмотреть файл

@ -1224,9 +1224,8 @@ ModOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs
static JS_ALWAYS_INLINE bool static JS_ALWAYS_INLINE bool
SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, const Value &value, SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, const Value &value,
bool strict, JSScript *maybeScript = NULL, jsbytecode *pc = NULL) bool strict, JSScript *script = NULL, jsbytecode *pc = NULL)
{ {
RootedScript script(cx, maybeScript);
types::TypeScript::MonitorAssign(cx, obj, id); types::TypeScript::MonitorAssign(cx, obj, id);
if (obj->isNative() && JSID_IS_INT(id)) { if (obj->isNative() && JSID_IS_INT(id)) {
@ -1234,14 +1233,12 @@ SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, con
int32_t i = JSID_TO_INT(id); int32_t i = JSID_TO_INT(id);
if ((uint32_t)i >= length) { if ((uint32_t)i >= length) {
// Annotate script if provided with information (e.g. baseline) // Annotate script if provided with information (e.g. baseline)
if (script && script->hasAnalysis()) { if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM)
JS_ASSERT(pc); script->baselineScript()->noteArrayWriteHole(pc - script->code);
script->analysis()->getCode(pc).arrayWriteHole = true;
}
} }
} }
if (obj->isNative() && !obj->setHadElementsAccess(cx)) if (obj->isNative() && !JSID_IS_INT(id) && !obj->setHadElementsAccess(cx))
return false; return false;
RootedValue tmp(cx, value); RootedValue tmp(cx, value);