summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-09-26 10:42:44 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-09-26 10:42:44 +0200
commit33b26980cb24288b5a9f2590ccf32a949281bb79 (patch)
treecc0203dac37338b24b0b25a4694c0b76d4e4164b /Source/JavaScriptCore
parent715be629d51174233403237bfc563cf150087dc8 (diff)
downloadqtwebkit-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/ChangeLog142
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp2
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp40
-rw-r--r--Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp3
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp147
-rw-r--r--Source/JavaScriptCore/heap/Heap.h4
-rw-r--r--Source/JavaScriptCore/heap/MarkedSpace.h18
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h36
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/Options.h3
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 {