diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-26 10:42:44 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-26 10:42:44 +0200 |
commit | 33b26980cb24288b5a9f2590ccf32a949281bb79 (patch) | |
tree | cc0203dac37338b24b0b25a4694c0b76d4e4164b /Source/JavaScriptCore | |
parent | 715be629d51174233403237bfc563cf150087dc8 (diff) | |
download | qtwebkit-33b26980cb24288b5a9f2590ccf32a949281bb79.tar.gz |
Imported WebKit commit c596dd7f03007fa7ed896b928106497e8784b3b5 (http://svn.webkit.org/repository/webkit/trunk@129610)
New snapshot that removes QtQuick1 support (to be moved into QtQuick1 module)
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r-- | Source/JavaScriptCore/ChangeLog | 142 | ||||
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGAbstractState.cpp | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp | 40 | ||||
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp | 3 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/Heap.cpp | 147 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/Heap.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/heap/MarkedSpace.h | 18 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/ArrayPrototype.cpp | 14 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/JSArray.cpp | 1 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp | 8 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.cpp | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.h | 36 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/Options.cpp | 10 | ||||
-rw-r--r-- | Source/JavaScriptCore/runtime/Options.h | 3 |
14 files changed, 377 insertions, 58 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 403a38c70..a5b548cab 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,145 @@ +2012-09-25 Gavin Barraclough <barraclough@apple.com> + + REGRESSION (r129456): http/tests/security/xss-eval.html is failing on JSC platforms + https://bugs.webkit.org/show_bug.cgi?id=97529 + + Reviewed by Filip Pizlo. + + A recent patch changed JSC's EvalError behaviour; bring this more into line with other browsers. + + JSC currently throws an EvalError if you try to call eval with a this object that doesn't + match the given eval function. This does not match other browsers, which generally just + ignore the this value that was passed, and eval the string in the eval function's environment. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + - Remove EvalError, ignore passed this value. + +2012-09-25 Filip Pizlo <fpizlo@apple.com> + + DFG ArrayPush, ArrayPop don't handle clobbering or having a bad time correctly + https://bugs.webkit.org/show_bug.cgi?id=97535 + + Reviewed by Oliver Hunt. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::handleIntrinsic): + * dfg/DFGStructureCheckHoistingPhase.cpp: + (JSC::DFG::StructureCheckHoistingPhase::run): + +2012-09-25 Geoffrey Garen <ggaren@apple.com> + + JSC should dump object size inference statistics + https://bugs.webkit.org/show_bug.cgi?id=97618 + + Reviewed by Filip Pizlo. + + Added an option to dump object size inference statistics. + + To see statistics on live objects: + + jsc --showHeapStatistics=1 + + To see cumulative statistics on all objects ever allocated: + + jsc --showHeapStatistics=1 --objectsAreImmortal=1 + + (This is useful for showing GC churn caused by over-allocation.) + + To support this second mode, I refactored Zombies to separate out their + immortality feature so I could reuse it. + + * heap/Heap.cpp: + (JSC::MarkObject): Helper for making things immortal. We have to checked + for being zapped because blocks start out in this state. + + (JSC::StorageStatistics): Gather statistics by walking the heap. Ignore + arrays and hash tables for now because they're not our focus. (We'll + remove these exceptions in future.) + + (JSC::Heap::collect): Moved zombify to the end so it wouldn't interfere + with statistics gathering. + + (JSC::Heap::showStatistics): + (JSC::Heap::markAllObjects): Factored out helper, so statistics could + take advantage of immortal objects. + + (Zombify): Don't mark immortal objects -- that's another class's job now. + + (JSC::Zombify::operator()): + (JSC::Heap::zombifyDeadObjects): Take advantage of forEachDeadCell instead + of rolling our own. + + * heap/Heap.h: + (Heap): + * heap/MarkedSpace.h: + (MarkedSpace): + (JSC::MarkedSpace::forEachDeadCell): Added, so clients don't have to do + the iteration logic themselves. + + * runtime/Options.cpp: + (JSC::Options::initialize): + * runtime/Options.h: New options, listed above. Make sure to initialize + based on environment variable first, so we can override with specific settings. + +2012-09-25 Filip Pizlo <fpizlo@apple.com> + + We shouldn't use the optimized versions of shift/unshift if the user is doing crazy things to the array + https://bugs.webkit.org/show_bug.cgi?id=97603 + <rdar://problem/12370864> + + Reviewed by Gavin Barraclough. + + You changed the length behind our backs? No optimizations for you then! + + * runtime/ArrayPrototype.cpp: + (JSC::shift): + (JSC::unshift): + * runtime/JSArray.cpp: + (JSC::JSArray::shiftCount): + +2012-09-25 Filip Pizlo <fpizlo@apple.com> + + JSC bindings appear to sometimes ignore the possibility of arrays being in sparse mode + https://bugs.webkit.org/show_bug.cgi?id=95610 + + Reviewed by Oliver Hunt. + + Add better support for quickly accessing the indexed storage from bindings. + + * runtime/JSObject.h: + (JSC::JSObject::tryGetIndexQuickly): + (JSObject): + (JSC::JSObject::getDirectIndex): + (JSC::JSObject::getIndex): + +2012-09-25 Filip Pizlo <fpizlo@apple.com> + + Structure check hoisting phase doesn't know about the side-effecting nature of Arrayify + https://bugs.webkit.org/show_bug.cgi?id=97537 + + Reviewed by Mark Hahnenberg. + + No tests because if we use Arrayify then we also use PutByVal(BlankToXYZ), and the latter is + already known to be side-effecting. So this bug shouldn't have had any symptoms, as far as I + can tell. + + * dfg/DFGStructureCheckHoistingPhase.cpp: + (JSC::DFG::StructureCheckHoistingPhase::run): + +2012-09-25 Gavin Barraclough <barraclough@apple.com> + + Regression: put beyond vector length prefers prototype setters to sparse properties + https://bugs.webkit.org/show_bug.cgi?id=97593 + + Reviewed by Geoff Garen & Filip Pizlo. + + * runtime/JSObject.cpp: + (JSC::JSObject::putByIndexBeyondVectorLength): + - Check for self properties in the sparse map - if present, don't examine the protochain. + 2012-09-24 Gavin Barraclough <barraclough@apple.com> https://bugs.webkit.org/show_bug.cgi?id=97530 diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index 18b5ad02a..db0861c7d 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -1001,11 +1001,13 @@ bool AbstractState::execute(unsigned indexInBlock) case ArrayPush: node.setCanExit(true); + clobberWorld(node.codeOrigin, indexInBlock); forNode(nodeIndex).set(SpecNumber); break; case ArrayPop: node.setCanExit(true); + clobberWorld(node.codeOrigin, indexInBlock); forNode(nodeIndex).makeTop(); break; diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 901b67b19..6d5f68200 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -1567,13 +1567,22 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return false; Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); - if (!modeIsJSArray(arrayMode)) + switch (arrayMode) { + case Array::ArrayWithArrayStorageToHole: + ASSERT_NOT_REACHED(); + + case Array::ArrayWithArrayStorage: + case Array::ArrayWithArrayStorageOutOfBounds: { + NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); + if (usesResult) + set(resultOperand, arrayPush); + + return true; + } + + default: return false; - NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); - if (usesResult) - set(resultOperand, arrayPush); - - return true; + } } case ArrayPopIntrinsic: { @@ -1581,12 +1590,21 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return false; Array::Mode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); - if (!modeIsJSArray(arrayMode)) + switch (arrayMode) { + case Array::ArrayWithArrayStorageToHole: + ASSERT_NOT_REACHED(); + + case Array::ArrayWithArrayStorage: + case Array::ArrayWithArrayStorageOutOfBounds: { + NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); + if (usesResult) + set(resultOperand, arrayPop); + return true; + } + + default: return false; - NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); - if (usesResult) - set(resultOperand, arrayPop); - return true; + } } case CharCodeAtIntrinsic: { diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp index 0838bb7e5..5b0b22963 100644 --- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp @@ -315,6 +315,9 @@ public: case ResolveBase: case ResolveBaseStrictPut: case ResolveGlobal: + case ArrayPush: + case ArrayPop: + case Arrayify: clobber(live); break; diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index c7fb8c015..ca936ebfc 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -176,6 +176,15 @@ static inline bool isValidThreadState(JSGlobalData* globalData) return true; } +struct MarkObject : public MarkedBlock::VoidFunctor { + void operator()(JSCell* cell) + { + if (cell->isZapped()) + return; + Heap::heap(cell)->setMarked(cell); + } +}; + struct Count : public MarkedBlock::CountFunctor { void operator()(JSCell*) { count(1); } }; @@ -226,6 +235,74 @@ inline PassOwnPtr<TypeCountSet> RecordType::returnValue() return m_typeCountSet.release(); } +class StorageStatistics : public MarkedBlock::VoidFunctor { +public: + StorageStatistics(); + + void operator()(JSCell*); + + size_t objectWithOutOfLineStorageCount(); + size_t objectCount(); + + size_t storageSize(); + size_t storageCapacity(); + +private: + size_t m_objectWithOutOfLineStorageCount; + size_t m_objectCount; + size_t m_storageSize; + size_t m_storageCapacity; +}; + +inline StorageStatistics::StorageStatistics() + : m_objectWithOutOfLineStorageCount(0) + , m_objectCount(0) + , m_storageSize(0) + , m_storageCapacity(0) +{ +} + +inline void StorageStatistics::operator()(JSCell* cell) +{ + if (!cell->isObject()) + return; + + JSObject* object = jsCast<JSObject*>(cell); + if (hasIndexedProperties(object->structure()->indexingType())) + return; + + if (object->structure()->isUncacheableDictionary()) + return; + + ++m_objectCount; + if (!object->hasInlineStorage()) + ++m_objectWithOutOfLineStorageCount; + m_storageSize += object->structure()->totalStorageSize() * sizeof(WriteBarrierBase<Unknown>); + m_storageCapacity += object->structure()->totalStorageCapacity() * sizeof(WriteBarrierBase<Unknown>); +} + +inline size_t StorageStatistics::objectWithOutOfLineStorageCount() +{ + return m_objectWithOutOfLineStorageCount; +} + +inline size_t StorageStatistics::objectCount() +{ + return m_objectCount; +} + + +inline size_t StorageStatistics::storageSize() +{ + return m_storageSize; +} + + +inline size_t StorageStatistics::storageCapacity() +{ + return m_storageCapacity; +} + } // anonymous namespace Heap::Heap(JSGlobalData* globalData, HeapType heapType) @@ -753,9 +830,6 @@ void Heap::collect(SweepToggle sweepToggle) m_objectSpace.resetAllocators(); } - if (Options::useZombieMode()) - zombifyDeadObjects(); - size_t currentHeapSize = size(); if (fullGC) { m_sizeAfterLastCollect = currentHeapSize; @@ -769,10 +843,48 @@ void Heap::collect(SweepToggle sweepToggle) m_bytesAllocated = 0; double lastGCEndTime = WTF::currentTime(); m_lastGCLength = lastGCEndTime - lastGCStartTime; + if (m_operationInProgress != Collection) CRASH(); m_operationInProgress = NoOperation; JAVASCRIPTCORE_GC_END(); + + if (Options::useZombieMode()) + zombifyDeadObjects(); + + if (Options::objectsAreImmortal()) + markDeadObjects(); + + if (Options::showHeapStatistics()) + showStatistics(); +} + +void Heap::showStatistics() +{ + dataLog("\n=== Heap Statistics: ===\n"); + dataLog("size: %ldkB\n", static_cast<long>(m_sizeAfterLastCollect / KB)); + dataLog("capacity: %ldkB\n", static_cast<long>(capacity() / KB)); + dataLog("pause time: %lfms\n\n", m_lastGCLength); + + StorageStatistics storageStatistics; + m_objectSpace.forEachLiveCell(storageStatistics); + dataLog("wasted .property storage: %ldkB (%ld%%)\n", + static_cast<long>( + (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB), + static_cast<long>( + (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 + / storageStatistics.storageCapacity())); + dataLog("objects with out-of-line .property storage: %ld (%ld%%)\n", + static_cast<long>( + storageStatistics.objectWithOutOfLineStorageCount()), + static_cast<long>( + storageStatistics.objectWithOutOfLineStorageCount() * 100 + / storageStatistics.objectCount())); +} + +void Heap::markDeadObjects() +{ + m_objectSpace.forEachDeadCell<MarkObject>(); } void Heap::setActivityCallback(GCActivityCallback* activityCallback) @@ -844,18 +956,10 @@ void Heap::didStartVMShutdown() lastChanceToFinalize(); } -class ZombifyCellFunctor : public MarkedBlock::VoidFunctor { +class Zombify : public MarkedBlock::VoidFunctor { public: - ZombifyCellFunctor(size_t cellSize) - : m_cellSize(cellSize) - { - } - void operator()(JSCell* cell) { - if (Options::zombiesAreImmortal()) - MarkedBlock::blockFor(cell)->setMarked(cell); - void** current = reinterpret_cast<void**>(cell); // We want to maintain zapped-ness because that's how we know if we've called @@ -863,30 +967,17 @@ public: if (cell->isZapped()) current++; - void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + m_cellSize); + void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + MarkedBlock::blockFor(cell)->cellSize()); for (; current < limit; current++) *current = reinterpret_cast<void*>(0xbbadbeef); } - -private: - size_t m_cellSize; -}; - -class ZombifyBlockFunctor : public MarkedBlock::VoidFunctor { -public: - void operator()(MarkedBlock* block) - { - ZombifyCellFunctor functor(block->cellSize()); - block->forEachDeadCell(functor); - } }; void Heap::zombifyDeadObjects() { + // Sweep now because destructors will crash once we're zombified. m_objectSpace.sweep(); - - ZombifyBlockFunctor functor; - m_objectSpace.forEachBlock(functor); + m_objectSpace.forEachDeadCell<Zombify>(); } } // namespace JSC diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index c9bbec1f6..92efff7c5 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -145,6 +145,7 @@ namespace JSC { JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount(); JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> protectedObjectTypeCounts(); JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> objectTypeCounts(); + void showStatistics(); void pushTempSortVector(Vector<ValueStringPair>*); void popTempSortVector(Vector<ValueStringPair>*); @@ -205,7 +206,8 @@ namespace JSC { void finalizeUnconditionalFinalizers(); void deleteUnmarkedCompiledCode(); void zombifyDeadObjects(); - + void markDeadObjects(); + RegisterFile& registerFile(); BlockAllocator& blockAllocator(); diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index e68ba9172..151099b60 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -95,6 +95,8 @@ public: template<typename Functor> typename Functor::ReturnType forEachLiveCell(Functor&); template<typename Functor> typename Functor::ReturnType forEachLiveCell(); + template<typename Functor> typename Functor::ReturnType forEachDeadCell(Functor&); + template<typename Functor> typename Functor::ReturnType forEachDeadCell(); template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&); template<typename Functor> typename Functor::ReturnType forEachBlock(); @@ -156,6 +158,22 @@ template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forE return forEachLiveCell(functor); } +template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(Functor& functor) +{ + canonicalizeCellLivenessData(); + + BlockIterator end = m_blocks.set().end(); + for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) + (*it)->forEachDeadCell(functor); + return functor.returnValue(); +} + +template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell() +{ + Functor functor; + return forEachDeadCell(functor); +} + inline MarkedAllocator& MarkedSpace::firstAllocator() { return m_normalSpace.preciseAllocators[0]; diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 95cba0936..1eacd1179 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -202,8 +202,11 @@ static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, un ASSERT(header <= length); ASSERT(currentCount <= (length - header)); - if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count)) - return; + if (!header && isJSArray(thisObj)) { + JSArray* array = asArray(thisObj); + if (array->length() == length && asArray(thisObj)->shiftCount(exec, count)) + return; + } for (unsigned k = header; k < length - currentCount; ++k) { unsigned from = k + currentCount; @@ -242,8 +245,11 @@ static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, return; } - if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count)) - return; + if (!header && isJSArray(thisObj)) { + JSArray* array = asArray(thisObj); + if (array->length() == length && asArray(thisObj)->unshiftCount(exec, count)) + return; + } for (unsigned k = length - currentCount; k > header; --k) { unsigned from = k + currentCount - 1; diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 609781c65..8398ae77d 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -499,6 +499,7 @@ bool JSArray::shiftCount(ExecState* exec, unsigned count) ArrayStorage* storage = ensureArrayStorage(exec->globalData()); unsigned oldLength = storage->length(); + ASSERT(count <= oldLength); // If the array contains holes or is otherwise in an abnormal state, // use the generic algorithm in ArrayPrototype. diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index c85965060..8b1acb25a 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -497,11 +497,6 @@ static double parseFloat(const String& s) EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) { - JSObject* thisObject = exec->hostThisValue().toThisObject(exec); - JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject(); - if (thisObject != exec->callee()->globalObject()->globalThis()) - return throwVMError(exec, createEvalError(exec, ASCIILiteral("The \"this\" value passed to eval must be the global object from which eval originated"))); - JSValue x = exec->argument(0); if (!x.isString()) return JSValue::encode(x); @@ -518,12 +513,13 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) return JSValue::encode(parsedObject); } + JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject(); EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); JSObject* error = eval->compile(exec, calleeGlobalObject); if (error) return throwVMError(exec, error); - return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, calleeGlobalObject)); + return JSValue::encode(exec->interpreter()->execute(eval, exec, calleeGlobalObject->globalThis(), calleeGlobalObject)); } EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 7bf12b67e..bf38f6876 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -1350,10 +1350,13 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue } case NonArrayWithSlowPutArrayStorage: - case ArrayWithSlowPutArrayStorage: - if (attemptToInterceptPutByIndexOnHole(exec, i, value, shouldThrow)) + case ArrayWithSlowPutArrayStorage: { + // No own property present in the vector, but there might be in the sparse map! + SparseArrayValueMap* map = arrayStorage()->m_sparseMap.get(); + if (!(map && map->contains(i)) && attemptToInterceptPutByIndexOnHole(exec, i, value, shouldThrow)) return; // Otherwise, fall though. + } case NonArrayWithArrayStorage: case ArrayWithArrayStorage: diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 16efeba5e..4b9cff5ad 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -226,6 +226,42 @@ namespace JSC { } } + JSValue tryGetIndexQuickly(unsigned i) + { + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: + break; + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + if (i < m_butterfly->arrayStorage()->vectorLength()) { + JSValue v = m_butterfly->arrayStorage()->m_vector[i].get(); + if (v) + return v; + } + break; + default: + ASSERT_NOT_REACHED(); + break; + } + return JSValue(); + } + + JSValue getDirectIndex(ExecState* exec, unsigned i) + { + if (JSValue result = tryGetIndexQuickly(i)) + return result; + PropertySlot slot(this); + if (methodTable()->getOwnPropertySlotByIndex(this, exec, i, slot)) + return slot.getValue(exec, i); + return JSValue(); + } + + JSValue getIndex(ExecState* exec, unsigned i) + { + if (JSValue result = tryGetIndexQuickly(i)) + return result; + return get(exec, i); + } + bool canSetIndexQuickly(unsigned i) { switch (structure()->indexingType()) { diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index b164948a5..ed0720b54 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -127,6 +127,11 @@ void Options::initialize() JSC_OPTIONS(FOR_EACH_OPTION) #undef FOR_EACH_OPTION +#if USE(CF) || OS(UNIX) + objectsAreImmortal() = !!getenv("JSImmortalZombieEnabled"); + useZombieMode() = !!getenv("JSImmortalZombieEnabled") || !!getenv("JSZombieEnabled"); +#endif + // Allow environment vars to override options if applicable. // The evn var should be the name of the option prefixed with // "JSC_". @@ -149,11 +154,6 @@ void Options::initialize() useRegExpJIT() = false; #endif -#if USE(CF) || OS(UNIX) - zombiesAreImmortal() = !!getenv("JSImmortalZombieEnabled"); - useZombieMode() = zombiesAreImmortal() || !!getenv("JSZombieEnabled"); -#endif - // Do range checks where needed and make corrections to the options: ASSERT(thresholdForOptimizeAfterLongWarmUp() >= thresholdForOptimizeAfterWarmUp()); ASSERT(thresholdForOptimizeAfterWarmUp() >= thresholdForOptimizeSoon()); diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index 5e53d1cf2..7571f9138 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.h @@ -121,7 +121,8 @@ namespace JSC { v(unsigned, forcedWeakRandomSeed, 0) \ \ v(bool, useZombieMode, false) \ - v(bool, zombiesAreImmortal, false) + v(bool, objectsAreImmortal, false) \ + v(bool, showHeapStatistics, false) class Options { |