From 67b88e4fd787ea44ef5ab06dfc28375d9e63452a Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Wed, 18 Sep 2013 09:43:21 -0600 Subject: [PATCH] Bug 917441 - Remove dependence of IonBuilder on ScriptAnalysis, r=jandem. --- js/src/jit/BaselineIC.cpp | 10 +++++ js/src/jit/BaselineIC.h | 7 +++ js/src/jit/BaselineInspector.cpp | 6 +++ js/src/jit/BaselineJIT.h | 1 + js/src/jit/BytecodeAnalysis.cpp | 24 ++++++++++- js/src/jit/BytecodeAnalysis.h | 11 +++++ js/src/jit/Ion.cpp | 3 -- js/src/jit/IonBuilder.cpp | 73 +++++++++++++++++++------------- js/src/jit/IonBuilder.h | 9 ++++ js/src/jit/MIRGraph.cpp | 14 +++--- js/src/jit/MIRGraph.h | 5 ++- js/src/jsanalyze.h | 7 --- js/src/jsobj.cpp | 6 --- js/src/jsscript.cpp | 14 ++++++ js/src/jsscript.h | 2 + js/src/vm/Interpreter.cpp | 11 ++--- 16 files changed, 140 insertions(+), 63 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index d568cbd658ce..c73c8da82040 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -4817,6 +4817,16 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler &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 // diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h index d197005f2c3b..3f10c72d4d8e 100644 --- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -3375,6 +3375,13 @@ class ICSetElem_Fallback : public ICFallbackStub return space->allocate(code); } + void noteArrayWriteHole() { + extra_ = 1; + } + bool hasArrayWriteHole() const { + return extra_; + } + // Compiler for this stub kind. class Compiler : public ICStubCompiler { protected: diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index 25a880ffa3b4..4f427bbd2e92 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -26,6 +26,12 @@ SetElemICInspector::sawOOBDenseWrite() const if (stub->isSetElem_DenseAdd()) 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; } diff --git a/js/src/jit/BaselineJIT.h b/js/src/jit/BaselineJIT.h index fc892a5b3955..15a586501015 100644 --- a/js/src/jit/BaselineJIT.h +++ b/js/src/jit/BaselineJIT.h @@ -267,6 +267,7 @@ struct BaselineScript void toggleSPS(bool enable); void noteAccessedGetter(uint32_t pcOffset); + void noteArrayWriteHole(uint32_t pcOffset); static size_t offsetOfFlags() { return offsetof(BaselineScript, flags_); diff --git a/js/src/jit/BytecodeAnalysis.cpp b/js/src/jit/BytecodeAnalysis.cpp index eb7a88697ec6..e7dd8a55bd89 100644 --- a/js/src/jit/BytecodeAnalysis.cpp +++ b/js/src/jit/BytecodeAnalysis.cpp @@ -15,7 +15,9 @@ using namespace js::jit; BytecodeAnalysis::BytecodeAnalysis(JSScript *script) : script_(script), - infos_() + infos_(), + usesScopeChain_(false), + hasTryFinally_(false) { } @@ -144,6 +146,26 @@ BytecodeAnalysis::init(JSContext *cx) } 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: break; } diff --git a/js/src/jit/BytecodeAnalysis.h b/js/src/jit/BytecodeAnalysis.h index c6e457dc0d38..275a6753e0b6 100644 --- a/js/src/jit/BytecodeAnalysis.h +++ b/js/src/jit/BytecodeAnalysis.h @@ -39,6 +39,9 @@ class BytecodeAnalysis JSScript *script_; Vector infos_; + bool usesScopeChain_; + bool hasTryFinally_; + public: explicit BytecodeAnalysis(JSScript *script); @@ -54,6 +57,14 @@ class BytecodeAnalysis return &infos_[pc - script_->code]; return NULL; } + + bool usesScopeChain() { + return usesScopeChain_; + } + + bool hasTryFinally() { + return hasTryFinally_; + } }; diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 2cc61bb0451a..db049b00aae4 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -1606,9 +1606,6 @@ IonCompile(JSContext *cx, JSScript *script, script); #endif - if (!script->ensureRanAnalysis(cx)) - return AbortReason_Alloc; - LifoAlloc *alloc = cx->new_(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE); if (!alloc) return AbortReason_Alloc; diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index 6eaaa32ce6cd..a0cfc43272c6 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -42,6 +42,7 @@ IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph, cx(cx), baselineFrame_(baselineFrame), abortReason_(AbortReason_Disable), + analysis_(info->script()), loopDepth_(loopDepth), callerResumePoint_(NULL), callerBuilder_(NULL), @@ -231,10 +232,10 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target) JSScript *targetScript = target->nonLazyScript(); - if (!targetScript->ensureRanAnalysis(cx)) + if (targetScript->uninlineable) return false; - if (targetScript->uninlineable) + if (!targetScript->analyzedArgsUsage()) return false; if (targetScript->needsArgsObj()) @@ -370,7 +371,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecod continue; if (slot >= info().firstStackSlot()) continue; - if (!script()->analysis()->maybeCode(pc)) + if (!analysis().maybeInfo(pc)) continue; MPhi *phi = entry->getSlot(slot)->toPhi(); @@ -491,11 +492,23 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e } bool -IonBuilder::build() +IonBuilder::init() { if (!script()->ensureHasBytecodeTypeMap(cx)) return false; + if (!analysis().init(cx)) + return false; + + return true; +} + +bool +IonBuilder::build() +{ + if (!init()) + return false; + setCurrentAndSpecializePhis(newBlock(pc)); if (!current) return false; @@ -633,11 +646,11 @@ bool IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint, CallInfo &callInfo) { - inlineCallInfo_ = &callInfo; - - if (!script()->ensureHasBytecodeTypeMap(cx)) + if (!init()) return false; + inlineCallInfo_ = &callInfo; + IonSpew(IonSpew_Scripts, "Inlining script %s:%d (%p)", 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 // for the script, since arguments object construction requires the scope chain // to be passed in. - if (!info().needsArgsObj() && !script()->analysis()->usesScopeChain()) + if (!info().needsArgsObj() && !analysis().usesScopeChain()) return true; // 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"); // Try-finally is not yet supported. - if (script()->analysis()->hasTryFinally()) + if (analysis().hasTryFinally()) return abort("Has try-finally"); // Try-catch within inline frames is not yet supported. @@ -3401,7 +3414,7 @@ IonBuilder::jsop_try() return false; MBasicBlock *successor; - if (script()->analysis()->maybeCode(afterTry)) { + if (analysis().maybeInfo(afterTry)) { successor = newBlock(current, afterTry); if (!successor) return false; @@ -3748,7 +3761,10 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target) BaselineInspector inspector(cx, calleeScript); // 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); if (!types->unknown()) { 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, inliningDepth_ + 1, loopDepth_); if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) { - JS_ASSERT(calleeScript->hasAnalysis()); if (cx->isExceptionPending()) { IonSpew(IonSpew_Abort, "Inline builder raised exception."); abortReason_ = AbortReason_Error; @@ -3931,7 +3946,7 @@ IonBuilder::makeInliningDecision(JSFunction *target, CallInfo &callInfo) return false; } - if (targetScript->analysis()->hasLoops()) { + if (targetScript->hasLoops()) { IonSpew(IonSpew_Inlining, "%s:%d - Vetoed: big function that contains a loop", targetScript->filename(), targetScript->lineno); return false; @@ -5087,7 +5102,7 @@ IonBuilder::testNeedsArgumentCheck(JSContext *cx, JSFunction *target, CallInfo & return true; JSScript *targetScript = target->nonLazyScript(); - if (!targetScript->hasAnalysis()) + if (!targetScript->types) return true; if (!ArgumentTypesMatch(callInfo.thisArg(), cloneTypeSet(types::TypeScript::ThisTypes(targetScript)))) @@ -5661,7 +5676,8 @@ IonBuilder::addBlock(MBasicBlock *block, uint32_t loopDepth) MBasicBlock * 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_); } @@ -5683,7 +5699,8 @@ IonBuilder::newBlockPopN(MBasicBlock *predecessor, jsbytecode *pc, uint32_t popp MBasicBlock * 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) return NULL; graph().insertBlockAfter(at, block); @@ -5693,7 +5710,8 @@ IonBuilder::newBlockAfter(MBasicBlock *at, MBasicBlock *predecessor, jsbytecode MBasicBlock * 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); } @@ -5719,7 +5737,7 @@ IonBuilder::newOsrPreheader(MBasicBlock *predecessor, jsbytecode *loopEntry) uint32_t slot = info().scopeChainSlot(); MInstruction *scopev; - if (script()->analysis()->usesScopeChain()) { + if (analysis().usesScopeChain()) { scopev = MOsrScopeChain::New(entry); } else { // Use an undefined value if the script does not need its scope @@ -6470,7 +6488,7 @@ IonBuilder::jsop_intrinsic(PropertyName *name) bool IonBuilder::jsop_bindname(PropertyName *name) { - JS_ASSERT(script()->analysis()->usesScopeChain()); + JS_ASSERT(analysis().usesScopeChain()); MDefinition *scopeChain = current->scopeChain(); 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"); } - bool writeHole; + bool writeHole = false; if (safety == SetElem_Normal) { - writeHole = script()->analysis()->getCode(pc).arrayWriteHole; SetElemICInspector icInspect(inspector->setElemICInspector(pc)); - writeHole |= icInspect.sawOOBDenseWrite(); - } else { - writeHole = false; + writeHole = icInspect.sawOOBDenseWrite(); } // 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) { JS_ASSERT(*emitted == false); - bool accessGetter = - script()->analysis()->getCode(pc).accessGetter || - inspector->hasSeenAccessedGetter(pc); + bool accessGetter = inspector->hasSeenAccessedGetter(pc); MDefinition *obj = current->peek(-1); @@ -8831,7 +8844,7 @@ IonBuilder::jsop_lambda(JSFunction *fun) if (fun->isInterpreted() && !fun->getOrCreateScript(cx)) return false; - JS_ASSERT(script()->analysis()->usesScopeChain()); + JS_ASSERT(analysis().usesScopeChain()); if (fun->isArrow()) return abort("bound arrow function"); if (fun->isNative() && IsAsmJSModuleNative(fun->native())) @@ -8857,7 +8870,7 @@ IonBuilder::jsop_defvar(uint32_t index) attrs |= JSPROP_READONLY; // Pass the ScopeChain. - JS_ASSERT(script()->analysis()->usesScopeChain()); + JS_ASSERT(analysis().usesScopeChain()); // Bake the name pointer into the MDefVar. MDefVar *defvar = MDefVar::New(name, attrs, current->scopeChain()); @@ -8873,7 +8886,7 @@ IonBuilder::jsop_deffun(uint32_t index) if (fun->isNative() && IsAsmJSModuleNative(fun->native())) return abort("asm.js module function"); - JS_ASSERT(script()->analysis()->usesScopeChain()); + JS_ASSERT(analysis().usesScopeChain()); MDefFun *deffun = MDefFun::New(fun, current->scopeChain()); current->add(deffun); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 0eabbe9220bd..530eec264d0e 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -12,6 +12,7 @@ // This file declares the data structures for building a MIRGraph from a // JSScript. +#include "jit/BytecodeAnalysis.h" #include "jit/MIR.h" #include "jit/MIRGraph.h" @@ -640,10 +641,18 @@ class IonBuilder : public MIRGenerator AbortReason abortReason() { return abortReason_; } private: + bool init(); + JSContext *cx; BaselineFrame *baselineFrame_; AbortReason abortReason_; + // Basic analysis information about the script. + BytecodeAnalysis analysis_; + BytecodeAnalysis &analysis() { + return analysis_; + } + jsbytecode *pc; MBasicBlock *current; uint32_t loopDepth_; diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp index 29f34871224a..fa5f39d86854 100644 --- a/js/src/jit/MIRGraph.cpp +++ b/js/src/jit/MIRGraph.cpp @@ -158,7 +158,7 @@ MIRGraph::forkJoinSlice() } MBasicBlock * -MBasicBlock::New(MIRGraph &graph, CompileInfo &info, +MBasicBlock::New(MIRGraph &graph, BytecodeAnalysis *analysis, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind) { JS_ASSERT(entryPc != NULL); @@ -167,7 +167,7 @@ MBasicBlock::New(MIRGraph &graph, CompileInfo &info, if (!block->init()) return NULL; - if (!block->inherit(pred, 0)) + if (!block->inherit(analysis, pred, 0)) return NULL; return block; @@ -181,7 +181,7 @@ MBasicBlock::NewPopN(MIRGraph &graph, CompileInfo &info, if (!block->init()) return NULL; - if (!block->inherit(pred, popped)) + if (!block->inherit(NULL, pred, popped)) return NULL; return block; @@ -210,14 +210,14 @@ MBasicBlock * MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, 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::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred) { 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); } @@ -323,7 +323,7 @@ MBasicBlock::copySlots(MBasicBlock *from) } bool -MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) +MBasicBlock::inherit(BytecodeAnalysis *analysis, MBasicBlock *pred, uint32_t popped) { if (pred) { stackPosition_ = pred->stackPosition_; @@ -332,7 +332,7 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) if (kind_ != PENDING_LOOP_HEADER) copySlots(pred); } else { - uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth; + uint32_t stackDepth = analysis->info(pc()).stackDepth; stackPosition_ = info().firstStackSlot() + stackDepth; JS_ASSERT(stackPosition_ >= popped); stackPosition_ -= popped; diff --git a/js/src/jit/MIRGraph.h b/js/src/jit/MIRGraph.h index 4140551c532d..a253743bdb67 100644 --- a/js/src/jit/MIRGraph.h +++ b/js/src/jit/MIRGraph.h @@ -18,6 +18,7 @@ namespace js { namespace jit { +class BytecodeAnalysis; class MBasicBlock; class MIRGraph; class MStart; @@ -46,7 +47,7 @@ class MBasicBlock : public TempObject, public InlineListNode MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind); bool init(); void copySlots(MBasicBlock *from); - bool inherit(MBasicBlock *pred, uint32_t popped); + bool inherit(BytecodeAnalysis *analysis, MBasicBlock *pred, uint32_t popped); bool inheritResumePoint(MBasicBlock *pred); void assertUsesAreNotWithin(MUseIterator use, MUseIterator end); @@ -67,7 +68,7 @@ class MBasicBlock : public TempObject, public InlineListNode // Creates a new basic block for a MIR generator. If |pred| is not NULL, // 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); static MBasicBlock *NewPopN(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind, uint32_t popn); diff --git a/js/src/jsanalyze.h b/js/src/jsanalyze.h index e7877837886b..c3bbf1aa7267 100644 --- a/js/src/jsanalyze.h +++ b/js/src/jsanalyze.h @@ -78,13 +78,6 @@ class Bytecode /* Whether this is a catch/finally entry point. */ 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. */ uint32_t stackDepth; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 0347d1b2f794..3f43dafe9057 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -4040,12 +4040,6 @@ NativeGetInline(JSContext *cx, { jsbytecode *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 if (script && script->hasBaselineScript()) { switch (JSOp(*pc)) { diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 8e24d92262b9..32765aee5aab 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -2959,6 +2959,20 @@ JSScript::updateBaselineOrIonRaw() #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 LazyScriptHash(uint32_t lineno, uint32_t column, uint32_t begin, uint32_t end, HashNumber hashes[3]) diff --git a/js/src/jsscript.h b/js/src/jsscript.h index b872b4f515e8..12cc33a08565 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -932,6 +932,8 @@ class JSScript : public js::gc::Cell return reinterpret_cast(data + trynotesOffset()); } + bool hasLoops(); + js::HeapPtrAtom &getAtom(size_t index) const { JS_ASSERT(index < natoms); return atoms[index]; diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 15130f61d80b..f56b72a47bd3 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1224,9 +1224,8 @@ ModOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lhs static JS_ALWAYS_INLINE bool SetObjectElementOperation(JSContext *cx, Handle 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); if (obj->isNative() && JSID_IS_INT(id)) { @@ -1234,14 +1233,12 @@ SetObjectElementOperation(JSContext *cx, Handle obj, HandleId id, con int32_t i = JSID_TO_INT(id); if ((uint32_t)i >= length) { // Annotate script if provided with information (e.g. baseline) - if (script && script->hasAnalysis()) { - JS_ASSERT(pc); - script->analysis()->getCode(pc).arrayWriteHole = true; - } + if (script && script->hasBaselineScript() && *pc == JSOP_SETELEM) + script->baselineScript()->noteArrayWriteHole(pc - script->code); } } - if (obj->isNative() && !obj->setHadElementsAccess(cx)) + if (obj->isNative() && !JSID_IS_INT(id) && !obj->setHadElementsAccess(cx)) return false; RootedValue tmp(cx, value);