diff options
author | Steve Block <steveblock@google.com> | 2011-05-18 13:36:51 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-24 15:38:28 +0100 |
commit | 2fc2651226baac27029e38c9d6ef883fa32084db (patch) | |
tree | e396d4bf89dcce6ed02071be66212495b1df1dec /Source/JavaScriptCore/runtime | |
parent | b3725cedeb43722b3b175aaeff70552e562d2c94 (diff) | |
download | external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2 |
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/JavaScriptCore/runtime')
93 files changed, 1632 insertions, 1436 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp index ab2b5d7..a862ea0 100644 --- a/Source/JavaScriptCore/runtime/ArgList.cpp +++ b/Source/JavaScriptCore/runtime/ArgList.cpp @@ -42,7 +42,7 @@ void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet) ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { MarkedArgumentBuffer* list = *it; - markStack.appendValues(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size); + markStack.deprecatedAppendValues(list->m_buffer, list->m_size); } } diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index 39886a8..305b247 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -48,17 +48,17 @@ void Arguments::markChildren(MarkStack& markStack) JSObject::markChildren(markStack); if (d->registerArray) - markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters); + markStack.deprecatedAppendValues(d->registerArray.get(), d->numParameters); if (d->extraArguments) { unsigned numExtraArguments = d->numArguments - d->numParameters; - markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments); + markStack.deprecatedAppendValues(d->extraArguments, numExtraArguments); } - markStack.append(d->callee); + markStack.append(&d->callee); if (d->activation) - markStack.append(d->activation); + markStack.append(&d->activation); } void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) @@ -197,7 +197,7 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { if (!d->isStrictMode) { - slot.setValue(d->callee); + slot.setValue(d->callee.get()); return true; } createStrictModeCalleeIfNecessary(exec); @@ -228,7 +228,7 @@ bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& prop if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { if (!d->isStrictMode) { - descriptor.setDescriptor(d->callee, DontEnum); + descriptor.setDescriptor(d->callee.get(), DontEnum); return true; } createStrictModeCalleeIfNecessary(exec); @@ -253,7 +253,7 @@ void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& property JSObject::getOwnPropertyNames(exec, propertyNames, mode); } -void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, unsigned i, JSValue value) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) @@ -263,6 +263,7 @@ void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& return; } + PutPropertySlot slot; JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot); } @@ -280,14 +281,14 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val if (propertyName == exec->propertyNames().length && !d->overrodeLength) { d->overrodeLength = true; - putDirect(propertyName, value, DontEnum); + putDirect(exec->globalData(), propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { if (!d->isStrictMode) { d->overrodeCallee = true; - putDirect(propertyName, value, DontEnum); + putDirect(exec->globalData(), propertyName, value, DontEnum); return; } createStrictModeCalleeIfNecessary(exec); @@ -303,7 +304,7 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i) { if (i < d->numArguments) { if (!d->deletedArguments) { - d->deletedArguments.set(new bool[d->numArguments]); + d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]); memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); } if (!d->deletedArguments[i]) { @@ -321,7 +322,7 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments) { if (!d->deletedArguments) { - d->deletedArguments.set(new bool[d->numArguments]); + d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]); memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); } if (!d->deletedArguments[i]) { diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index fe900a2..658538b 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -37,7 +37,7 @@ namespace JSC { WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED; public: ArgumentsData() { } - JSActivation* activation; + WriteBarrier<JSActivation> activation; unsigned numParameters; ptrdiff_t firstParameterIndex; @@ -50,7 +50,7 @@ namespace JSC { OwnArrayPtr<bool> deletedArguments; Register extraArgumentsFixedBuffer[4]; - JSFunction* callee; + WriteBarrier<JSFunction> callee; bool overrodeLength : 1; bool overrodeCallee : 1; bool overrodeCaller : 1; @@ -86,9 +86,9 @@ namespace JSC { void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize); void copyRegisters(); bool isTornOff() const { return d->registerArray; } - void setActivation(JSActivation* activation) + void setActivation(JSGlobalData& globalData, JSActivation* activation) { - d->activation = activation; + d->activation.set(globalData, this, activation); d->registers = &activation->registerAt(0); } @@ -107,7 +107,7 @@ namespace JSC { virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); + virtual void put(ExecState*, unsigned propertyName, JSValue); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); void createStrictModeCallerIfNecessary(ExecState*); @@ -158,7 +158,6 @@ namespace JSC { d->firstParameterIndex = firstParameterIndex; d->numArguments = numArguments; - d->activation = 0; d->registers = callFrame->registers(); Register* extraArguments; @@ -176,7 +175,7 @@ namespace JSC { d->extraArguments = extraArguments; - d->callee = callee; + d->callee.set(callFrame->globalData(), this, callee); d->overrodeLength = false; d->overrodeCallee = false; d->overrodeCaller = false; @@ -195,7 +194,6 @@ namespace JSC { d->numParameters = 0; d->numArguments = numArguments; - d->activation = 0; Register* extraArguments; if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) @@ -209,7 +207,7 @@ namespace JSC { d->extraArguments = extraArguments; - d->callee = asFunction(callFrame->callee()); + d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee())); d->overrodeLength = false; d->overrodeCallee = false; d->overrodeCaller = false; @@ -228,10 +226,10 @@ namespace JSC { int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize; size_t registerArraySize = d->numParameters; - Register* registerArray = new Register[registerArraySize]; - memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register)); - d->registerArray.set(registerArray); - d->registers = registerArray + registerOffset; + OwnArrayPtr<Register> registerArray = adoptArrayPtr(new Register[registerArraySize]); + memcpy(registerArray.get(), d->registers - registerOffset, registerArraySize * sizeof(Register)); + d->registers = registerArray.get() + registerOffset; + d->registerArray = registerArray.release(); } // This JSActivation function is defined here so it can get at Arguments::setRegisters. @@ -249,8 +247,9 @@ namespace JSC { int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize; size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; - Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize); - setRegisters(registerArray + registerOffset, registerArray); + OwnArrayPtr<Register> registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize); + Register* registers = registerArray.get() + registerOffset; + setRegisters(registers, registerArray.release()); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index 632d466..5d0adbd 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -42,10 +42,10 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className)) { // ECMA 15.4.3.1 Array.prototype - putDirectWithoutTransition(exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); // ES5 putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum); @@ -62,7 +62,7 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi } // otherwise the array is constructed with the arguments in it - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), args); + return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), args); } static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 7615ffc..70c0d06 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -117,7 +117,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) : JSArray(structure) { - putAnonymousValue(0, globalObject); + putAnonymousValue(globalObject->globalData(), 0, globalObject); } bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -545,9 +545,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) JSArray* resObj = new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact); JSValue result = resObj; - + JSGlobalData& globalData = exec->globalData(); for (unsigned k = 0; k < deleteCount; k++) - resObj->uncheckedSetIndex(k, getProperty(exec, thisObj, k + begin)); + resObj->uncheckedSetIndex(globalData, k, getProperty(exec, thisObj, k + begin)); resObj->setLength(deleteCount); diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index db2d1d7..0f6a646 100644 --- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -34,8 +34,9 @@ namespace JSC { class BatchedTransitionOptimizer { WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer); public: - BatchedTransitionOptimizer(JSObject* object) - : m_object(object) + BatchedTransitionOptimizer(JSGlobalData& globalData, JSObject* object) + : m_globalData(&globalData) + , m_object(object) { if (!m_object->structure()->isDictionary()) m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure())); @@ -43,10 +44,11 @@ namespace JSC { ~BatchedTransitionOptimizer() { - m_object->flattenDictionaryObject(); + m_object->flattenDictionaryObject(*m_globalData); } private: + JSGlobalData* m_globalData; JSObject* m_object; }; diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 0167e03..21ef5bb 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -31,17 +31,17 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor); BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, booleanPrototype->classInfo()->className)) { - putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); } // ECMA 15.6.2 JSObject* constructBoolean(ExecState* exec, const ArgList& args) { - BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); - obj->setInternalValue(jsBoolean(args.at(0).toBoolean(exec))); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -71,8 +71,8 @@ CallType BooleanConstructor::getCallData(CallData& callData) JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue) { - BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure()); - obj->setInternalValue(immediateBooleanValue); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + obj->setInternalValue(exec->globalData(), immediateBooleanValue); return obj; } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index c9b3846..71ff2d2 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.cpp +++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp @@ -27,8 +27,8 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject); const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 }; -BooleanObject::BooleanObject(NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +BooleanObject::BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(globalData, structure) { } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index 4b02acb..ff10ef6 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -27,7 +27,7 @@ namespace JSC { class BooleanObject : public JSWrapperObject { public: - explicit BooleanObject(NonNullPassRefPtr<Structure>); + explicit BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure>); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp index 7ffd095..54d621c 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -39,9 +39,9 @@ static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*); // ECMA 15.6.4 BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) - : BooleanObject(structure) + : BooleanObject(exec->globalData(), structure) { - setInternalValue(jsBoolean(false)); + setInternalValue(exec->globalData(), jsBoolean(false)); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum); diff --git a/Source/JavaScriptCore/runtime/CollectorHeapIterator.h b/Source/JavaScriptCore/runtime/CollectorHeapIterator.h deleted file mode 100644 index 7229d77..0000000 --- a/Source/JavaScriptCore/runtime/CollectorHeapIterator.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "Heap.h" - -#ifndef CollectorHeapIterator_h -#define CollectorHeapIterator_h - -namespace JSC { - - class CollectorHeapIterator { - public: - bool operator!=(const CollectorHeapIterator& other); - JSCell* operator*() const; - - protected: - CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell); - void advance(size_t max); - - CollectorHeap& m_heap; - size_t m_block; - size_t m_cell; - }; - - class LiveObjectIterator : public CollectorHeapIterator { - public: - LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); - LiveObjectIterator& operator++(); - }; - - class DeadObjectIterator : public CollectorHeapIterator { - public: - DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); - DeadObjectIterator& operator++(); - }; - - class ObjectIterator : public CollectorHeapIterator { - public: - ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); - ObjectIterator& operator++(); - }; - - inline CollectorHeapIterator::CollectorHeapIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) - : m_heap(heap) - , m_block(startBlock) - , m_cell(startCell) - { - } - - inline bool CollectorHeapIterator::operator!=(const CollectorHeapIterator& other) - { - return m_block != other.m_block || m_cell != other.m_cell; - } - - inline JSCell* CollectorHeapIterator::operator*() const - { - return reinterpret_cast<JSCell*>(&m_heap.collectorBlock(m_block)->cells[m_cell]); - } - - // Iterators advance up to the next-to-last -- and not the last -- cell in a - // block, since the last cell is a dummy sentinel. - inline void CollectorHeapIterator::advance(size_t max) - { - ++m_cell; - if (m_cell == max) { - m_cell = 0; - ++m_block; - } - } - - inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) - : CollectorHeapIterator(heap, startBlock, startCell - 1) - { - ++(*this); - } - - inline LiveObjectIterator& LiveObjectIterator::operator++() - { - advance(HeapConstants::cellsPerBlock - 1); - if (m_block < m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell < m_heap.nextCell)) - return *this; - - while (m_block < m_heap.usedBlocks && !m_heap.collectorBlock(m_block)->marked.get(m_cell)) - advance(HeapConstants::cellsPerBlock - 1); - return *this; - } - - inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) - : CollectorHeapIterator(heap, startBlock, startCell - 1) - { - ++(*this); - } - - inline DeadObjectIterator& DeadObjectIterator::operator++() - { - do { - advance(HeapConstants::cellsPerBlock - 1); - ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell)); - } while (m_block < m_heap.usedBlocks && m_heap.collectorBlock(m_block)->marked.get(m_cell)); - return *this; - } - - inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) - : CollectorHeapIterator(heap, startBlock, startCell - 1) - { - ++(*this); - } - - inline ObjectIterator& ObjectIterator::operator++() - { - advance(HeapConstants::cellsPerBlock - 1); - return *this; - } - -} // namespace JSC - -#endif // CollectorHeapIterator_h diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.cpp b/Source/JavaScriptCore/runtime/ConservativeSet.cpp new file mode 100644 index 0000000..bc8bd6d --- /dev/null +++ b/Source/JavaScriptCore/runtime/ConservativeSet.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ConservativeSet.h" + +namespace JSC { + +inline bool isPointerAligned(void* p) +{ + return !((intptr_t)(p) & (sizeof(char*) - 1)); +} + +void ConservativeSet::grow() +{ + size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; + DeprecatedPtr<JSCell>* newSet = static_cast<DeprecatedPtr<JSCell>*>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); + memcpy(newSet, m_set, m_size * sizeof(JSCell*)); + if (m_set != m_inlineSet) + OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(JSCell*)); + m_capacity = newCapacity; + m_set = newSet; +} + +void ConservativeSet::add(void* begin, void* end) +{ + ASSERT(begin <= end); + ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000); + ASSERT(isPointerAligned(begin)); + ASSERT(isPointerAligned(end)); + + for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) { + if (!m_heap->contains(*it)) + continue; + + if (m_size == m_capacity) + grow(); + + m_set[m_size++] = reinterpret_cast<JSCell*>(*it); + } +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.h b/Source/JavaScriptCore/runtime/ConservativeSet.h new file mode 100644 index 0000000..e7c2c4a --- /dev/null +++ b/Source/JavaScriptCore/runtime/ConservativeSet.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ConservativeSet_h +#define ConservativeSet_h + +#include "Heap.h" +#include "MarkStack.h" +#include <wtf/Vector.h> + +namespace JSC { + +class JSCell; + +class ConservativeSet { +public: + ConservativeSet(Heap*); + ~ConservativeSet(); + + void add(void* begin, void* end); + void mark(MarkStack&); + +private: + static const size_t inlineCapacity = 128; + static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*); + + void grow(); + + Heap* m_heap; + DeprecatedPtr<JSCell>* m_set; + size_t m_size; + size_t m_capacity; + DeprecatedPtr<JSCell> m_inlineSet[inlineCapacity]; +}; + +inline ConservativeSet::ConservativeSet(Heap* heap) + : m_heap(heap) + , m_set(m_inlineSet) + , m_size(0) + , m_capacity(inlineCapacity) +{ +} + +inline ConservativeSet::~ConservativeSet() +{ + if (m_set != m_inlineSet) + OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(DeprecatedPtr<JSCell>*)); +} + +inline void ConservativeSet::mark(MarkStack& markStack) +{ + for (size_t i = 0; i < m_size; ++i) + markStack.append(&m_set[i]); +} + +} // namespace JSC + +#endif // ConservativeSet_h diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index dcbe12d..f1f3956 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -61,13 +61,13 @@ static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*); DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className)) { - putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum); - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete); } // ECMA 15.9.3 diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp index 8562e2d..44e8b7d 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.cpp +++ b/Source/JavaScriptCore/runtime/DateInstance.cpp @@ -34,22 +34,22 @@ namespace JSC { const ClassInfo DateInstance::info = {"Date", 0, 0, 0}; -DateInstance::DateInstance(ExecState*, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(exec->globalData(), structure) { - setInternalValue(jsNaN()); + setInternalValue(exec->globalData(), jsNaN()); } -DateInstance::DateInstance(ExecState*, NonNullPassRefPtr<Structure> structure, double time) - : JSWrapperObject(structure) +DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time) + : JSWrapperObject(exec->globalData(), structure) { - setInternalValue(jsNumber(timeClip(time))); + setInternalValue(exec->globalData(), jsNumber(timeClip(time))); } DateInstance::DateInstance(ExecState* exec, double time) - : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure()) + : JSWrapperObject(exec->globalData(), exec->lexicalGlobalObject()->dateStructure()) { - setInternalValue(jsNumber(timeClip(time))); + setInternalValue(exec->globalData(), jsNumber(timeClip(time))); } const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 085cb33..5838b60 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -433,7 +433,7 @@ DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, NonN : DateInstance(exec, structure) { // The constructor will be added later, after DateConstructor has been built. - putAnonymousValue(0, globalObject); + putAnonymousValue(exec->globalData(), 0, globalObject); } bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -845,7 +845,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec) double milli = timeClip(exec->argument(0).toNumber(exec)); JSValue result = jsNumber(milli); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -860,7 +860,7 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, if (!exec->argumentCount() || isnan(milli)) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -877,12 +877,12 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, gregorianDateTime.copyFrom(*other); if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC)); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -895,7 +895,7 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, DateInstance* thisDateObj = asDateInstance(thisValue); if (!exec->argumentCount()) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -917,12 +917,12 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC)); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -1019,7 +1019,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) DateInstance* thisDateObj = asDateInstance(thisValue); if (!exec->argumentCount()) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } @@ -1041,13 +1041,13 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) double year = exec->argument(0).toIntegerPreserveNaN(exec); if (!isfinite(year)) { JSValue result = jsNaN(); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } gregorianDateTime.year = toInt32((year > 99 || year < 0) ? year - 1900 : year); JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false)); - thisDateObj->setInternalValue(result); + thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp index 227e9ec..b84f5ea 100644 --- a/Source/JavaScriptCore/runtime/Error.cpp +++ b/Source/JavaScriptCore/runtime/Error.cpp @@ -201,7 +201,7 @@ private: UString m_message; }; -COMPILE_ASSERT(sizeof(StrictModeTypeErrorFunction) <= sizeof(CollectorCell), sizeof_StrictModeTypeErrorFunction_must_be_less_than_CollectorCell); +ASSERT_CLASS_FITS_IN_CELL(StrictModeTypeErrorFunction); JSValue createTypeErrorFunction(ExecState* exec, const UString& message) { diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp index 4326a4d..2e53b95 100644 --- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -33,8 +33,8 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, errorPrototype->classInfo()->className)) { // ECMA 15.11.3.1 Error.prototype - putDirectWithoutTransition(exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly); - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); } // ECMA 15.9.3 diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp index 0f3153c..a6208d5 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp +++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp @@ -29,14 +29,14 @@ ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structu : JSObject(structure) , m_appendSourceToMessage(false) { - putDirect(globalData->propertyNames->message, jsString(globalData, "")); + putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, "")); } ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message) : JSObject(structure) , m_appendSourceToMessage(false) { - putDirect(globalData->propertyNames->message, jsString(globalData, message)); + putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message)); } ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message) diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp index d8fc829..b4e0a7c 100644 --- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -41,7 +41,7 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, No { // The constructor will be added later in ErrorConstructor's constructor - putDirectWithoutTransition(exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum); } diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index 45b4802..933b11f 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -40,10 +40,10 @@ ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor); FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className)) { - putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); // Number of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); } static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index cd7739d..e651538 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -41,7 +41,7 @@ static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*); FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) : InternalFunction(&exec->globalData(), globalObject, structure, exec->propertyNames().nullIdentifier) { - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum); } void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction) diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.h b/Source/JavaScriptCore/runtime/GCActivityCallback.h index 862b4df..9b6ef04 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallback.h +++ b/Source/JavaScriptCore/runtime/GCActivityCallback.h @@ -32,6 +32,10 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#if PLATFORM(CF) +#include <CoreFoundation/CoreFoundation.h> +#endif + namespace JSC { class Heap; @@ -58,6 +62,12 @@ public: void operator()(); void synchronize(); +#if PLATFORM(CF) +protected: + DefaultGCActivityCallback(Heap*, CFRunLoopRef); + void commonConstructor(Heap*, CFRunLoopRef); +#endif + private: OwnPtr<DefaultGCActivityCallbackPlatformData*> d; }; diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 414a0ad..211c423 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -35,7 +35,6 @@ #include "JSLock.h" #include <wtf/RetainPtr.h> #include <wtf/WTFThreadData.h> -#include <CoreFoundation/CoreFoundation.h> #if !PLATFORM(CF) #error "This file should only be used on CF platforms." @@ -54,22 +53,22 @@ struct DefaultGCActivityCallbackPlatformData { const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10; const CFTimeInterval triggerInterval = 2; // seconds -void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef, void *info) +void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info) { Heap* heap = static_cast<Heap*>(info); APIEntryShim shim(heap->globalData()); heap->collectAllGarbage(); + CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade); } DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) { - d = adoptPtr(new DefaultGCActivityCallbackPlatformData); + commonConstructor(heap, CFRunLoopGetCurrent()); +} - memset(&d->context, '\0', sizeof(CFRunLoopTimerContext)); - d->context.info = heap; - d->runLoop = CFRunLoopGetCurrent(); - d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context)); - CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); +DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop) +{ + commonConstructor(heap, runLoop); } DefaultGCActivityCallback::~DefaultGCActivityCallback() @@ -81,6 +80,17 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback() d->timer = 0; } +void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop) +{ + d = adoptPtr(new DefaultGCActivityCallbackPlatformData); + + memset(&d->context, 0, sizeof(CFRunLoopTimerContext)); + d->context.info = heap; + d->runLoop = runLoop; + d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context)); + CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); +} + void DefaultGCActivityCallback::operator()() { CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval); diff --git a/Source/JavaScriptCore/runtime/GetterSetter.cpp b/Source/JavaScriptCore/runtime/GetterSetter.cpp index 7e54053..2b9f444 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.cpp +++ b/Source/JavaScriptCore/runtime/GetterSetter.cpp @@ -33,9 +33,9 @@ void GetterSetter::markChildren(MarkStack& markStack) JSCell::markChildren(markStack); if (m_getter) - markStack.append(m_getter); + markStack.append(&m_getter); if (m_setter) - markStack.append(m_setter); + markStack.append(&m_setter); } bool GetterSetter::isGetterSetter() const diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h index e7b1938..ffab94d 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.h +++ b/Source/JavaScriptCore/runtime/GetterSetter.h @@ -38,17 +38,15 @@ namespace JSC { public: GetterSetter(ExecState* exec) : JSCell(exec->globalData().getterSetterStructure.get()) - , m_getter(0) - , m_setter(0) { } virtual void markChildren(MarkStack&); - JSObject* getter() const { return m_getter; } - void setGetter(JSObject* getter) { m_getter = getter; } - JSObject* setter() const { return m_setter; } - void setSetter(JSObject* setter) { m_setter = setter; } + JSObject* getter() const { return m_getter.get(); } + void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); } + JSObject* setter() const { return m_setter.get(); } + void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); } static PassRefPtr<Structure> createStructure(JSValue prototype) { return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount); @@ -56,8 +54,8 @@ namespace JSC { private: virtual bool isGetterSetter() const; - JSObject* m_getter; - JSObject* m_setter; + WriteBarrier<JSObject> m_getter; + WriteBarrier<JSObject> m_setter; }; GetterSetter* asGetterSetter(JSValue); diff --git a/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp index 3ad4644..27207e2 100644 --- a/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp +++ b/Source/JavaScriptCore/runtime/GlobalEvalFunction.cpp @@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction); GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) : PrototypeFunction(exec, globalObject, structure, len, name, function) - , m_cachedGlobalObject(cachedGlobalObject) + , m_cachedGlobalObject(exec->globalData(), this, cachedGlobalObject) { ASSERT_ARG(cachedGlobalObject, cachedGlobalObject); } @@ -42,7 +42,7 @@ GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, JSGlobalObject* globalOb void GlobalEvalFunction::markChildren(MarkStack& markStack) { PrototypeFunction::markChildren(markStack); - markStack.append(m_cachedGlobalObject); + markStack.append(&m_cachedGlobalObject); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/GlobalEvalFunction.h b/Source/JavaScriptCore/runtime/GlobalEvalFunction.h index b889ca9..13f0946 100644 --- a/Source/JavaScriptCore/runtime/GlobalEvalFunction.h +++ b/Source/JavaScriptCore/runtime/GlobalEvalFunction.h @@ -33,7 +33,7 @@ namespace JSC { class GlobalEvalFunction : public PrototypeFunction { public: GlobalEvalFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); - JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } + JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject.get(); } static PassRefPtr<Structure> createStructure(JSValue prototype) { @@ -46,7 +46,7 @@ namespace JSC { private: virtual void markChildren(MarkStack&); - JSGlobalObject* m_cachedGlobalObject; + WriteBarrier<JSGlobalObject> m_cachedGlobalObject; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp index 3966324..c05233c 100644 --- a/Source/JavaScriptCore/runtime/Heap.cpp +++ b/Source/JavaScriptCore/runtime/Heap.cpp @@ -21,7 +21,8 @@ #include "config.h" #include "Heap.h" -#include "CollectorHeapIterator.h" +#include "CodeBlock.h" +#include "ConservativeSet.h" #include "GCActivityCallback.h" #include "GCHandle.h" #include "Interpreter.h" @@ -30,14 +31,19 @@ #include "JSLock.h" #include "JSONObject.h" #include "Tracing.h" +#include <algorithm> #define COLLECT_ON_EVERY_ALLOCATION 0 +using namespace std; + namespace JSC { +const size_t minBytesPerCycle = 512 * 1024; + Heap::Heap(JSGlobalData* globalData) - : m_markedSpace(globalData) - , m_operationInProgress(NoOperation) + : m_operationInProgress(NoOperation) + , m_markedSpace(globalData) , m_markListSet(0) , m_activityCallback(DefaultGCActivityCallback::create(this)) , m_globalData(globalData) @@ -71,14 +77,12 @@ void Heap::destroy() delete m_markListSet; m_markListSet = 0; - ProtectCountSet protectedValuesCopy = m_protectedValues; - m_markedSpace.destroy(protectedValuesCopy); - ASSERT(!protectedObjectCount()); + m_markedSpace.destroy(); m_globalData = 0; } -void Heap::recordExtraCost(size_t cost) +void Heap::reportExtraMemoryCostSlowCase(size_t cost) { // Our frequency of garbage collection tries to balance memory use against speed // by collecting based on the number of newly created values. However, for values @@ -91,20 +95,8 @@ void Heap::recordExtraCost(size_t cost) // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. - if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.size() / 2) { - JAVASCRIPTCORE_GC_BEGIN(); - - markRoots(); - - JAVASCRIPTCORE_GC_MARKED(); - - m_markedSpace.reset(); - m_extraCost = 0; - - JAVASCRIPTCORE_GC_END(); - - (*m_activityCallback)(); - } + if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.capacity() / 2) + collectAllGarbage(); m_extraCost += cost; } @@ -113,7 +105,7 @@ void* Heap::allocate(size_t s) ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT_UNUSED(s, s <= HeapConstants::cellSize); + ASSERT_UNUSED(s, s <= MarkedBlock::CELL_SIZE); ASSERT(m_operationInProgress == NoOperation); #if COLLECT_ON_EVERY_ALLOCATION @@ -124,34 +116,18 @@ void* Heap::allocate(size_t s) m_operationInProgress = Allocation; void* result = m_markedSpace.allocate(s); m_operationInProgress = NoOperation; - if (!result) { - JAVASCRIPTCORE_GC_BEGIN(); - - markRoots(); - - JAVASCRIPTCORE_GC_MARKED(); - - m_markedSpace.reset(); - m_extraCost = 0; - - JAVASCRIPTCORE_GC_END(); - - (*m_activityCallback)(); + reset(DoNotSweep); m_operationInProgress = Allocation; result = m_markedSpace.allocate(s); m_operationInProgress = NoOperation; } + ASSERT(result); return result; } -void Heap::markConservatively(ConservativeSet& conservativeSet, void* start, void* end) -{ - m_markedSpace.markConservatively(conservativeSet, start, end); -} - void Heap::updateWeakGCHandles() { for (unsigned i = 0; i < m_weakGCHandlePools.size(); ++i) @@ -163,7 +139,7 @@ void WeakGCHandlePool::update() for (unsigned i = 1; i < WeakGCHandlePool::numPoolEntries; ++i) { if (m_entries[i].isValidPtr()) { JSCell* cell = m_entries[i].get(); - if (!cell || !Heap::isCellMarked(cell)) + if (!cell || !Heap::isMarked(cell)) m_entries[i].invalidate(); } } @@ -208,7 +184,7 @@ void Heap::markProtectedObjects(MarkStack& markStack) { ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - markStack.append(it->first); + markStack.deprecatedAppend(&it->first); } void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) @@ -233,11 +209,16 @@ void Heap::markTempSortVectors(MarkStack& markStack) Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) { if (vectorIt->first) - markStack.append(vectorIt->first); + markStack.deprecatedAppend(&vectorIt->first); } } } - + +inline RegisterFile& Heap::registerFile() +{ + return m_globalData->interpreter->registerFile(); +} + void Heap::markRoots() { #ifndef NDEBUG @@ -256,12 +237,11 @@ void Heap::markRoots() // We gather the conservative set before clearing mark bits, because // conservative gathering uses the mark bits from our last mark pass to // determine whether a reference is valid. - ConservativeSet conservativeSet; + ConservativeSet conservativeSet(this); m_machineStackMarker.markMachineStackConservatively(conservativeSet); - m_globalData->interpreter->registerFile().markCallFrames(conservativeSet, this); + conservativeSet.add(registerFile().start(), registerFile().end()); - // Reset mark bits. - m_markedSpace.clearMarkBits(); + m_markedSpace.clearMarks(); MarkStack& markStack = m_markStack; conservativeSet.mark(markStack); @@ -274,12 +254,17 @@ void Heap::markRoots() // Mark temporary vector for Array sorting markTempSortVectors(markStack); markStack.drain(); + + HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end(); + for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it) + (*it)->markAggregate(markStack); + markStack.drain(); // Mark misc. other roots. if (m_markListSet && m_markListSet->size()) MarkedArgumentBuffer::markLists(markStack, *m_markListSet); if (m_globalData->exception) - markStack.append(m_globalData->exception); + markStack.append(&m_globalData->exception); if (m_globalData->firstStringifierToMark) JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); markStack.drain(); @@ -301,39 +286,30 @@ size_t Heap::objectCount() const return m_markedSpace.objectCount(); } -MarkedSpace::Statistics Heap::statistics() const +size_t Heap::size() const { - return m_markedSpace.statistics(); + return m_markedSpace.size(); } -size_t Heap::size() const +size_t Heap::capacity() const { - return m_markedSpace.size(); + return m_markedSpace.capacity(); } size_t Heap::globalObjectCount() { - size_t count = 0; - if (JSGlobalObject* head = m_globalData->head) { - JSGlobalObject* o = head; - do { - ++count; - o = o->next(); - } while (o != head); - } - return count; + return m_globalData->globalObjects.uncheckedSize(); } size_t Heap::protectedGlobalObjectCount() { size_t count = 0; - if (JSGlobalObject* head = m_globalData->head) { - JSGlobalObject* o = head; - do { - if (m_protectedValues.contains(o)) - ++count; - o = o->next(); - } while (o != head); + + GlobalObjectMap& map = m_globalData->globalObjects; + GlobalObjectMap::iterator end = map.uncheckedEnd(); + for (GlobalObjectMap::iterator it = map.uncheckedBegin(); it != end; ++it) { + if (map.isValid(it) && m_protectedValues.contains(it->second.get())) + ++count; } return count; @@ -344,7 +320,23 @@ size_t Heap::protectedObjectCount() return m_protectedValues.size(); } -static const char* typeName(JSCell* cell) +class TypeCounter { +public: + TypeCounter(); + void operator()(JSCell*); + PassOwnPtr<TypeCountSet> take(); + +private: + const char* typeName(JSCell*); + OwnPtr<TypeCountSet> m_typeCountSet; +}; + +inline TypeCounter::TypeCounter() + : m_typeCountSet(new TypeCountSet) +{ +} + +inline const char* TypeCounter::typeName(JSCell* cell) { if (cell->isString()) return "string"; @@ -360,27 +352,32 @@ static const char* typeName(JSCell* cell) return info ? info->className : "Object"; } -HashCountedSet<const char*>* Heap::protectedObjectTypeCounts() +inline void TypeCounter::operator()(JSCell* cell) +{ + m_typeCountSet->add(typeName(cell)); +} + +inline PassOwnPtr<TypeCountSet> TypeCounter::take() +{ + return m_typeCountSet.release(); +} + +PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts() { - HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; + TypeCounter typeCounter; ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - counts->add(typeName(it->first)); + typeCounter(it->first); - return counts; + return typeCounter.take(); } -HashCountedSet<const char*>* Heap::objectTypeCounts() +PassOwnPtr<TypeCountSet> Heap::objectTypeCounts() { - HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; - - LiveObjectIterator it = primaryHeapBegin(); - LiveObjectIterator heapEnd = primaryHeapEnd(); - for ( ; it != heapEnd; ++it) - counts->add(typeName(*it)); - - return counts; + TypeCounter typeCounter; + forEach(typeCounter); + return typeCounter.take(); } bool Heap::isBusy() @@ -390,6 +387,11 @@ bool Heap::isBusy() void Heap::collectAllGarbage() { + reset(DoSweep); +} + +void Heap::reset(SweepToggle sweepToggle) +{ ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); JAVASCRIPTCORE_GC_BEGIN(); @@ -398,22 +400,19 @@ void Heap::collectAllGarbage() JAVASCRIPTCORE_GC_MARKED(); m_markedSpace.reset(); - m_markedSpace.sweep(); m_extraCost = 0; - JAVASCRIPTCORE_GC_END(); + if (sweepToggle == DoSweep) { + m_markedSpace.sweep(); + m_markedSpace.shrink(); + } - (*m_activityCallback)(); -} + size_t proportionalBytes = static_cast<size_t>(1.5 * m_markedSpace.size()); + m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle)); -LiveObjectIterator Heap::primaryHeapBegin() -{ - return m_markedSpace.primaryHeapBegin(); -} + JAVASCRIPTCORE_GC_END(); -LiveObjectIterator Heap::primaryHeapEnd() -{ - return m_markedSpace.primaryHeapEnd(); + (*m_activityCallback)(); } void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h index f7f4deb..6591a5b 100644 --- a/Source/JavaScriptCore/runtime/Heap.h +++ b/Source/JavaScriptCore/runtime/Heap.h @@ -27,89 +27,86 @@ #include <wtf/Forward.h> #include <wtf/HashSet.h> -#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell) - namespace JSC { - class JSValue; - class UString; class GCActivityCallback; + class GlobalCodeBlock; class JSCell; class JSGlobalData; class JSValue; + class JSValue; class LiveObjectIterator; - class MarkedArgumentBuffer; class MarkStack; + class MarkedArgumentBuffer; + class RegisterFile; + class UString; class WeakGCHandlePool; typedef std::pair<JSValue, UString> ValueStringPair; + typedef HashCountedSet<JSCell*> ProtectCountSet; + typedef HashCountedSet<const char*> TypeCountSet; enum OperationInProgress { NoOperation, Allocation, Collection }; class Heap { WTF_MAKE_NONCOPYABLE(Heap); public: - void destroy(); + static Heap* heap(JSValue); // 0 for immediate values + static Heap* heap(JSCell*); - void* allocate(size_t); + static bool isMarked(const JSCell*); + static bool testAndSetMarked(const JSCell*); + static void setMarked(JSCell*); + + Heap(JSGlobalData*); + ~Heap(); + void destroy(); // JSGlobalData must call destroy() before ~Heap(). - bool isBusy(); // true if an allocation or collection is in progress - void collectAllGarbage(); + JSGlobalData* globalData() const { return m_globalData; } + MarkedSpace& markedSpace() { return m_markedSpace; } + MachineStackMarker& machineStackMarker() { return m_machineStackMarker; } GCActivityCallback* activityCallback(); void setActivityCallback(PassOwnPtr<GCActivityCallback>); - static const size_t minExtraCost = 256; - static const size_t maxExtraCost = 1024 * 1024; + bool isBusy(); // true if an allocation or collection is in progress + void* allocate(size_t); + void collectAllGarbage(); void reportExtraMemoryCost(size_t cost); - size_t objectCount() const; - MarkedSpace::Statistics statistics() const; - size_t size() const; - void protect(JSValue); - // Returns true if the value is no longer protected by any protect pointers - // (though it may still be alive due to heap/stack references). - bool unprotect(JSValue); + bool unprotect(JSValue); // True when the protect count drops to 0. - static Heap* heap(JSValue); // 0 for immediate values - static Heap* heap(JSCell*); + bool contains(void*); + size_t size() const; + size_t capacity() const; + size_t objectCount() const; size_t globalObjectCount(); size_t protectedObjectCount(); size_t protectedGlobalObjectCount(); - HashCountedSet<const char*>* protectedObjectTypeCounts(); - HashCountedSet<const char*>* objectTypeCounts(); - - static bool isCellMarked(const JSCell*); - static bool checkMarkCell(const JSCell*); - static void markCell(JSCell*); + PassOwnPtr<TypeCountSet> protectedObjectTypeCounts(); + PassOwnPtr<TypeCountSet> objectTypeCounts(); WeakGCHandle* addWeakGCHandle(JSCell*); - void markConservatively(ConservativeSet&, void* start, void* end); - - void pushTempSortVector(WTF::Vector<ValueStringPair>*); - void popTempSortVector(WTF::Vector<ValueStringPair>*); + void pushTempSortVector(Vector<ValueStringPair>*); + void popTempSortVector(Vector<ValueStringPair>*); + + HashSet<GlobalCodeBlock*>& codeBlocks() { return m_codeBlocks; } HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } - - JSGlobalData* globalData() const { return m_globalData; } - LiveObjectIterator primaryHeapBegin(); - LiveObjectIterator primaryHeapEnd(); + template <typename Functor> void forEach(Functor&); - MachineStackMarker& machineStackMarker() { return m_machineStackMarker; } - - MarkedSpace& markedSpace() { return m_markedSpace; } - private: friend class JSGlobalData; - Heap(JSGlobalData*); - ~Heap(); - void recordExtraCost(size_t); + static const size_t minExtraCost = 256; + static const size_t maxExtraCost = 1024 * 1024; + + void reportExtraMemoryCostSlowCase(size_t); void markRoots(); void markProtectedObjects(MarkStack&); @@ -117,13 +114,19 @@ namespace JSC { void updateWeakGCHandles(); WeakGCHandlePool* weakGCHandlePool(size_t index); + + enum SweepToggle { DoNotSweep, DoSweep }; + void reset(SweepToggle); + + RegisterFile& registerFile(); - MarkedSpace m_markedSpace; OperationInProgress m_operationInProgress; + MarkedSpace m_markedSpace; ProtectCountSet m_protectedValues; - WTF::Vector<PageAllocationAligned> m_weakGCHandlePools; - WTF::Vector<WTF::Vector<ValueStringPair>* > m_tempSortingVectors; + Vector<PageAllocationAligned> m_weakGCHandlePools; + Vector<Vector<ValueStringPair>* > m_tempSortingVectors; + HashSet<GlobalCodeBlock*> m_codeBlocks; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -137,25 +140,30 @@ namespace JSC { size_t m_extraCost; }; - inline bool Heap::isCellMarked(const JSCell* cell) + inline bool Heap::isMarked(const JSCell* cell) { - return MarkedSpace::isCellMarked(cell); + return MarkedSpace::isMarked(cell); } - inline bool Heap::checkMarkCell(const JSCell* cell) + inline bool Heap::testAndSetMarked(const JSCell* cell) { - return MarkedSpace::checkMarkCell(cell); + return MarkedSpace::testAndSetMarked(cell); } - inline void Heap::markCell(JSCell* cell) + inline void Heap::setMarked(JSCell* cell) { - MarkedSpace::markCell(cell); + MarkedSpace::setMarked(cell); + } + + inline bool Heap::contains(void* p) + { + return m_markedSpace.contains(p); } inline void Heap::reportExtraMemoryCost(size_t cost) { if (cost > minExtraCost) - recordExtraCost(cost); + reportExtraMemoryCostSlowCase(cost); } inline WeakGCHandlePool* Heap::weakGCHandlePool(size_t index) @@ -163,6 +171,11 @@ namespace JSC { return static_cast<WeakGCHandlePool*>(m_weakGCHandlePools[index].base()); } + template <typename Functor> inline void Heap::forEach(Functor& functor) + { + m_markedSpace.forEach(functor); + } + } // namespace JSC #endif // Heap_h diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp index 0a8d9de..f19ae0d 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.cpp +++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp @@ -46,7 +46,7 @@ InternalFunction::InternalFunction(NonNullPassRefPtr<Structure> structure) InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const Identifier& name) : JSObjectWithGlobalObject(globalObject, structure) { - putDirect(globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); + putDirect(*globalData, globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); } const UString& InternalFunction::name(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h index 10ded4c..a113e91 100644 --- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -31,7 +31,7 @@ namespace JSC { class JSAPIValueWrapper : public JSCell { friend JSValue jsAPIValueWrapper(ExecState*, JSValue); public: - JSValue value() const { return m_value; } + JSValue value() const { return m_value.get(); } virtual bool isAPIValueWrapper() const { return true; } @@ -44,12 +44,12 @@ namespace JSC { private: JSAPIValueWrapper(ExecState* exec, JSValue value) : JSCell(exec->globalData().apiWrapperStructure.get()) - , m_value(value) { + m_value.set(exec->globalData(), this, value); ASSERT(!value.isCell()); } - JSValue m_value; + WriteBarrier<Unknown> m_value; }; inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value) diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index 428403d..6fb5ced 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -61,12 +61,12 @@ void JSActivation::markChildren(MarkStack& markStack) size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); size_t count = numParametersMinusThis; - markStack.appendValues(registerArray, count); + markStack.deprecatedAppendValues(registerArray, count); size_t numVars = d()->functionExecutable->capturedVariableCount(); // Skip the call frame, which sits between the parameters and vars. - markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); + markStack.deprecatedAppendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); } inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) @@ -132,8 +132,8 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert if (symbolTableGet(propertyName, slot)) return true; - if (JSValue* location = getDirectLocation(propertyName)) { - slot.setValueSlot(location); + if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) { + slot.setValue(location->get()); return true; } @@ -144,7 +144,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert return false; } -void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +void JSActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -155,7 +155,7 @@ void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value // properties are non-standard extensions that other implementations do not // expose in the activation object. ASSERT(!hasGetterSetterProperties()); - putDirect(propertyName, value, 0, true, slot); + putDirect(exec->globalData(), propertyName, value, 0, true, slot); } // FIXME: Make this function honor ReadOnly (const) and DontEnum diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 556603b..ded6d87 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -188,9 +188,9 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, #endif m_storage->m_length = initialLength; m_storage->m_numValuesInVector = 0; - JSValue* vector = m_storage->m_vector; + WriteBarrier<Unknown>* vector = m_storage->m_vector; for (size_t i = 0; i < initialCapacity; ++i) - vector[i] = JSValue(); + vector[i].clear(); } checkConsistency(); @@ -198,7 +198,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity)); } -JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list) +JSArray::JSArray(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, const ArgList& list) : JSObject(structure) { unsigned initialCapacity = list.size(); @@ -225,12 +225,12 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list) #endif size_t i = 0; - JSValue* vector = m_storage->m_vector; + WriteBarrier<Unknown>* vector = m_storage->m_vector; ArgList::const_iterator end = list.end(); for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i) - vector[i] = *it; + vector[i].set(globalData, this, *it); for (; i < initialStorage; i++) - vector[i] = JSValue(); + vector[i].clear(); checkConsistency(); @@ -257,16 +257,16 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot } if (i < m_vectorLength) { - JSValue& valueSlot = storage->m_vector[i]; - if (valueSlot) { - slot.setValueSlot(&valueSlot); + JSValue value = storage->m_vector[i].get(); + if (value) { + slot.setValue(value); return true; } } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { if (i >= MIN_SPARSE_ARRAY_INDEX) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->end()) { - slot.setValueSlot(&it->second); + slot.setValue(it->second.get()); return true; } } @@ -305,16 +305,16 @@ bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& proper if (i >= storage->m_length) return false; if (i < m_vectorLength) { - JSValue& value = storage->m_vector[i]; + WriteBarrier<Unknown>& value = storage->m_vector[i]; if (value) { - descriptor.setDescriptor(value, 0); + descriptor.setDescriptor(value.get(), 0); return true; } } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { if (i >= MIN_SPARSE_ARRAY_INDEX) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->end()) { - descriptor.setDescriptor(it->second, 0); + descriptor.setDescriptor(it->second.get(), 0); return true; } } @@ -359,13 +359,13 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value) } if (i < m_vectorLength) { - JSValue& valueSlot = storage->m_vector[i]; + WriteBarrier<Unknown>& valueSlot = storage->m_vector[i]; if (valueSlot) { - valueSlot = value; + valueSlot.set(exec->globalData(), this, value); checkConsistency(); return; } - valueSlot = value; + valueSlot.set(exec->globalData(), this, value); ++storage->m_numValuesInVector; checkConsistency(); return; @@ -395,11 +395,11 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu storage->m_sparseValueMap = map; } - pair<SparseArrayValueMap::iterator, bool> result = map->add(i, value); - if (!result.second) { // pre-existing entry - result.first->second = value; + WriteBarrier<Unknown> temp; + pair<SparseArrayValueMap::iterator, bool> result = map->add(i, temp); + result.first->second.set(exec->globalData(), this, value); + if (!result.second) // pre-existing entry return; - } size_t capacity = map->capacity(); if (capacity != storage->reportedMapCapacity) { @@ -415,7 +415,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu if (!map || map->isEmpty()) { if (increaseVectorLength(i + 1)) { storage = m_storage; - storage->m_vector[i] = value; + storage->m_vector[i].set(exec->globalData(), this, value); ++storage->m_numValuesInVector; checkConsistency(); } else @@ -457,18 +457,19 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu storage = m_storage; unsigned vectorLength = m_vectorLength; - JSValue* vector = storage->m_vector; + WriteBarrier<Unknown>* vector = storage->m_vector; if (newNumValuesInVector == storage->m_numValuesInVector + 1) { for (unsigned j = vectorLength; j < newVectorLength; ++j) - vector[j] = JSValue(); + vector[j].clear(); if (i > MIN_SPARSE_ARRAY_INDEX) map->remove(i); } else { for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j) - vector[j] = JSValue(); + vector[j].clear(); + JSGlobalData& globalData = exec->globalData(); for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j) - vector[j] = map->take(j); + vector[j].set(globalData, this, map->take(j).get()); } ASSERT(i < newVectorLength); @@ -476,7 +477,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu m_vectorLength = newVectorLength; storage->m_numValuesInVector = newNumValuesInVector; - storage->m_vector[i] = value; + storage->m_vector[i].set(exec->globalData(), this, value); checkConsistency(); @@ -503,12 +504,12 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i) ArrayStorage* storage = m_storage; if (i < m_vectorLength) { - JSValue& valueSlot = storage->m_vector[i]; + WriteBarrier<Unknown>& valueSlot = storage->m_vector[i]; if (!valueSlot) { checkConsistency(); return false; } - valueSlot = JSValue(); + valueSlot.clear(); --storage->m_numValuesInVector; checkConsistency(); return true; @@ -605,9 +606,9 @@ bool JSArray::increaseVectorLength(unsigned newLength) storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue)); m_storage->m_allocBase = baseStorage; - JSValue* vector = storage->m_vector; + WriteBarrier<Unknown>* vector = storage->m_vector; for (unsigned i = vectorLength; i < newVectorLength; ++i) - vector[i] = JSValue(); + vector[i].clear(); m_vectorLength = newVectorLength; @@ -666,9 +667,9 @@ void JSArray::setLength(unsigned newLength) if (newLength < length) { unsigned usedVectorLength = min(length, m_vectorLength); for (unsigned i = newLength; i < usedVectorLength; ++i) { - JSValue& valueSlot = storage->m_vector[i]; + WriteBarrier<Unknown>& valueSlot = storage->m_vector[i]; bool hadValue = valueSlot; - valueSlot = JSValue(); + valueSlot.clear(); storage->m_numValuesInVector -= hadValue; } @@ -706,11 +707,11 @@ JSValue JSArray::pop() JSValue result; if (length < m_vectorLength) { - JSValue& valueSlot = storage->m_vector[length]; + WriteBarrier<Unknown>& valueSlot = storage->m_vector[length]; if (valueSlot) { --storage->m_numValuesInVector; - result = valueSlot; - valueSlot = JSValue(); + result = valueSlot.get(); + valueSlot.clear(); } else result = jsUndefined(); } else { @@ -718,7 +719,7 @@ JSValue JSArray::pop() if (SparseArrayValueMap* map = storage->m_sparseValueMap) { SparseArrayValueMap::iterator it = map->find(length); if (it != map->end()) { - result = it->second; + result = it->second.get(); map->remove(it); if (map->isEmpty()) { delete map; @@ -742,7 +743,7 @@ void JSArray::push(ExecState* exec, JSValue value) ArrayStorage* storage = m_storage; if (storage->m_length < m_vectorLength) { - storage->m_vector[storage->m_length] = value; + storage->m_vector[storage->m_length].set(exec->globalData(), this, value); ++storage->m_numValuesInVector; ++storage->m_length; checkConsistency(); @@ -754,7 +755,7 @@ void JSArray::push(ExecState* exec, JSValue value) if (!map || map->isEmpty()) { if (increaseVectorLength(storage->m_length + 1)) { storage = m_storage; - storage->m_vector[storage->m_length] = value; + storage->m_vector[storage->m_length].set(exec->globalData(), this, value); ++storage->m_numValuesInVector; ++storage->m_length; checkConsistency(); @@ -857,9 +858,9 @@ void JSArray::unshiftCount(ExecState* exec, int count) return; } - JSValue* vector = m_storage->m_vector; + WriteBarrier<Unknown>* vector = m_storage->m_vector; for (int i = 0; i < count; i++) - vector[i] = JSValue(); + vector[i].clear(); } void JSArray::markChildren(MarkStack& markStack) @@ -941,7 +942,7 @@ void JSArray::sort(ExecState* exec) Heap::heap(this)->pushTempSortVector(&values); for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { - JSValue value = storage->m_vector[i]; + JSValue value = storage->m_vector[i].get(); ASSERT(!value.isUndefined()); values[i].first = value; } @@ -974,9 +975,10 @@ void JSArray::sort(ExecState* exec) increaseVectorLength(lengthNotIncludingUndefined); if (storage->m_length < lengthNotIncludingUndefined) storage->m_length = lengthNotIncludingUndefined; - + + JSGlobalData& globalData = exec->globalData(); for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - storage->m_vector[i] = values[i].first; + storage->m_vector[i].set(globalData, this, values[i].first); Heap::heap(this)->popTempSortVector(&values); @@ -1105,14 +1107,14 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. for (; numDefined < usedVectorLength; ++numDefined) { - JSValue v = storage->m_vector[numDefined]; + JSValue v = storage->m_vector[numDefined].get(); if (!v || v.isUndefined()) break; tree.abstractor().m_nodes[numDefined].value = v; tree.insert(numDefined); } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - JSValue v = storage->m_vector[i]; + JSValue v = storage->m_vector[i].get(); if (v) { if (v.isUndefined()) ++numUndefined; @@ -1140,7 +1142,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, SparseArrayValueMap::iterator end = map->end(); for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) { - tree.abstractor().m_nodes[numDefined].value = it->second; + tree.abstractor().m_nodes[numDefined].value = it->second.get(); tree.insert(numDefined); ++numDefined; } @@ -1157,18 +1159,19 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, // Copy the values back into m_storage. AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter; iter.start_iter_least(tree); + JSGlobalData& globalData = exec->globalData(); for (unsigned i = 0; i < numDefined; ++i) { - storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value; + storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); ++iter; } // Put undefined values back in. for (unsigned i = numDefined; i < newUsedVectorLength; ++i) - storage->m_vector[i] = jsUndefined(); + storage->m_vector[i].setUndefined(); // Ensure that unused values in the vector are zeroed out. for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) - storage->m_vector[i] = JSValue(); + storage->m_vector[i].clear(); storage->m_numValuesInVector = newUsedVectorLength; @@ -1179,14 +1182,14 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) { ArrayStorage* storage = m_storage; - JSValue* vector = storage->m_vector; + WriteBarrier<Unknown>* vector = storage->m_vector; unsigned vectorEnd = min(storage->m_length, m_vectorLength); unsigned i = 0; for (; i < vectorEnd; ++i) { - JSValue& v = vector[i]; + WriteBarrier<Unknown>& v = vector[i]; if (!v) break; - args.append(v); + args.append(v.get()); } for (; i < storage->m_length; ++i) @@ -1197,14 +1200,14 @@ void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSiz { ASSERT(m_storage->m_length >= maxSize); UNUSED_PARAM(maxSize); - JSValue* vector = m_storage->m_vector; + WriteBarrier<Unknown>* vector = m_storage->m_vector; unsigned vectorEnd = min(maxSize, m_vectorLength); unsigned i = 0; for (; i < vectorEnd; ++i) { - JSValue& v = vector[i]; + WriteBarrier<Unknown>& v = vector[i]; if (!v) break; - buffer[i] = v; + buffer[i] = v.get(); } for (; i < maxSize; ++i) @@ -1223,17 +1226,18 @@ unsigned JSArray::compactForSorting() unsigned numUndefined = 0; for (; numDefined < usedVectorLength; ++numDefined) { - JSValue v = storage->m_vector[numDefined]; + JSValue v = storage->m_vector[numDefined].get(); if (!v || v.isUndefined()) break; } + for (unsigned i = numDefined; i < usedVectorLength; ++i) { - JSValue v = storage->m_vector[i]; + JSValue v = storage->m_vector[i].get(); if (v) { if (v.isUndefined()) ++numUndefined; else - storage->m_vector[numDefined++] = v; + storage->m_vector[numDefined++].setWithoutWriteBarrier(v); } } @@ -1252,16 +1256,16 @@ unsigned JSArray::compactForSorting() SparseArrayValueMap::iterator end = map->end(); for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) - storage->m_vector[numDefined++] = it->second; + storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.get()); delete map; storage->m_sparseValueMap = 0; } for (unsigned i = numDefined; i < newUsedVectorLength; ++i) - storage->m_vector[i] = jsUndefined(); + storage->m_vector[i].setUndefined(); for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) - storage->m_vector[i] = JSValue(); + storage->m_vector[i].clear(); storage->m_numValuesInVector = newUsedVectorLength; diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index de28b65..b5caa47 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -27,7 +27,7 @@ namespace JSC { - typedef HashMap<unsigned, JSValue> SparseArrayValueMap; + typedef HashMap<unsigned, WriteBarrier<Unknown> > SparseArrayValueMap; // This struct holds the actual data values of an array. A JSArray object points to it's contained ArrayStorage // struct by pointing to m_vector. To access the contained ArrayStorage struct, use the getStorage() and @@ -44,7 +44,7 @@ namespace JSC { #if CHECK_ARRAY_CONSISTENCY bool m_inCompactInitialization; #endif - JSValue m_vector[1]; + WriteBarrier<Unknown> m_vector[1]; }; // The CreateCompact creation mode is used for fast construction of arrays @@ -67,7 +67,7 @@ namespace JSC { explicit JSArray(NonNullPassRefPtr<Structure>); JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength, ArrayCreationMode); - JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues); + JSArray(JSGlobalData&, NonNullPassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -94,32 +94,32 @@ namespace JSC { JSValue getIndex(unsigned i) { ASSERT(canGetIndex(i)); - return m_storage->m_vector[i]; + return m_storage->m_vector[i].get(); } bool canSetIndex(unsigned i) { return i < m_vectorLength; } - void setIndex(unsigned i, JSValue v) + void setIndex(JSGlobalData& globalData, unsigned i, JSValue v) { ASSERT(canSetIndex(i)); - JSValue& x = m_storage->m_vector[i]; + WriteBarrier<Unknown>& x = m_storage->m_vector[i]; if (!x) { ArrayStorage *storage = m_storage; ++storage->m_numValuesInVector; if (i >= storage->m_length) storage->m_length = i + 1; } - x = v; + x.set(globalData, this, v); } - void uncheckedSetIndex(unsigned i, JSValue v) + void uncheckedSetIndex(JSGlobalData& globalData, unsigned i, JSValue v) { ASSERT(canSetIndex(i)); ArrayStorage *storage = m_storage; #if CHECK_ARRAY_CONSISTENCY ASSERT(storage->m_inCompactInitialization); #endif - storage->m_vector[i] = v; + storage->m_vector[i].set(globalData, this, v); } void fillArgList(ExecState*, MarkedArgumentBuffer&); @@ -194,13 +194,13 @@ namespace JSC { if (SparseArrayValueMap* map = storage->m_sparseValueMap) { SparseArrayValueMap::iterator end = map->end(); for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) - markStack.append(it->second); + markStack.append(&it->second); } } inline void MarkStack::markChildren(JSCell* cell) { - ASSERT(Heap::isCellMarked(cell)); + ASSERT(Heap::isMarked(cell)); if (!cell->structure()->typeInfo().overridesMarkChildren()) { #ifdef NDEBUG asObject(cell)->markChildrenDirect(*this); @@ -240,7 +240,7 @@ namespace JSC { current.m_values++; JSCell* cell; - if (!value || !value.isCell() || Heap::checkMarkCell(cell = value.asCell())) { + if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) { if (current.m_values == end) { m_markSets.removeLast(); continue; diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp index 6af9d75..3f7d806 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp @@ -40,7 +40,7 @@ JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure , m_storage(storage) , m_classInfo(classInfo) { - putDirect(exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete); + putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete); } #if !ASSERT_DISABLED diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 95f4efa..66f6197 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -64,6 +64,7 @@ namespace JSC { friend class JSZombie; friend class JSGlobalData; friend class MarkedSpace; + friend class MarkedBlock; private: explicit JSCell(Structure*); @@ -336,22 +337,50 @@ namespace JSC { { return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); } + + template <typename T> void MarkStack::append(DeprecatedPtr<T>* slot) + { + internalAppend(slot->get()); + } + + template <typename T> void MarkStack::append(WriteBarrierBase<T>* slot) + { + internalAppend(slot->get()); + } - ALWAYS_INLINE void MarkStack::append(JSCell* cell) + ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) { ASSERT(!m_isCheckingForDefaultMarkViolation); ASSERT(cell); - if (Heap::checkMarkCell(cell)) + if (Heap::testAndSetMarked(cell)) return; if (cell->structure()->typeInfo().type() >= CompoundType) m_values.append(cell); } - ALWAYS_INLINE void MarkStack::append(JSValue value) + ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::deprecatedAppend(JSValue* value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::deprecatedAppend(Register* value) + { + ASSERT(value); + internalAppend(value->jsValue()); + } + + ALWAYS_INLINE void MarkStack::internalAppend(JSValue value) { ASSERT(value); if (value.isCell()) - append(value.asCell()); + internalAppend(value.asCell()); } inline Heap* Heap::heap(JSValue v) @@ -363,7 +392,7 @@ namespace JSC { inline Heap* Heap::heap(JSCell* c) { - return MarkedSpace::cellBlock(c)->heap; + return MarkedSpace::heap(c); } #if ENABLE(JSC_ZOMBIES) @@ -372,6 +401,23 @@ namespace JSC { return isCell() && asCell() && asCell()->isZombie(); } #endif + + inline void* MarkedBlock::allocate(size_t& nextCell) + { + do { + ASSERT(nextCell < CELLS_PER_BLOCK); + if (!marked.testAndSet(nextCell)) { // Always false for the last cell in the block + JSCell* cell = reinterpret_cast<JSCell*>(&cells[nextCell++]); + cell->~JSCell(); + return cell; + } + nextCell = marked.nextPossiblyUnset(nextCell); + } while (nextCell != CELLS_PER_BLOCK); + + nextCell = 0; + return 0; + } + } // namespace JSC #endif // JSCell_h diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 99f8e6f..c569722 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -71,8 +71,8 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas , m_executable(thunk) , m_scopeChain(globalObject->globalScopeChain()) { - putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); - putDirect(exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } #endif @@ -83,9 +83,9 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas #endif , m_scopeChain(globalObject->globalScopeChain()) { - putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); #if ENABLE(JIT) - putDirect(exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); #else UNUSED_PARAM(length); UNUSED_PARAM(func); @@ -99,7 +99,7 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex , m_scopeChain(scopeChainNode) { const Identifier& name = static_cast<FunctionExecutable*>(m_executable.get())->name(); - putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); } JSFunction::~JSFunction() @@ -203,16 +203,16 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); if (propertyName == exec->propertyNames().prototype) { - JSValue* location = getDirectLocation(propertyName); + WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName); if (!location) { JSObject* prototype = new (exec) JSObject(scope().globalObject()->emptyObjectStructure()); - prototype->putDirect(exec->propertyNames().constructor, this, DontEnum); - putDirect(exec->propertyNames().prototype, prototype, DontDelete | DontEnum); + prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, this, DontEnum); + putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum); location = getDirectLocation(propertyName); } - slot.setValueSlot(this, location, offsetForLocation(location)); + slot.setValue(this, location->get(), offsetForLocation(location)); } if (propertyName == exec->propertyNames().arguments) { diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index 3928c82..ff88048 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -31,7 +31,6 @@ #include "ArgList.h" #include "Heap.h" -#include "CollectorHeapIterator.h" #include "CommonIdentifiers.h" #include "FunctionConstructor.h" #include "GetterSetter.h" @@ -87,25 +86,26 @@ void* JSGlobalData::jsFunctionVPtr; void JSGlobalData::storeVPtrs() { - CollectorCell cell; - void* storage = &cell; + // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction. + // COMPILE_ASSERTS below check that this is true. + char storage[64]; - COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell); + COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage); JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack); JSGlobalData::jsArrayVPtr = jsArray->vptr(); jsArray->~JSCell(); - COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell); + COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage); JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr(); jsByteArray->~JSCell(); - COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell); + COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage); JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); JSGlobalData::jsStringVPtr = jsString->vptr(); jsString->~JSCell(); - COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell); + COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage); JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); jsFunction->~JSCell(); @@ -140,7 +140,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , parser(new Parser) , interpreter(new Interpreter) , heap(this) - , head(0) , dynamicGlobalObject(0) , firstStringifierToMark(0) , cachedUTCOffset(NaN) @@ -166,11 +165,14 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread if (canUseJIT) { m_canUseJIT = kCFBooleanTrue == canUseJIT; CFRelease(canUseJIT); - } else - m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); + } else { + char* canUseJITString = getenv("JavaScriptCoreUseJIT"); + m_canUseJIT = !canUseJITString || atoi(canUseJITString); + } CFRelease(canUseJITKey); #elif OS(UNIX) - m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); + char* canUseJITString = getenv("JavaScriptCoreUseJIT"); + m_canUseJIT = !canUseJITString || atoi(canUseJITString); #else m_canUseJIT = true; #endif @@ -311,21 +313,30 @@ void JSGlobalData::dumpSampleData(ExecState* exec) interpreter->dumpSampleData(exec); } +class Recompiler { +public: + void operator()(JSCell*); +}; + +inline void Recompiler::operator()(JSCell* cell) +{ + if (!cell->inherits(&JSFunction::info)) + return; + JSFunction* function = asFunction(cell); + if (function->executable()->isHostFunction()) + return; + function->jsExecutable()->discardCode(); +} + + void JSGlobalData::recompileAllJSFunctions() { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. ASSERT(!dynamicGlobalObject); - - LiveObjectIterator it = heap.primaryHeapBegin(); - LiveObjectIterator heapEnd = heap.primaryHeapEnd(); - for ( ; it != heapEnd; ++it) { - if ((*it)->inherits(&JSFunction::info)) { - JSFunction* function = asFunction(*it); - if (!function->executable()->isHostFunction()) - function->jsExecutable()->discardCode(); - } - } + + Recompiler recompiler; + heap.forEach(recompiler); } #if ENABLE(REGEXP_TRACING) diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 31f41e9..7b69055 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -39,6 +39,7 @@ #include "SmallStrings.h" #include "Terminator.h" #include "TimeoutChecker.h" +#include "WeakGCMap.h" #include "WeakRandom.h" #include <wtf/BumpPointerAllocator.h> #include <wtf/Forward.h> @@ -72,7 +73,9 @@ namespace JSC { #endif struct HashTable; - struct Instruction; + struct Instruction; + + typedef WeakGCMap<JSGlobalObject*, JSGlobalObject> GlobalObjectMap; // FIXME: Would be nice to use a WeakGCSet here. struct DSTOffsetCache { DSTOffsetCache() @@ -203,14 +206,14 @@ namespace JSC { Terminator terminator; Heap heap; - JSValue exception; + DeprecatedPtr<Unknown> exception; #if ENABLE(JIT) ReturnAddressPtr exceptionLocation; #endif HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData; - JSGlobalObject* head; + GlobalObjectMap globalObjects; JSGlobalObject* dynamicGlobalObject; HashSet<JSObject*> stringRecursionCheckVisitedObjects; diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 9b67dbb..f303196 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -80,16 +80,16 @@ static const int initialTickCountThreshold = 255; // Preferred number of milliseconds between each timeout check static const int preferredScriptCheckTimeInterval = 1000; -static inline void markIfNeeded(MarkStack& markStack, JSValue v) +template <typename T> static inline void markIfNeeded(MarkStack& markStack, WriteBarrier<T>* v) { - if (v) + if (*v) markStack.append(v); } static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s) { - if (s) - markIfNeeded(markStack, s->storedPrototype()); + if (s && s->storedPrototype()) + markStack.append(s->storedPrototypeSlot()); } JSGlobalObject::~JSGlobalObject() @@ -104,18 +104,8 @@ JSGlobalObject::~JSGlobalObject() (*profiler)->stopProfiling(globalExec(), UString()); } - d()->next->d()->prev = d()->prev; - d()->prev->d()->next = d()->next; - JSGlobalObject*& headObject = head(); - if (headObject == this) - headObject = d()->next; - if (headObject == this) - headObject = 0; - - HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); - for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) - (*it)->clearGlobalObject(); - + d()->globalData->globalObjects.take(this); + RegisterFile& registerFile = globalData().interpreter->registerFile(); if (registerFile.clearGlobalObject(this)) registerFile.setNumGlobals(0); @@ -125,22 +115,15 @@ JSGlobalObject::~JSGlobalObject() void JSGlobalObject::init(JSObject* thisValue) { ASSERT(JSLock::currentThreadIsHoldingLock()); - + structure()->disableSpecificFunctionTracking(); d()->globalData = Heap::heap(this)->globalData(); + d()->globalData->globalObjects.set(this, this); d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue); JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0); - if (JSGlobalObject*& headObject = head()) { - d()->prev = headObject; - d()->next = headObject->d()->next; - headObject->d()->next->d()->prev = this; - headObject->d()->next = this; - } else - headObject = d()->next = d()->prev = this; - d()->debugger = 0; d()->profileGroup = 0; @@ -202,117 +185,117 @@ void JSGlobalObject::reset(JSValue prototype) // Prototypes - d()->functionPrototype = new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created. - d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype); - d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype); + d()->functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull()))); // The real prototype will be set once ObjectPrototype is created. + d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype.get()); + d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype.get()); NativeFunctionWrapper* callFunction = 0; NativeFunctionWrapper* applyFunction = 0; d()->functionPrototype->addFunctionProperties(exec, this, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction); - d()->callFunction = callFunction; - d()->applyFunction = applyFunction; - d()->objectPrototype = new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get()); - d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype); + d()->callFunction.set(exec->globalData(), this, callFunction); + d()->applyFunction.set(exec->globalData(), this, applyFunction); + d()->objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get())); + d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype.get()); d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); - d()->functionStructure = JSFunction::createStructure(d()->functionPrototype); - d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype); - d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype); - d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype); - d()->callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(d()->objectPrototype); + d()->functionStructure = JSFunction::createStructure(d()->functionPrototype.get()); + d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype.get()); + d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype.get()); + d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype.get()); + d()->callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(d()->objectPrototype.get()); - d()->arrayPrototype = new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(d()->objectPrototype)); - d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype); - d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype); + d()->arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(d()->objectPrototype.get()))); + d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype.get()); + d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype.get()); - d()->stringPrototype = new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype)); - d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype); + d()->stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype.get()))); + d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype.get()); - d()->booleanPrototype = new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype); + d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get())); + d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype.get()); - d()->numberPrototype = new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype); + d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get())); + d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype.get()); - d()->datePrototype = new (exec) DatePrototype(exec, this, DatePrototype::createStructure(d()->objectPrototype)); - d()->dateStructure = DateInstance::createStructure(d()->datePrototype); + d()->datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(d()->objectPrototype.get()))); + d()->dateStructure = DateInstance::createStructure(d()->datePrototype.get()); - d()->regExpPrototype = new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); - d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype); + d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get())); + d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype.get()); - d()->methodCallDummy = constructEmptyObject(exec); + d()->methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); - ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get()); + ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->prototypeFunctionStructure.get()); d()->errorStructure = ErrorInstance::createStructure(errorPrototype); // Constructors - JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get()); - JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype); - JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get()); - JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); - JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype); - JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype); - JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); + JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.get(), d()->prototypeFunctionStructure.get()); + JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(d()->functionPrototype.get()), d()->functionPrototype.get()); + JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype.get()), d()->arrayPrototype.get(), d()->prototypeFunctionStructure.get()); + JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype.get()), d()->prototypeFunctionStructure.get(), d()->stringPrototype.get()); + JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(d()->functionPrototype.get()), d()->booleanPrototype.get()); + JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(d()->functionPrototype.get()), d()->numberPrototype.get()); + JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype.get()), d()->prototypeFunctionStructure.get(), d()->datePrototype.get()); - d()->regExpConstructor = new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype); + d()->regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype.get()), d()->regExpPrototype.get())); - d()->errorConstructor = new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(d()->functionPrototype), errorPrototype); + d()->errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(d()->functionPrototype.get()), errorPrototype)); RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype); - RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype); - d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError"); - d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError"); - d()->referenceErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError"); - d()->syntaxErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError"); - d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError"); - d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError"); - - d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum); - d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum); - d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum); - d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum); - d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum); - d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum); - d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum); - d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum); - errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum); + RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype.get()); + d()->evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); + d()->rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); + d()->referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); + d()->syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); + d()->typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); + d()->URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); + + d()->objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); + d()->functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); + d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); + d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); + d()->stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); + d()->numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); + d()->datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); + d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->regExpConstructor.get(), DontEnum); + errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->errorConstructor.get(), DontEnum); // Set global constructors // FIXME: These properties could be handled by a static hash table. - putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor, DontEnum); - putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), d()->regExpConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), d()->errorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), d()->evalErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), d()->rangeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), d()->typeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), d()->URIErrorConstructor.get(), DontEnum); // Set global values. GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete) + GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); // Set global functions. - d()->evalFunction = new (exec) GlobalEvalFunction(exec, this, GlobalEvalFunction::createStructure(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this); - putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum); + d()->evalFunction.set(exec->globalData(), this, new (exec) GlobalEvalFunction(exec, this, GlobalEvalFunction::createStructure(d()->functionPrototype.get()), 1, exec->propertyNames().eval, globalFuncEval, this)); + putDirectFunctionWithoutTransition(exec, d()->evalFunction.get(), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, this, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); @@ -336,7 +319,7 @@ void JSGlobalObject::resetPrototype(JSValue prototype) setPrototype(prototype); JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); - JSObject* objectPrototype = d()->objectPrototype; + JSObject* objectPrototype = d()->objectPrototype.get(); if (oldLastInPrototypeChain != objectPrototype) oldLastInPrototypeChain->setPrototype(objectPrototype); } @@ -345,33 +328,29 @@ void JSGlobalObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); - for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) - (*it)->markAggregate(markStack); - - markIfNeeded(markStack, d()->regExpConstructor); - markIfNeeded(markStack, d()->errorConstructor); - markIfNeeded(markStack, d()->evalErrorConstructor); - markIfNeeded(markStack, d()->rangeErrorConstructor); - markIfNeeded(markStack, d()->referenceErrorConstructor); - markIfNeeded(markStack, d()->syntaxErrorConstructor); - markIfNeeded(markStack, d()->typeErrorConstructor); - markIfNeeded(markStack, d()->URIErrorConstructor); - - markIfNeeded(markStack, d()->evalFunction); - markIfNeeded(markStack, d()->callFunction); - markIfNeeded(markStack, d()->applyFunction); - - markIfNeeded(markStack, d()->objectPrototype); - markIfNeeded(markStack, d()->functionPrototype); - markIfNeeded(markStack, d()->arrayPrototype); - markIfNeeded(markStack, d()->booleanPrototype); - markIfNeeded(markStack, d()->stringPrototype); - markIfNeeded(markStack, d()->numberPrototype); - markIfNeeded(markStack, d()->datePrototype); - markIfNeeded(markStack, d()->regExpPrototype); - - markIfNeeded(markStack, d()->methodCallDummy); + markIfNeeded(markStack, &d()->regExpConstructor); + markIfNeeded(markStack, &d()->errorConstructor); + markIfNeeded(markStack, &d()->evalErrorConstructor); + markIfNeeded(markStack, &d()->rangeErrorConstructor); + markIfNeeded(markStack, &d()->referenceErrorConstructor); + markIfNeeded(markStack, &d()->syntaxErrorConstructor); + markIfNeeded(markStack, &d()->typeErrorConstructor); + markIfNeeded(markStack, &d()->URIErrorConstructor); + + markIfNeeded(markStack, &d()->evalFunction); + markIfNeeded(markStack, &d()->callFunction); + markIfNeeded(markStack, &d()->applyFunction); + + markIfNeeded(markStack, &d()->objectPrototype); + markIfNeeded(markStack, &d()->functionPrototype); + markIfNeeded(markStack, &d()->arrayPrototype); + markIfNeeded(markStack, &d()->booleanPrototype); + markIfNeeded(markStack, &d()->stringPrototype); + markIfNeeded(markStack, &d()->numberPrototype); + markIfNeeded(markStack, &d()->datePrototype); + markIfNeeded(markStack, &d()->regExpPrototype); + + markIfNeeded(markStack, &d()->methodCallDummy); markIfNeeded(markStack, d()->errorStructure); markIfNeeded(markStack, d()->argumentsStructure); @@ -396,12 +375,12 @@ void JSGlobalObject::markChildren(MarkStack& markStack) if (d()->registerArray) { // Outside the execution of global code, when our variables are torn off, // we can mark the torn-off array. - markStack.appendValues(d()->registerArray.get(), d()->registerArraySize); + markStack.deprecatedAppendValues(d()->registerArray.get(), d()->registerArraySize); } else if (d()->registers) { // During execution of global code, when our variables are in the register file, // the symbol table tells us how many variables there are, and registers // points to where they end, and the registers used for execution begin. - markStack.appendValues(d()->registers - symbolTable().size(), symbolTable().size()); + markStack.deprecatedAppendValues(d()->registers - symbolTable().size(), symbolTable().size()); } } @@ -425,9 +404,10 @@ void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) d()->registers = 0; return; } - - Register* registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals); - setRegisters(registerArray + numGlobals, registerArray, numGlobals); + + OwnArrayPtr<Register> registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals); + Register* registers = registerArray.get() + numGlobals; + setRegisters(registers, registerArray.release(), numGlobals); } void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 24bc2f8..d13d2da 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -73,26 +73,6 @@ namespace JSC { , destructor(destructor) , registerArraySize(0) , globalScopeChain(NoScopeChain()) - , regExpConstructor(0) - , errorConstructor(0) - , evalErrorConstructor(0) - , rangeErrorConstructor(0) - , referenceErrorConstructor(0) - , syntaxErrorConstructor(0) - , typeErrorConstructor(0) - , URIErrorConstructor(0) - , evalFunction(0) - , callFunction(0) - , applyFunction(0) - , objectPrototype(0) - , functionPrototype(0) - , arrayPrototype(0) - , booleanPrototype(0) - , stringPrototype(0) - , numberPrototype(0) - , datePrototype(0) - , regExpPrototype(0) - , methodCallDummy(0) , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { } @@ -109,29 +89,29 @@ namespace JSC { ScopeChain globalScopeChain; Register globalCallFrame[RegisterFile::CallFrameHeaderSize]; - RegExpConstructor* regExpConstructor; - ErrorConstructor* errorConstructor; - NativeErrorConstructor* evalErrorConstructor; - NativeErrorConstructor* rangeErrorConstructor; - NativeErrorConstructor* referenceErrorConstructor; - NativeErrorConstructor* syntaxErrorConstructor; - NativeErrorConstructor* typeErrorConstructor; - NativeErrorConstructor* URIErrorConstructor; - - GlobalEvalFunction* evalFunction; - NativeFunctionWrapper* callFunction; - NativeFunctionWrapper* applyFunction; - - ObjectPrototype* objectPrototype; - FunctionPrototype* functionPrototype; - ArrayPrototype* arrayPrototype; - BooleanPrototype* booleanPrototype; - StringPrototype* stringPrototype; - NumberPrototype* numberPrototype; - DatePrototype* datePrototype; - RegExpPrototype* regExpPrototype; - - JSObject* methodCallDummy; + WriteBarrier<RegExpConstructor> regExpConstructor; + WriteBarrier<ErrorConstructor> errorConstructor; + WriteBarrier<NativeErrorConstructor> evalErrorConstructor; + WriteBarrier<NativeErrorConstructor> rangeErrorConstructor; + WriteBarrier<NativeErrorConstructor> referenceErrorConstructor; + WriteBarrier<NativeErrorConstructor> syntaxErrorConstructor; + WriteBarrier<NativeErrorConstructor> typeErrorConstructor; + WriteBarrier<NativeErrorConstructor> URIErrorConstructor; + + WriteBarrier<GlobalEvalFunction> evalFunction; + WriteBarrier<NativeFunctionWrapper> callFunction; + WriteBarrier<NativeFunctionWrapper> applyFunction; + + WriteBarrier<ObjectPrototype> objectPrototype; + WriteBarrier<FunctionPrototype> functionPrototype; + WriteBarrier<ArrayPrototype> arrayPrototype; + WriteBarrier<BooleanPrototype> booleanPrototype; + WriteBarrier<StringPrototype> stringPrototype; + WriteBarrier<NumberPrototype> numberPrototype; + WriteBarrier<DatePrototype> datePrototype; + WriteBarrier<RegExpPrototype> regExpPrototype; + + WriteBarrier<JSObject> methodCallDummy; RefPtr<Structure> argumentsStructure; RefPtr<Structure> arrayStructure; @@ -155,7 +135,6 @@ namespace JSC { RefPtr<JSGlobalData> globalData; - HashSet<GlobalCodeBlock*> codeBlocks; WeakMapSet weakMaps; WeakRandom weakRandom; }; @@ -167,7 +146,7 @@ namespace JSC { : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData)) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); - putAnonymousValue(0, this); + putThisToAnonymousValue(0); init(this); } @@ -175,7 +154,7 @@ namespace JSC { : JSVariableObject(structure, new JSGlobalObjectData(destroyJSGlobalObjectData)) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); - putAnonymousValue(0, this); + putThisToAnonymousValue(0); init(this); } @@ -184,7 +163,7 @@ namespace JSC { : JSVariableObject(structure, data) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); - putAnonymousValue(0, this); + putThisToAnonymousValue(0); init(thisValue); } @@ -202,35 +181,31 @@ namespace JSC { virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); - // Linked list of all global objects that use the same JSGlobalData. - JSGlobalObject*& head() { return d()->globalData->head; } - JSGlobalObject* next() { return d()->next; } - // The following accessors return pristine values, even if a script // replaces the global object's associated property. - RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; } + RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor.get(); } - ErrorConstructor* errorConstructor() const { return d()->errorConstructor; } - NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; } - NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; } - NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; } - NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; } - NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; } - NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; } + ErrorConstructor* errorConstructor() const { return d()->errorConstructor.get(); } + NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor.get(); } + NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor.get(); } + NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor.get(); } + NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor.get(); } + NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor.get(); } + NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor.get(); } - GlobalEvalFunction* evalFunction() const { return d()->evalFunction; } + GlobalEvalFunction* evalFunction() const { return d()->evalFunction.get(); } - ObjectPrototype* objectPrototype() const { return d()->objectPrototype; } - FunctionPrototype* functionPrototype() const { return d()->functionPrototype; } - ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; } - BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; } - StringPrototype* stringPrototype() const { return d()->stringPrototype; } - NumberPrototype* numberPrototype() const { return d()->numberPrototype; } - DatePrototype* datePrototype() const { return d()->datePrototype; } - RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; } + ObjectPrototype* objectPrototype() const { return d()->objectPrototype.get(); } + FunctionPrototype* functionPrototype() const { return d()->functionPrototype.get(); } + ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype.get(); } + BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype.get(); } + StringPrototype* stringPrototype() const { return d()->stringPrototype.get(); } + NumberPrototype* numberPrototype() const { return d()->numberPrototype.get(); } + DatePrototype* datePrototype() const { return d()->datePrototype.get(); } + RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype.get(); } - JSObject* methodCallDummy() const { return d()->methodCallDummy; } + JSObject* methodCallDummy() const { return d()->methodCallDummy.get(); } Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } Structure* arrayStructure() const { return d()->arrayStructure.get(); } @@ -270,8 +245,6 @@ namespace JSC { virtual bool isDynamicScope(bool& requiresDynamicChecks) const; - HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; } - void copyGlobalsFrom(RegisterFile&); void copyGlobalsTo(RegisterFile&); @@ -322,7 +295,7 @@ namespace JSC { void init(JSObject* thisValue); void reset(JSValue prototype); - void setRegisters(Register* registers, Register* registerArray, size_t count); + void setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray, size_t count); void* operator new(size_t); // can only be allocated with JSGlobalData }; @@ -335,7 +308,7 @@ namespace JSC { return static_cast<JSGlobalObject*>(asObject(value)); } - inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count) + inline void JSGlobalObject::setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray, size_t count) { JSVariableObject::setRegisters(registers, registerArray); d()->registerArraySize = count; @@ -385,7 +358,7 @@ namespace JSC { inline JSValue Structure::prototypeForLookup(ExecState* exec) const { if (typeInfo().type() == ObjectType) - return m_prototype; + return m_prototype.get(); ASSERT(typeInfo().type() == StringType); return exec->lexicalGlobalObject()->stringPrototype(); @@ -457,12 +430,12 @@ namespace JSC { { MarkedArgumentBuffer values; values.append(singleItemValue); - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); + return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), values); } inline JSArray* constructArray(ExecState* exec, const ArgList& values) { - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); + return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), values); } class DynamicGlobalObjectScope { diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index df4be52..0f7a576 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -84,12 +84,13 @@ private: public: Holder(JSObject*); - JSObject* object() const { return m_object; } + JSObject* object() const { return m_object.get(); } + DeprecatedPtr<JSObject>* objectSlot() { return &m_object; } bool appendNextProperty(Stringifier&, UStringBuilder&); private: - JSObject* const m_object; + DeprecatedPtr<JSObject> m_object; const bool m_isArray; bool m_isJSArray; unsigned m_index; @@ -258,7 +259,7 @@ void Stringifier::markAggregate(MarkStack& markStack) for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) { size_t size = m_holderStack.size(); for (size_t i = 0; i < size; ++i) - markStack.append(m_holderStack[i].object()); + markStack.append(m_holderStack[i].objectSlot()); } } @@ -269,7 +270,7 @@ JSValue Stringifier::stringify(JSValue value) return jsNull(); PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier); - object->putDirect(m_exec->globalData().propertyNames->emptyIdentifier, value); + object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value); UStringBuilder result; if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded) @@ -284,9 +285,6 @@ void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& val { int length = value.length(); - // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters. - builder.reserveCapacity(builder.length() + length + 2 + 8); - builder.append('"'); const UChar* data = value.characters(); @@ -502,7 +500,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu // First time through, initialize. if (!m_index) { if (m_isArray) { - m_isJSArray = isJSArray(&exec->globalData(), m_object); + m_isJSArray = isJSArray(&exec->globalData(), m_object.get()); m_size = m_object->get(exec, exec->globalData().propertyNames->length).toUInt32(exec); builder.append('['); } else { @@ -535,10 +533,10 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu if (m_isArray) { // Get the value. JSValue value; - if (m_isJSArray && asArray(m_object)->canGetIndex(index)) - value = asArray(m_object)->getIndex(index); + if (m_isJSArray && asArray(m_object.get())->canGetIndex(index)) + value = asArray(m_object.get())->getIndex(index); else { - PropertySlot slot(m_object); + PropertySlot slot(m_object.get()); if (!m_object->getOwnPropertySlot(exec, index, slot)) slot.setUndefined(); if (exec->hadException()) @@ -552,10 +550,10 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu stringifier.startNewLine(builder); // Append the stringified value. - stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, index); + stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), index); } else { // Get the value. - PropertySlot slot(m_object); + PropertySlot slot(m_object.get()); Identifier& propertyName = m_propertyNames->propertyNameVector()[index]; if (!m_object->getOwnPropertySlot(exec, propertyName, slot)) return true; @@ -577,7 +575,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBu builder.append(' '); // Append the stringified value. - stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, propertyName); + stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), propertyName); } // From this point on, no access to the this pointer or to any members, because the @@ -644,13 +642,13 @@ private: { JSValue args[] = { property, unfiltered }; ArgList argList(args, 2); - return call(m_exec, m_function, m_callType, m_callData, thisObj, argList); + return call(m_exec, m_function.get(), m_callType, m_callData, thisObj, argList); } friend class Holder; ExecState* m_exec; - JSObject* m_function; + DeprecatedPtr<JSObject> m_function; CallType m_callType; CallData m_callData; }; @@ -729,7 +727,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) array->deleteProperty(m_exec, indexStack.last()); else { if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last())) - array->setIndex(indexStack.last(), filteredValue); + array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue); else array->put(m_exec, indexStack.last(), filteredValue); } diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 6ecc73f..277ffff 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -312,7 +312,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO JSValue object = getDirect(propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); - asGetterSetter(object)->setGetter(getterFunction); + asGetterSetter(object)->setGetter(exec->globalData(), getterFunction); return; } @@ -331,7 +331,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO } m_structure->setHasGetterSetterProperties(true); - getterSetter->setGetter(getterFunction); + getterSetter->setGetter(exec->globalData(), getterFunction); } void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes) @@ -339,7 +339,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO JSValue object = getDirect(propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); - asGetterSetter(object)->setSetter(setterFunction); + asGetterSetter(object)->setSetter(exec->globalData(), setterFunction); return; } @@ -358,7 +358,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO } m_structure->setHasGetterSetterProperties(true); - getterSetter->setSetter(setterFunction); + getterSetter->setSetter(exec->globalData(), setterFunction); } JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName) @@ -512,39 +512,39 @@ void JSObject::removeDirect(const Identifier& propertyName) if (m_structure->isUncacheableDictionary()) { offset = m_structure->removePropertyWithoutTransition(propertyName); if (offset != WTF::notFound) - putDirectOffset(offset, jsUndefined()); + putUndefinedAtDirectOffset(offset); return; } RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset); setStructure(structure.release()); if (offset != WTF::notFound) - putDirectOffset(offset, jsUndefined()); + putUndefinedAtDirectOffset(offset); } void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirectFunction(Identifier(exec, function->name(exec)), function, attr); + putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr); } void JSObject::putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr) { - putDirectFunction(Identifier(exec, function->name(exec)), function, attr); + putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr); } void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr); } void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr) { - putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr); } -NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location) +NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarrierBase<Unknown>* location) { - if (JSObject* getterFunction = asGetterSetter(*location)->getter()) { + if (JSObject* getterFunction = asGetterSetter(location->get())->getter()) { if (!structure()->isDictionary()) slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location)); else @@ -595,11 +595,11 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p GetterSetter* accessor = new (exec) GetterSetter(exec); if (oldDescriptor.getter()) { attributes |= Getter; - accessor->setGetter(asObject(oldDescriptor.getter())); + accessor->setGetter(exec->globalData(), asObject(oldDescriptor.getter())); } if (oldDescriptor.setter()) { attributes |= Setter; - accessor->setSetter(asObject(oldDescriptor.setter())); + accessor->setSetter(exec->globalData(), asObject(oldDescriptor.setter())); } target->putWithAttributes(exec, propertyName, accessor, attributes); return true; @@ -720,9 +720,9 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName GetterSetter* getterSetter = asGetterSetter(accessor); if (current.attributesEqual(descriptor)) { if (descriptor.setter()) - getterSetter->setSetter(asObject(descriptor.setter())); + getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter())); if (descriptor.getter()) - getterSetter->setGetter(asObject(descriptor.getter())); + getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter())); return true; } deleteProperty(exec, propertyName); @@ -731,7 +731,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName attrs |= Setter; if (descriptor.getter()) attrs |= Getter; - putDirect(propertyName, getterSetter, attrs); + putDirect(exec->globalData(), propertyName, getterSetter, attrs); return true; } diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 803abfd..b79249c 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -70,8 +70,8 @@ namespace JSC { Setter = 1 << 6 // property is a setter }; - typedef EncodedJSValue* PropertyStorage; - typedef const EncodedJSValue* ConstPropertyStorage; + typedef WriteBarrierBase<Unknown>* PropertyStorage; + typedef const WriteBarrierBase<Unknown>* ConstPropertyStorage; class JSObject : public JSCell { friend class BatchedTransitionOptimizer; @@ -155,22 +155,22 @@ namespace JSC { return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); } - JSValue* getDirectLocation(const Identifier& propertyName) + WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName) { size_t offset = m_structure->get(propertyName); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes) + WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName, unsigned& attributes) { JSCell* specificFunction; size_t offset = m_structure->get(propertyName, attributes, specificFunction); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - size_t offsetForLocation(JSValue* location) const + size_t offsetForLocation(WriteBarrierBase<Unknown>* location) const { - return location - reinterpret_cast<const JSValue*>(propertyStorage()); + return location - propertyStorage(); } void transitionTo(Structure*); @@ -179,25 +179,26 @@ namespace JSC { bool hasCustomProperties() { return !m_structure->isEmpty(); } bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } - bool putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); - void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0); - bool putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); + bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); + bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); - void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0); - void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr = 0); + void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr, bool checkReadOnly, PutPropertySlot&); void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0); void putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr = 0); - void putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0); - void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attr = 0); + void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); + void putDirectFunctionWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSCell* value, unsigned attr = 0); void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0); void putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr = 0); // Fast access to known property offsets. - JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); } - void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); } + JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); } + void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); } + void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); } - void fillGetterPropertySlot(PropertySlot&, JSValue* location); + void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); @@ -225,25 +226,35 @@ namespace JSC { return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } - void flattenDictionaryObject() + void flattenDictionaryObject(JSGlobalData& globalData) { - m_structure->flattenDictionaryStructure(this); + m_structure->flattenDictionaryStructure(globalData, this); } - void putAnonymousValue(unsigned index, JSValue value) + void putAnonymousValue(JSGlobalData& globalData, unsigned index, JSValue value) { ASSERT(index < m_structure->anonymousSlotCount()); - *locationForOffset(index) = value; + locationForOffset(index)->set(globalData, this, value); + } + void clearAnonymousValue(unsigned index) + { + ASSERT(index < m_structure->anonymousSlotCount()); + locationForOffset(index)->clear(); } JSValue getAnonymousValue(unsigned index) const { ASSERT(index < m_structure->anonymousSlotCount()); - return *locationForOffset(index); + return locationForOffset(index)->get(); } protected: static const unsigned StructureFlags = 0; + void putThisToAnonymousValue(unsigned index) + { + locationForOffset(index)->setWithoutWriteBarrier(this); + } + private: // Nobody should ever ask any of these questions on something already known to be a JSObject. using JSCell::isAPIValueWrapper; @@ -253,22 +264,22 @@ namespace JSC { void getString(ExecState* exec); void isObject(); void isString(); - + ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } - const JSValue* locationForOffset(size_t offset) const + const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const { - return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]); + return &propertyStorage()[offset]; } - JSValue* locationForOffset(size_t offset) + WriteBarrierBase<Unknown>* locationForOffset(size_t offset) { - return reinterpret_cast<JSValue*>(&propertyStorage()[offset]); + return &propertyStorage()[offset]; } - bool putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*); - bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&, JSCell*); + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&); void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0); bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -278,7 +289,7 @@ namespace JSC { union { PropertyStorage m_externalStorage; - EncodedJSValue m_inlineStorage[inlineStorageCapacity]; + WriteBarrierBase<Unknown> m_inlineStorage[inlineStorageCapacity]; }; RefPtr<Structure> m_inheritorID; @@ -372,11 +383,11 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (JSValue* location = getDirectLocation(propertyName)) { - if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter()) + if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) { + if (m_structure->hasGetterSetterProperties() && location->isGetterSetter()) fillGetterPropertySlot(slot, location); else - slot.setValueSlot(this, location, offsetForLocation(location)); + slot.setValue(this, location->get(), offsetForLocation(location)); return true; } @@ -450,7 +461,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); @@ -467,7 +478,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (checkReadOnly && currentAttributes & ReadOnly) return false; - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); // At this point, the objects structure only has a specific value set if previously there // had been one set, and if the new value being specified is the same (otherwise we would // have despecified, above). So, if currentSpecificFunction is not set, or if the new @@ -485,7 +496,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); ASSERT(offset < m_structure->propertyStorageCapacity()); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); // See comment on setNewProperty call below. if (!specificFunction) slot.setNewProperty(this, offset); @@ -500,7 +511,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. if (!specificFunction) @@ -527,7 +538,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (currentSpecificFunction) { // case (1) Do the put, then return leaving the slot uncachable. if (specificFunction == currentSpecificFunction) { - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); return true; } // case (2) Despecify, fall through to (3). @@ -536,7 +547,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); return true; } @@ -557,7 +568,7 @@ inline bool JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. if (!specificFunction) @@ -570,61 +581,61 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); + return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value)); } inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { PutPropertySlot slot; - putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); + putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); } -inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); - return putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0); + return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, 0); } -inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { PutPropertySlot slot; - putDirectInternal(propertyName, value, attributes, false, slot, 0); + putDirectInternal(globalData, propertyName, value, attributes, false, slot, 0); } -inline bool JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - return putDirectInternal(propertyName, value, 0, false, slot, 0); + return putDirectInternal(globalData, propertyName, value, 0, false, slot, 0); } -inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { - putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value); + putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, value); } -inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr) +inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attr) { PutPropertySlot slot; - putDirectInternal(propertyName, value, attr, false, slot, value); + putDirectInternal(globalData, propertyName, value, attr, false, slot, value); } -inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attributes) +inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { size_t currentCapacity = m_structure->propertyStorageCapacity(); size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); } -inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes) +inline void JSObject::putDirectFunctionWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes) { size_t currentCapacity = m_structure->propertyStorageCapacity(); size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); - putDirectOffset(offset, value); + putDirectOffset(globalData, offset, value); } inline void JSObject::transitionTo(Structure* newStructure) @@ -703,7 +714,7 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(isCell() && isObject()); - if (!asObject(asCell())->putDirect(propertyName, value, slot) && slot.isStrictMode()) + if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode()) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); } @@ -725,7 +736,7 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_ bool wasInline = (oldSize == JSObject::inlineStorageCapacity); PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage); - PropertyStorage newPropertyStorage = new EncodedJSValue[newSize]; + PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize]; for (unsigned i = 0; i < oldSize; ++i) newPropertyStorage[i] = oldPropertyStorage[i]; @@ -740,11 +751,10 @@ ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) { JSCell::markChildren(markStack); - markStack.append(prototype()); - + markStack.append(m_structure->storedPrototypeSlot()); PropertyStorage storage = propertyStorage(); size_t storageSize = m_structure->propertyStorageSize(); - markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize); + markStack.appendValues(storage, storageSize); } // --- JSValue inlines ---------------------------- diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp index e9d6c96..c16acb1 100644 --- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp @@ -35,7 +35,10 @@ JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, { COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one); ASSERT(!globalObject || globalObject->isGlobalObject()); - putAnonymousValue(GlobalObjectSlot, globalObject); + if (!globalObject) + clearAnonymousValue(GlobalObjectSlot); + else + putAnonymousValue(globalObject->globalData(), GlobalObjectSlot, globalObject); } JSGlobalObject* JSObjectWithGlobalObject::globalObject() const diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index a5d4da0..6fd28e3 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -40,11 +40,11 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyN , m_cachedStructure(0) , m_numCacheableSlots(numCacheableSlots) , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) - , m_jsStrings(new JSValue[m_jsStringsSize]) + , m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize])) { PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector(); for (size_t i = 0; i < m_jsStringsSize; ++i) - m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring()); + m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].ustring())); } JSPropertyNameIterator::~JSPropertyNameIterator() @@ -91,7 +91,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) { - JSValue& identifier = m_jsStrings[i]; + JSValue identifier = m_jsStrings[i].get(); if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec)) return identifier; diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h index 01700ac..cd46243 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -85,7 +85,7 @@ namespace JSC { RefPtr<StructureChain> m_cachedPrototypeChain; uint32_t m_numCacheableSlots; uint32_t m_jsStringsSize; - OwnArrayPtr<JSValue> m_jsStrings; + OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings; }; inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 7ab1d1c..80b048e 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject); void JSStaticScopeObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - markStack.append(d()->registerStore.jsValue()); + markStack.deprecatedAppend(&d()->registerStore); } JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index ba28139..848c431 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -255,7 +255,7 @@ UString JSString::toString(ExecState* exec) const inline StringObject* StringObject::create(ExecState* exec, JSString* string) { - return new (exec) StringObject(exec->lexicalGlobalObject()->stringObjectStructure(), string); + return new (exec) StringObject(exec->globalData(), exec->lexicalGlobalObject()->stringObjectStructure(), string); } JSObject* JSString::toObject(ExecState* exec) const diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index cad9662..b2e7a51 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -47,6 +47,9 @@ namespace JSC { struct ClassInfo; struct Instruction; + template <class T> class DeprecatedPtr; + template <class T> class WriteBarrierBase; + enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; #if USE(JSVALUE32_64) @@ -212,6 +215,9 @@ namespace JSC { #endif private: + template <class T> JSValue(DeprecatedPtr<T>); + template <class T> JSValue(WriteBarrierBase<T>); + enum HashTableDeletedValueTag { HashTableDeletedValue }; JSValue(HashTableDeletedValueTag); diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 3f2e218..96a0ec4 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -89,8 +89,8 @@ namespace JSC { { } - Register* copyRegisterArray(Register* src, size_t count); - void setRegisters(Register* r, Register* registerArray); + PassOwnArrayPtr<Register> copyRegisterArray(Register* src, size_t count); + void setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray); bool symbolTableGet(const Identifier&, PropertySlot&); bool symbolTableGet(const Identifier&, PropertyDescriptor&); @@ -149,18 +149,18 @@ namespace JSC { return true; } - inline Register* JSVariableObject::copyRegisterArray(Register* src, size_t count) + inline PassOwnArrayPtr<Register> JSVariableObject::copyRegisterArray(Register* src, size_t count) { - Register* registerArray = new Register[count]; - memcpy(registerArray, src, count * sizeof(Register)); + OwnArrayPtr<Register> registerArray = adoptArrayPtr(new Register[count]); + memcpy(registerArray.get(), src, count * sizeof(Register)); - return registerArray; + return registerArray.release(); } - inline void JSVariableObject::setRegisters(Register* registers, Register* registerArray) + inline void JSVariableObject::setRegisters(Register* registers, PassOwnArrayPtr<Register> registerArray) { - ASSERT(registerArray != d->registerArray.get()); - d->registerArray.set(registerArray); + ASSERT(registerArray != d->registerArray); + d->registerArray = registerArray; d->registers = registers; } diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp index 2c39f5c..6c73b2f 100644 --- a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp +++ b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp @@ -30,7 +30,7 @@ void JSWrapperObject::markChildren(MarkStack& markStack) { JSObject::markChildren(markStack); if (m_internalValue) - markStack.append(m_internalValue); + markStack.append(&m_internalValue); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h index f19cd30..0b0d3fd 100644 --- a/Source/JavaScriptCore/runtime/JSWrapperObject.h +++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h @@ -30,11 +30,11 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSObject { protected: - explicit JSWrapperObject(NonNullPassRefPtr<Structure>); + explicit JSWrapperObject(JSGlobalData&, NonNullPassRefPtr<Structure>); public: - JSValue internalValue() const { return m_internalValue; } - void setInternalValue(JSValue); + JSValue internalValue() const { return m_internalValue.get(); } + void setInternalValue(JSGlobalData&, JSValue); static PassRefPtr<Structure> createStructure(JSValue prototype) { @@ -47,21 +47,21 @@ namespace JSC { private: virtual void markChildren(MarkStack&); - JSValue m_internalValue; + WriteBarrier<Unknown> m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure) + inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) : JSObject(structure) { - putAnonymousValue(0, jsNull()); + putAnonymousValue(globalData, 0, jsNull()); } - inline void JSWrapperObject::setInternalValue(JSValue value) + inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value) { ASSERT(value); ASSERT(!value.isObject()); - m_internalValue = value; - putAnonymousValue(0, value); + m_internalValue.set(globalData, this, value); + putAnonymousValue(globalData, 0, value); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp index df87e7f..bc2e736 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.cpp +++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp @@ -373,7 +373,7 @@ JSValue LiteralParser::parse(ParserState initialState) } case DoParseObjectEndExpression: { - asObject(objectStack.last())->putDirect(identifierStack.last(), lastValue); + asObject(objectStack.last())->putDirect(m_exec->globalData(), identifierStack.last(), lastValue); identifierStack.removeLast(); if (m_lexer.currentToken().type == TokComma) goto doParseObjectStartExpression; diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp index dac1c94..3c7d4be 100644 --- a/Source/JavaScriptCore/runtime/Lookup.cpp +++ b/Source/JavaScriptCore/runtime/Lookup.cpp @@ -74,7 +74,7 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* ASSERT(thisObj->structure()->anonymousSlotCount() > 0); ASSERT(thisObj->getAnonymousValue(0).isCell() && asObject(thisObj->getAnonymousValue(0).asCell())->isGlobalObject()); ASSERT(entry->attributes() & Function); - JSValue* location = thisObj->getDirectLocation(propertyName); + WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(propertyName); if (!location) { NativeFunctionWrapper* function; @@ -86,11 +86,11 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* #endif function = new (exec) NativeFunctionWrapper(exec, globalObject, globalObject->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); - thisObj->putDirectFunction(propertyName, function, entry->attributes()); + thisObj->putDirectFunction(exec->globalData(), propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(propertyName); } - slot.setValueSlot(thisObj, location, thisObj->offsetForLocation(location)); + slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location)); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h index 0d6d98f..43184e5 100644 --- a/Source/JavaScriptCore/runtime/Lookup.h +++ b/Source/JavaScriptCore/runtime/Lookup.h @@ -312,9 +312,9 @@ namespace JSC { if (entry->attributes() & Function) { // function: put as override property if (LIKELY(value.isCell())) - thisObj->putDirectFunction(propertyName, value.asCell()); + thisObj->putDirectFunction(exec->globalData(), propertyName, value.asCell()); else - thisObj->putDirect(propertyName, value); + thisObj->putDirect(exec->globalData(), propertyName, value); } else if (!(entry->attributes() & ReadOnly)) entry->propertyPutter()(exec, thisObj, value); diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp index e52f402..4430947 100644 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "MachineStackMarker.h" +#include "ConservativeSet.h" #include "Heap.h" #include "JSArray.h" #include "JSGlobalData.h" @@ -73,6 +74,18 @@ namespace JSC { +static inline void swapIfBackwards(void*& begin, void*& end) +{ +#if OS(WINCE) + if (begin <= end) + return; + std::swap(begin, end); +#else +UNUSED_PARAM(begin); +UNUSED_PARAM(end); +#endif +} + #if ENABLE(JSC_MULTIPLE_THREADS) #if OS(DARWIN) @@ -196,7 +209,10 @@ void MachineStackMarker::unregisterThread() void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(ConservativeSet& conservativeSet) { - m_heap->markConservatively(conservativeSet, m_heap->globalData()->stack().current(), m_heap->globalData()->stack().origin()); + void* begin = m_heap->globalData()->stack().current(); + void* end = m_heap->globalData()->stack().origin(); + swapIfBackwards(begin, end); + conservativeSet.add(begin, end); } #if COMPILER(GCC) @@ -358,10 +374,12 @@ void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conserva size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); // mark the thread's registers - m_heap->markConservatively(conservativeSet, static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + conservativeSet.add(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); void* stackPointer = otherThreadStackPointer(regs); - m_heap->markConservatively(conservativeSet, stackPointer, thread->stackBase); + void* stackBase = thread->stackBase; + swapIfBackwards(stackPointer, stackBase); + conservativeSet.add(stackPointer, stackBase); resumeThread(thread->platformThread); } diff --git a/Source/JavaScriptCore/runtime/MarkStack.h b/Source/JavaScriptCore/runtime/MarkStack.h index 7946e65..0b7941e 100644 --- a/Source/JavaScriptCore/runtime/MarkStack.h +++ b/Source/JavaScriptCore/runtime/MarkStack.h @@ -27,7 +27,8 @@ #define MarkStack_h #include "JSValue.h" -#include <wtf/HashSet.h> +#include "WriteBarrier.h" +#include <wtf/Vector.h> #include <wtf/Noncopyable.h> #include <wtf/OSAllocator.h> @@ -49,17 +50,23 @@ namespace JSC { #endif { } - - ALWAYS_INLINE void append(JSValue); - void append(JSCell*); - ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues) + void deprecatedAppend(JSValue*); + void deprecatedAppend(JSCell**); + void deprecatedAppend(Register*); + template <typename T> void append(WriteBarrierBase<T>*); + template <typename T> void append(DeprecatedPtr<T>*); + + ALWAYS_INLINE void deprecatedAppendValues(Register* registers, size_t count, MarkSetProperties properties = NoNullValues) { - appendValues(reinterpret_cast<JSValue*>(values), count, properties); + JSValue* values = reinterpret_cast<JSValue*>(registers); + if (count) + m_markSets.append(MarkSet(values, values + count, properties)); } - ALWAYS_INLINE void appendValues(JSValue* values, size_t count, MarkSetProperties properties = NoNullValues) + void appendValues(WriteBarrierBase<Unknown>* barriers, size_t count, MarkSetProperties properties = NoNullValues) { + JSValue* values = barriers->slot(); if (count) m_markSets.append(MarkSet(values, values + count, properties)); } @@ -74,6 +81,8 @@ namespace JSC { } private: + void internalAppend(JSCell*); + void internalAppend(JSValue); void markChildren(JSCell*); struct MarkSet { @@ -188,19 +197,6 @@ namespace JSC { #endif }; - class ConservativeSet { - public: - void add(JSCell* cell) { m_set.add(cell); } - void mark(MarkStack& markStack) - { - HashSet<JSCell*>::iterator end = m_set.end(); - for (HashSet<JSCell*>::iterator it = m_set.begin(); it != end; ++it) - markStack.append(*it); - } - - private: - HashSet<JSCell*> m_set; - }; } #endif diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp new file mode 100644 index 0000000..16053f2 --- /dev/null +++ b/Source/JavaScriptCore/runtime/MarkedBlock.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MarkedBlock.h" + +#include "JSCell.h" + +namespace JSC { + +MarkedBlock* MarkedBlock::create(JSGlobalData* globalData) +{ + PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages); + if (!static_cast<bool>(allocation)) + CRASH(); + return new (allocation.base()) MarkedBlock(allocation, globalData); +} + +void MarkedBlock::destroy(MarkedBlock* block) +{ + for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) + reinterpret_cast<JSCell*>(&block->cells[i])->~JSCell(); + block->m_allocation.deallocate(); +} + +MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData) + : m_allocation(allocation) + , m_heap(&globalData->heap) +{ + marked.set(CELLS_PER_BLOCK - 1); + + Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get(); + for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) + new (&cells[i]) JSCell(dummyMarkableCellStructure); +} + +void MarkedBlock::sweep() +{ +#if !ENABLE(JSC_ZOMBIES) + Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get(); +#endif + + for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) { + if (marked.get(i)) + continue; + + JSCell* cell = reinterpret_cast<JSCell*>(&cells[i]); +#if ENABLE(JSC_ZOMBIES) + if (!cell->isZombie()) { + const ClassInfo* info = cell->classInfo(); + cell->~JSCell(); + new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); + marked.set(i); + } +#else + cell->~JSCell(); + new (cell) JSCell(dummyMarkableCellStructure); +#endif + } +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.h b/Source/JavaScriptCore/runtime/MarkedBlock.h new file mode 100644 index 0000000..f726c25 --- /dev/null +++ b/Source/JavaScriptCore/runtime/MarkedBlock.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MarkedBlock_h +#define MarkedBlock_h + +#include <wtf/Bitmap.h> +#include <wtf/FixedArray.h> +#include <wtf/PageAllocationAligned.h> + +#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedBlock::CELL_SIZE, class_fits_in_cell) + +namespace JSC { + + class Heap; + class JSCell; + class JSGlobalData; + + class MarkedBlock { +#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) + static const size_t BLOCK_SIZE = 64 * 1024; // 64k +#else + static const size_t BLOCK_SIZE = 256 * 1024; // 256k +#endif + + static const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; + static const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK; + static const size_t MINIMUM_CELL_SIZE = 64; + static const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0); + public: + // This is still public for now, for use in assertions. + static const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double); + private: + static const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; + static const size_t CELL_MASK = CELL_SIZE - 1; + static const size_t CELL_ALIGN_MASK = ~CELL_MASK; + static const size_t BITS_PER_BLOCK = BLOCK_SIZE / CELL_SIZE; + static const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(WTF::Bitmap<BITS_PER_BLOCK>)) / CELL_SIZE; // Division rounds down intentionally. + + struct CollectorCell { + FixedArray<double, CELL_ARRAY_LENGTH> memory; + }; + + // Cell size needs to be a power of two for CELL_MASK to be valid. + COMPILE_ASSERT(!(sizeof(CollectorCell) % 2), Collector_cell_size_is_power_of_two); + + public: + static MarkedBlock* create(JSGlobalData*); + static void destroy(MarkedBlock*); + + static bool isCellAligned(const void*); + static MarkedBlock* blockFor(const void*); + + Heap* heap() const; + + void* allocate(size_t& nextCell); + void sweep(); + + bool isEmpty(); + + void clearMarks(); + size_t markCount(); + size_t size(); + size_t capacity(); + + size_t cellNumber(const void*); + bool isMarked(const void*); + bool testAndSetMarked(const void*); + void setMarked(const void*); + + template <typename Functor> void forEach(Functor&); + + FixedArray<CollectorCell, CELLS_PER_BLOCK> cells; + + private: + MarkedBlock(const PageAllocationAligned&, JSGlobalData*); + + WTF::Bitmap<BITS_PER_BLOCK> marked; + PageAllocationAligned m_allocation; + Heap* m_heap; + }; + + inline bool MarkedBlock::isCellAligned(const void* p) + { + return !((intptr_t)(p) & CELL_MASK); + } + + inline MarkedBlock* MarkedBlock::blockFor(const void* p) + { + return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & BLOCK_MASK); + } + + inline Heap* MarkedBlock::heap() const + { + return m_heap; + } + + inline bool MarkedBlock::isEmpty() + { + marked.clear(CELLS_PER_BLOCK - 1); // Clear the always-set last bit to avoid confusing isEmpty(). + bool result = marked.isEmpty(); + marked.set(CELLS_PER_BLOCK - 1); + return result; + } + + inline void MarkedBlock::clearMarks() + { + // allocate() assumes that the last mark bit is always set. + marked.clearAll(); + marked.set(CELLS_PER_BLOCK - 1); + } + + inline size_t MarkedBlock::markCount() + { + return marked.count() - 1; // The last mark bit is always set. + } + + inline size_t MarkedBlock::size() + { + return markCount() * CELL_SIZE; + } + + inline size_t MarkedBlock::capacity() + { + return BLOCK_SIZE; + } + + inline size_t MarkedBlock::cellNumber(const void* cell) + { + return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; + } + + inline bool MarkedBlock::isMarked(const void* cell) + { + return marked.get(cellNumber(cell)); + } + + inline bool MarkedBlock::testAndSetMarked(const void* cell) + { + return marked.testAndSet(cellNumber(cell)); + } + + inline void MarkedBlock::setMarked(const void* cell) + { + marked.set(cellNumber(cell)); + } + + template <typename Functor> inline void MarkedBlock::forEach(Functor& functor) + { + for (size_t i = 0; i < CELLS_PER_BLOCK - 1; ++i) { // The last cell is a dummy place-holder. + if (!marked.get(i)) + continue; + functor(reinterpret_cast<JSCell*>(&cells[i])); + } + } + +} // namespace JSC + +#endif // MarkedSpace_h diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp index 036c8f0..2f8075d 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp +++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp @@ -21,361 +21,118 @@ #include "config.h" #include "MarkedSpace.h" -#include "CollectorHeapIterator.h" #include "JSCell.h" #include "JSGlobalData.h" #include "JSLock.h" -using std::max; - namespace JSC { class Structure; -// tunable parameters - -const size_t GROWTH_FACTOR = 2; -const size_t LOW_WATER_FACTOR = 4; -const size_t ALLOCATIONS_PER_COLLECTION = 3600; -// This value has to be a macro to be used in max() without introducing -// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. -#define MIN_ARRAY_SIZE (static_cast<size_t>(14)) - MarkedSpace::MarkedSpace(JSGlobalData* globalData) - : m_globalData(globalData) + : m_waterMark(0) + , m_highWaterMark(0) + , m_globalData(globalData) { - memset(&m_heap, 0, sizeof(CollectorHeap)); allocateBlock(); } -void MarkedSpace::destroy(ProtectCountSet& protectedValuesCopy) +void MarkedSpace::destroy() { - clearMarkBits(); - ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end(); - for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) - markCell(it->first); - - m_heap.nextCell = 0; - m_heap.nextBlock = 0; - DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); - DeadObjectIterator end(m_heap, m_heap.usedBlocks); - for ( ; it != end; ++it) - (*it)->~JSCell(); + clearMarks(); // Make sure weak pointers appear dead during destruction. - protectedValuesEnd = protectedValuesCopy.end(); - for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) - it->first->~JSCell(); - - for (size_t block = 0; block < m_heap.usedBlocks; ++block) - m_heap.blocks[block].deallocate(); - - fastFree(m_heap.blocks); - - memset(&m_heap, 0, sizeof(CollectorHeap)); + while (m_heap.blocks.size()) + freeBlock(0); + m_heap.blocks.clear(); } -NEVER_INLINE CollectorBlock* MarkedSpace::allocateBlock() +NEVER_INLINE MarkedBlock* MarkedSpace::allocateBlock() { - PageAllocationAligned allocation = PageAllocationAligned::allocate(BLOCK_SIZE, BLOCK_SIZE, OSAllocator::JSGCHeapPages); - CollectorBlock* block = static_cast<CollectorBlock*>(allocation.base()); - if (!block) - CRASH(); - - // Initialize block. - - block->heap = &globalData()->heap; - clearMarkBits(block); - - Structure* dummyMarkableCellStructure = globalData()->dummyMarkableCellStructure.get(); - for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i) - new (&block->cells[i]) JSCell(dummyMarkableCellStructure); - - // Add block to blocks vector. - - size_t numBlocks = m_heap.numBlocks; - if (m_heap.usedBlocks == numBlocks) { - static const size_t maxNumBlocks = ULONG_MAX / sizeof(PageAllocationAligned) / GROWTH_FACTOR; - if (numBlocks > maxNumBlocks) - CRASH(); - numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); - m_heap.numBlocks = numBlocks; - m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, numBlocks * sizeof(PageAllocationAligned))); - } - m_heap.blocks[m_heap.usedBlocks++] = allocation; - + MarkedBlock* block = MarkedBlock::create(globalData()); + m_heap.blocks.append(block); return block; } NEVER_INLINE void MarkedSpace::freeBlock(size_t block) { - ObjectIterator it(m_heap, block); - ObjectIterator end(m_heap, block + 1); - for ( ; it != end; ++it) - (*it)->~JSCell(); - m_heap.blocks[block].deallocate(); + MarkedBlock::destroy(m_heap.blocks[block]); // swap with the last block so we compact as we go - m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1]; - m_heap.usedBlocks--; - - if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { - m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; - m_heap.blocks = static_cast<PageAllocationAligned*>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(PageAllocationAligned))); - } + m_heap.blocks[block] = m_heap.blocks.last(); + m_heap.blocks.removeLast(); } -void* MarkedSpace::allocate(size_t s) +void* MarkedSpace::allocate(size_t) { - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - typedef HeapConstants::Block Block; - typedef HeapConstants::Cell Cell; - - ASSERT(JSLock::lockCount() > 0); - ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT_UNUSED(s, s <= HeapConstants::cellSize); - - // Fast case: find the next garbage cell and recycle it. - do { - ASSERT(m_heap.nextBlock < m_heap.usedBlocks); - Block* block = m_heap.collectorBlock(m_heap.nextBlock); - do { - ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock); - if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block - Cell* cell = &block->cells[m_heap.nextCell]; + ASSERT(m_heap.nextBlock < m_heap.blocks.size()); + MarkedBlock* block = m_heap.collectorBlock(m_heap.nextBlock); + if (void* result = block->allocate(m_heap.nextCell)) + return result; - JSCell* imp = reinterpret_cast<JSCell*>(cell); - imp->~JSCell(); + m_waterMark += block->capacity(); + } while (++m_heap.nextBlock != m_heap.blocks.size()); - ++m_heap.nextCell; - return cell; - } - block->marked.advanceToNextPossibleFreeCell(m_heap.nextCell); - } while (m_heap.nextCell != HeapConstants::cellsPerBlock); - m_heap.nextCell = 0; - } while (++m_heap.nextBlock != m_heap.usedBlocks); - - return 0; -} + if (m_waterMark < m_highWaterMark) + return allocateBlock()->allocate(m_heap.nextCell); -void MarkedSpace::resizeBlocks() -{ - size_t usedCellCount = markedCells(); - size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount); - size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; - - size_t maxCellCount = 1.25f * minCellCount; - size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; - - if (m_heap.usedBlocks < minBlockCount) - growBlocks(minBlockCount); - else if (m_heap.usedBlocks > maxBlockCount) - shrinkBlocks(maxBlockCount); -} - -void MarkedSpace::growBlocks(size_t neededBlocks) -{ - ASSERT(m_heap.usedBlocks < neededBlocks); - while (m_heap.usedBlocks < neededBlocks) - allocateBlock(); + return 0; } -void MarkedSpace::shrinkBlocks(size_t neededBlocks) +void MarkedSpace::shrink() { - ASSERT(m_heap.usedBlocks > neededBlocks); - - // Clear the always-on last bit, so isEmpty() isn't fooled by it. - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - m_heap.collectorBlock(i)->marked.clear(HeapConstants::cellsPerBlock - 1); - - for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) { - if (m_heap.collectorBlock(i)->marked.isEmpty()) { + for (size_t i = 0; i != m_heap.blocks.size() && m_heap.blocks.size() > 1; ) { // We assume at least one block exists at all times. + if (m_heap.collectorBlock(i)->isEmpty()) { freeBlock(i); } else ++i; } - - // Reset the always-on last bit. - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1); } -inline bool isPointerAligned(void* p) +void MarkedSpace::clearMarks() { - return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0); -} - -// Cell size needs to be a power of two for isPossibleCell to be valid. -COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); - -static inline bool isCellAligned(void *p) -{ - return (((intptr_t)(p) & CELL_MASK) == 0); -} - -static inline bool isPossibleCell(void* p) -{ - return isCellAligned(p) && p; -} - -void MarkedSpace::markConservatively(ConservativeSet& conservativeSet, void* start, void* end) -{ -#if OS(WINCE) - if (start > end) { - void* tmp = start; - start = end; - end = tmp; - } -#else - ASSERT(start <= end); -#endif - - ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); - ASSERT(isPointerAligned(start)); - ASSERT(isPointerAligned(end)); - - char** p = static_cast<char**>(start); - char** e = static_cast<char**>(end); - - while (p != e) { - char* x = *p++; - if (isPossibleCell(x)) { - uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x); - xAsBits &= CELL_ALIGN_MASK; - - uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK; - const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); - if (offset > lastCellOffset) - continue; - - CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset); - size_t usedBlocks = m_heap.usedBlocks; - for (size_t block = 0; block < usedBlocks; block++) { - if (m_heap.collectorBlock(block) != blockAddr) - continue; - - // x is a pointer into the heap. Now, verify that the cell it - // points to is live. (If the cell is dead, we must not mark it, - // since that would revive it in a zombie state.) - if (block < m_heap.nextBlock) { - conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits)); - break; - } - - size_t cellOffset = offset / CELL_SIZE; - - if (block == m_heap.nextBlock && cellOffset < m_heap.nextCell) { - conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits)); - break; - } - - if (blockAddr->marked.get(cellOffset)) { - conservativeSet.add(reinterpret_cast<JSCell*>(xAsBits)); - break; - } - } - } - } -} - -void MarkedSpace::clearMarkBits() -{ - for (size_t i = 0; i < m_heap.usedBlocks; ++i) - clearMarkBits(m_heap.collectorBlock(i)); -} - -void MarkedSpace::clearMarkBits(CollectorBlock* block) -{ - // allocate assumes that the last cell in every block is marked. - block->marked.clearAll(); - block->marked.set(HeapConstants::cellsPerBlock - 1); -} - -size_t MarkedSpace::markedCells(size_t startBlock, size_t startCell) const -{ - ASSERT(startBlock <= m_heap.usedBlocks); - ASSERT(startCell < HeapConstants::cellsPerBlock); - - if (startBlock >= m_heap.usedBlocks) - return 0; - - size_t result = 0; - result += m_heap.collectorBlock(startBlock)->marked.count(startCell); - for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i) - result += m_heap.collectorBlock(i)->marked.count(); - - return result; + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + m_heap.collectorBlock(i)->clearMarks(); } void MarkedSpace::sweep() { -#if !ENABLE(JSC_ZOMBIES) - Structure* dummyMarkableCellStructure = globalData()->dummyMarkableCellStructure.get(); -#endif - - DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); - DeadObjectIterator end(m_heap, m_heap.usedBlocks); - for ( ; it != end; ++it) { - JSCell* cell = *it; -#if ENABLE(JSC_ZOMBIES) - if (!cell->isZombie()) { - const ClassInfo* info = cell->classInfo(); - cell->~JSCell(); - new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); - Heap::markCell(cell); - } -#else - cell->~JSCell(); - // Callers of sweep assume it's safe to mark any cell in the heap. - new (cell) JSCell(dummyMarkableCellStructure); -#endif - } + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + m_heap.collectorBlock(i)->sweep(); } size_t MarkedSpace::objectCount() const { - return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks - + m_heap.nextCell // allocated cells in current block - + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap - - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel -} - -void MarkedSpace::addToStatistics(Statistics& statistics) const -{ - statistics.size += m_heap.usedBlocks * BLOCK_SIZE; - statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize); + size_t result = 0; + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + result += m_heap.collectorBlock(i)->markCount(); + return result; } -MarkedSpace::Statistics MarkedSpace::statistics() const +size_t MarkedSpace::size() const { - Statistics statistics = { 0, 0 }; - addToStatistics(statistics); - return statistics; + size_t result = 0; + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + result += m_heap.collectorBlock(i)->size(); + return result; } -size_t MarkedSpace::size() const +size_t MarkedSpace::capacity() const { - return m_heap.usedBlocks * BLOCK_SIZE; + size_t result = 0; + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + result += m_heap.collectorBlock(i)->capacity(); + return result; } void MarkedSpace::reset() { m_heap.nextCell = 0; m_heap.nextBlock = 0; + m_waterMark = 0; #if ENABLE(JSC_ZOMBIES) sweep(); #endif - resizeBlocks(); -} - -LiveObjectIterator MarkedSpace::primaryHeapBegin() -{ - return LiveObjectIterator(m_heap, 0); -} - -LiveObjectIterator MarkedSpace::primaryHeapEnd() -{ - return LiveObjectIterator(m_heap, m_heap.usedBlocks); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h index af312b5..fcb93b7 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.h +++ b/Source/JavaScriptCore/runtime/MarkedSpace.h @@ -23,7 +23,9 @@ #define MarkedSpace_h #include "MachineStackMarker.h" +#include "MarkedBlock.h" #include "PageAllocationAligned.h" +#include <wtf/Bitmap.h> #include <wtf/FixedArray.h> #include <wtf/HashCountedSet.h> #include <wtf/Noncopyable.h> @@ -31,7 +33,6 @@ namespace JSC { - class CollectorBlock; class Heap; class JSCell; class JSGlobalData; @@ -39,182 +40,115 @@ namespace JSC { class MarkStack; class WeakGCHandle; -#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP) - const size_t BLOCK_SIZE = 64 * 1024; // 64k -#else - const size_t BLOCK_SIZE = 256 * 1024; // 256k -#endif - - typedef HashCountedSet<JSCell*> ProtectCountSet; - struct CollectorHeap { - size_t nextBlock; - size_t nextCell; - PageAllocationAligned* blocks; + CollectorHeap() + : nextBlock(0) + , nextCell(0) + { + } - size_t numBlocks; - size_t usedBlocks; - - CollectorBlock* collectorBlock(size_t index) const + MarkedBlock* collectorBlock(size_t index) const { - return static_cast<CollectorBlock*>(blocks[index].base()); + return blocks[index]; } + + size_t nextBlock; + size_t nextCell; + Vector<MarkedBlock*> blocks; }; class MarkedSpace { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: - MarkedSpace(JSGlobalData*); - void destroy(ProtectCountSet&); - - void* allocate(size_t); - - size_t objectCount() const; - struct Statistics { - size_t size; - size_t free; - }; - Statistics statistics() const; - size_t size() const; - static Heap* heap(JSCell*); - static bool isCellMarked(const JSCell*); - static bool checkMarkCell(const JSCell*); - static void markCell(JSCell*); - - WeakGCHandle* addWeakGCHandle(JSCell*); - - void markConservatively(ConservativeSet&, void* start, void* end); + static bool isMarked(const JSCell*); + static bool testAndSetMarked(const JSCell*); + static void setMarked(const JSCell*); - static bool isNumber(JSCell*); - - LiveObjectIterator primaryHeapBegin(); - LiveObjectIterator primaryHeapEnd(); + MarkedSpace(JSGlobalData*); + void destroy(); JSGlobalData* globalData() { return m_globalData; } - static CollectorBlock* cellBlock(const JSCell*); - static size_t cellOffset(const JSCell*); + size_t highWaterMark() { return m_highWaterMark; } + void setHighWaterMark(size_t highWaterMark) { m_highWaterMark = highWaterMark; } + + void* allocate(size_t); + void clearMarks(); + void markRoots(); void reset(); void sweep(); + void shrink(); - NEVER_INLINE CollectorBlock* allocateBlock(); - NEVER_INLINE void freeBlock(size_t); - void resizeBlocks(); - void growBlocks(size_t neededBlocks); - void shrinkBlocks(size_t neededBlocks); - void clearMarkBits(); - void clearMarkBits(CollectorBlock*); - size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; + size_t size() const; + size_t capacity() const; + size_t objectCount() const; - void addToStatistics(Statistics&) const; + bool contains(const void*); - void markRoots(); + template<typename Functor> void forEach(Functor&); private: - CollectorHeap m_heap; - JSGlobalData* m_globalData; - }; + NEVER_INLINE MarkedBlock* allocateBlock(); + NEVER_INLINE void freeBlock(size_t); - // tunable parameters - // derived constants - const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; - const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK; - const size_t MINIMUM_CELL_SIZE = 64; - const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0); - const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double); - const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; - const size_t CELL_MASK = CELL_SIZE - 1; - const size_t CELL_ALIGN_MASK = ~CELL_MASK; - const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(MarkedSpace*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. - - const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; - const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); - - struct CollectorBitmap { - FixedArray<uint32_t, BITMAP_WORDS> bits; - bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } - void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } - bool getset(size_t n) - { - unsigned i = (1 << (n & 0x1F)); - uint32_t& b = bits[n >> 5]; - bool r = !!(b & i); - b |= i; - return r; - } - void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } - void clearAll() { memset(bits.data(), 0, sizeof(bits)); } - ALWAYS_INLINE void advanceToNextPossibleFreeCell(size_t& startCell) - { - if (!~bits[startCell >> 5]) - startCell = (startCell & (~0x1F)) + 32; - else - ++startCell; - } - size_t count(size_t startCell = 0) - { - size_t result = 0; - for ( ; (startCell & 0x1F) != 0; ++startCell) { - if (get(startCell)) - ++result; - } - for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i) - result += WTF::bitCount(bits[i]); - return result; - } - size_t isEmpty() // Much more efficient than testing count() == 0. - { - for (size_t i = 0; i < BITMAP_WORDS; ++i) - if (bits[i] != 0) - return false; - return true; - } - }; - - struct CollectorCell { - FixedArray<double, CELL_ARRAY_LENGTH> memory; - }; + void clearMarks(MarkedBlock*); - class CollectorBlock { - public: - FixedArray<CollectorCell, CELLS_PER_BLOCK> cells; - CollectorBitmap marked; - Heap* heap; + CollectorHeap m_heap; + size_t m_waterMark; + size_t m_highWaterMark; + JSGlobalData* m_globalData; }; - struct HeapConstants { - static const size_t cellSize = CELL_SIZE; - static const size_t cellsPerBlock = CELLS_PER_BLOCK; - typedef CollectorCell Cell; - typedef CollectorBlock Block; - }; + inline Heap* MarkedSpace::heap(JSCell* cell) + { + return MarkedBlock::blockFor(cell)->heap(); + } - inline CollectorBlock* MarkedSpace::cellBlock(const JSCell* cell) + inline bool MarkedSpace::isMarked(const JSCell* cell) { - return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); + return MarkedBlock::blockFor(cell)->isMarked(cell); } - inline size_t MarkedSpace::cellOffset(const JSCell* cell) + inline bool MarkedSpace::testAndSetMarked(const JSCell* cell) { - return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; + return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); } - inline bool MarkedSpace::isCellMarked(const JSCell* cell) + inline void MarkedSpace::setMarked(const JSCell* cell) { - return cellBlock(cell)->marked.get(cellOffset(cell)); + MarkedBlock::blockFor(cell)->setMarked(cell); } - inline bool MarkedSpace::checkMarkCell(const JSCell* cell) + inline bool MarkedSpace::contains(const void* x) { - return cellBlock(cell)->marked.getset(cellOffset(cell)); + if (!MarkedBlock::isCellAligned(x)) + return false; + + MarkedBlock* block = MarkedBlock::blockFor(x); + if (!block) + return false; + + size_t size = m_heap.blocks.size(); + for (size_t i = 0; i < size; i++) { + if (block != m_heap.collectorBlock(i)) + continue; + + // x is a pointer into the heap. Now, verify that the cell it + // points to is live. (If the cell is dead, we must not mark it, + // since that would revive it in a zombie state.) + return block->isMarked(x); + } + + return false; } - inline void MarkedSpace::markCell(JSCell* cell) + template <typename Functor> inline void MarkedSpace::forEach(Functor& functor) { - cellBlock(cell)->marked.set(cellOffset(cell)); + for (size_t i = 0; i < m_heap.blocks.size(); ++i) + m_heap.collectorBlock(i)->forEach(functor); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp index 080d7d2..c79316b 100644 --- a/Source/JavaScriptCore/runtime/MathObject.cpp +++ b/Source/JavaScriptCore/runtime/MathObject.cpp @@ -89,14 +89,14 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable }; MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) : JSObjectWithGlobalObject(globalObject, structure) { - putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly); - putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG10E"), jsNumber(1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly); } // ECMA 15.8 diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp index 06a319b..86101f5 100644 --- a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp +++ b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp @@ -32,11 +32,6 @@ namespace JSC { -MarkedSpace::Statistics heapStatistics(JSGlobalData* commonGlobalData) -{ - return commonGlobalData->heap.statistics(); -} - GlobalMemoryStatistics globalMemoryStatistics() { GlobalMemoryStatistics stats; diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.h b/Source/JavaScriptCore/runtime/MemoryStatistics.h index 2659702..d4b8b6f 100644 --- a/Source/JavaScriptCore/runtime/MemoryStatistics.h +++ b/Source/JavaScriptCore/runtime/MemoryStatistics.h @@ -37,7 +37,6 @@ struct GlobalMemoryStatistics { size_t JITBytes; }; -MarkedSpace::Statistics heapStatistics(JSGlobalData* commonGlobalData); GlobalMemoryStatistics globalMemoryStatistics(); } diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp index eb508eb..421eecf 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -37,8 +37,8 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* { NativeErrorPrototype* prototype = new (exec) NativeErrorPrototype(exec, globalObject, prototypeStructure, nameAndMessage, this); - putDirect(exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 - putDirect(exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 + putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum); m_errorStructure = ErrorInstance::createStructure(prototype); } diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp index 540220a..4e10268 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp @@ -34,9 +34,9 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype); NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& nameAndMessage, NativeErrorConstructor* constructor) : JSObjectWithGlobalObject(globalObject, structure) { - putDirect(exec->propertyNames().name, jsString(exec, nameAndMessage), 0); - putDirect(exec->propertyNames().message, jsString(exec, nameAndMessage), 0); - putDirect(exec->propertyNames().constructor, constructor, DontEnum); + putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), 0); + putDirect(exec->globalData(), exec->propertyNames().message, jsString(exec, nameAndMessage), 0); + putDirect(exec->globalData(), exec->propertyNames().constructor, constructor, DontEnum); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp index 5369ca0..7cec875 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp @@ -58,10 +58,10 @@ NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObje : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->info.className)) { // Number.Prototype - putDirectWithoutTransition(exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); } bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -102,9 +102,9 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&) // ECMA 15.7.1 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec) { - NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); + NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0; - object->setInternalValue(jsNumber(n)); + object->setInternalValue(exec->globalData(), jsNumber(n)); return JSValue::encode(object); } diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp index 1a7e44c..603c2f0 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.cpp +++ b/Source/JavaScriptCore/runtime/NumberObject.cpp @@ -31,8 +31,8 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject); const ClassInfo NumberObject::info = { "Number", 0, 0, 0 }; -NumberObject::NumberObject(NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +NumberObject::NumberObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(globalData, structure) { } @@ -43,8 +43,8 @@ JSValue NumberObject::getJSNumber() NumberObject* constructNumber(ExecState* exec, JSValue number) { - NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure()); - object->setInternalValue(number); + NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); + object->setInternalValue(exec->globalData(), number); return object; } diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h index e82b593..044f490 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.h +++ b/Source/JavaScriptCore/runtime/NumberObject.h @@ -27,7 +27,7 @@ namespace JSC { class NumberObject : public JSWrapperObject { public: - explicit NumberObject(NonNullPassRefPtr<Structure>); + explicit NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure>); static const ClassInfo info; diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp index 0b86c00..fbe6992 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp @@ -47,9 +47,9 @@ static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*); // ECMA 15.7.4 NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) - : NumberObject(structure) + : NumberObject(exec->globalData(), structure) { - setInternalValue(jsNumber(0)); + setInternalValue(exec->globalData(), jsNumber(0)); // The constructor will be added later, after NumberConstructor has been constructed diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index ca3dcd7..f31da67 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -47,10 +47,10 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObje : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object")) { // ECMA 15.2.3.1 - putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum); @@ -117,15 +117,15 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState JSObject* description = constructEmptyObject(exec); if (!descriptor.isAccessorDescriptor()) { - description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0); - description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0); + description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0); + description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0); } else { - description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0); - description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0); + description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0); + description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0); } - description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0); - description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0); + description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0); + description->putDirect(exec->globalData(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0); return JSValue::encode(description); } diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index 1252345..6e84123 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -429,7 +429,7 @@ namespace JSC { // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. if (cell->structure()->isDictionary()) { - asObject(cell)->flattenDictionaryObject(); + asObject(cell)->flattenDictionaryObject(callFrame->globalData()); if (slotBase == cell) slotOffset = cell->structure()->get(propertyName); } @@ -454,7 +454,7 @@ namespace JSC { // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. if (base->structure()->isDictionary()) - asObject(base)->flattenDictionaryObject(); + asObject(base)->flattenDictionaryObject(callFrame->globalData()); ++count; } @@ -471,7 +471,7 @@ namespace JSC { PropertySlot slot; JSObject* base; while (true) { - base = *iter; + base = iter->get(); if (next == end) return isStrictPut ? JSValue() : base; if (base->getPropertySlot(callFrame, property, slot)) diff --git a/Source/JavaScriptCore/runtime/PropertySlot.h b/Source/JavaScriptCore/runtime/PropertySlot.h index de9ddc9..cdda6ff 100644 --- a/Source/JavaScriptCore/runtime/PropertySlot.h +++ b/Source/JavaScriptCore/runtime/PropertySlot.h @@ -32,8 +32,7 @@ namespace JSC { class ExecState; class JSObject; -#define JSC_VALUE_SLOT_MARKER 0 -#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1) +#define JSC_VALUE_MARKER 0 #define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2) #define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3) @@ -67,10 +66,8 @@ namespace JSC { JSValue getValue(ExecState* exec, const Identifier& propertyName) const { - if (m_getValue == JSC_VALUE_SLOT_MARKER) - return *m_data.valueSlot; - if (m_getValue == JSC_REGISTER_SLOT_MARKER) - return (*m_data.registerSlot).jsValue(); + if (m_getValue == JSC_VALUE_MARKER) + return m_value; if (m_getValue == INDEX_GETTER_MARKER) return m_getIndexValue(exec, slotBase(), index()); if (m_getValue == GETTER_FUNCTION_MARKER) @@ -80,10 +77,8 @@ namespace JSC { JSValue getValue(ExecState* exec, unsigned propertyName) const { - if (m_getValue == JSC_VALUE_SLOT_MARKER) - return *m_data.valueSlot; - if (m_getValue == JSC_REGISTER_SLOT_MARKER) - return (*m_data.registerSlot).jsValue(); + if (m_getValue == JSC_VALUE_MARKER) + return m_value; if (m_getValue == INDEX_GETTER_MARKER) return m_getIndexValue(exec, m_slotBase, m_data.index); if (m_getValue == GETTER_FUNCTION_MARKER) @@ -100,41 +95,32 @@ namespace JSC { return m_offset; } - void setValueSlot(JSValue* valueSlot) + void setValue(JSValue slotBase, JSValue value) { - ASSERT(valueSlot); - clearBase(); + ASSERT(value); clearOffset(); - m_getValue = JSC_VALUE_SLOT_MARKER; - m_data.valueSlot = valueSlot; - } - - void setValueSlot(JSValue slotBase, JSValue* valueSlot) - { - ASSERT(valueSlot); - m_getValue = JSC_VALUE_SLOT_MARKER; + m_getValue = JSC_VALUE_MARKER; m_slotBase = slotBase; - m_data.valueSlot = valueSlot; + m_value = value; } - void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset) + void setValue(JSValue slotBase, JSValue value, size_t offset) { - ASSERT(valueSlot); - m_getValue = JSC_VALUE_SLOT_MARKER; + ASSERT(value); + m_getValue = JSC_VALUE_MARKER; m_slotBase = slotBase; - m_data.valueSlot = valueSlot; + m_value = value; m_offset = offset; m_cachedPropertyType = Value; } - + void setValue(JSValue value) { ASSERT(value); clearBase(); clearOffset(); - m_getValue = JSC_VALUE_SLOT_MARKER; + m_getValue = JSC_VALUE_MARKER; m_value = value; - m_data.valueSlot = &m_value; } void setRegisterSlot(Register* registerSlot) @@ -142,8 +128,8 @@ namespace JSC { ASSERT(registerSlot); clearBase(); clearOffset(); - m_getValue = JSC_REGISTER_SLOT_MARKER; - m_data.registerSlot = registerSlot; + m_getValue = JSC_VALUE_MARKER; + m_value = registerSlot->jsValue(); } void setCustom(JSValue slotBase, GetValueFunc getValue) @@ -251,8 +237,6 @@ namespace JSC { JSValue m_slotBase; union { JSObject* getterFunc; - JSValue* valueSlot; - Register* registerSlot; unsigned index; } m_data; diff --git a/Source/JavaScriptCore/runtime/PrototypeFunction.cpp b/Source/JavaScriptCore/runtime/PrototypeFunction.cpp index 3529080..95e1033 100644 --- a/Source/JavaScriptCore/runtime/PrototypeFunction.cpp +++ b/Source/JavaScriptCore/runtime/PrototypeFunction.cpp @@ -37,7 +37,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, JSGlobalObject* globalObje , m_function(function) { ASSERT_ARG(function, function); - putDirect(exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } PrototypeFunction::PrototypeFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function) @@ -45,7 +45,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, JSGlobalObject* globalObje , m_function(function) { ASSERT_ARG(function, function); - putDirect(exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); + putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } CallType PrototypeFunction::getCallData(CallData& callData) diff --git a/Source/JavaScriptCore/runtime/PutPropertySlot.h b/Source/JavaScriptCore/runtime/PutPropertySlot.h index 4b0b394..4c9e0e6 100644 --- a/Source/JavaScriptCore/runtime/PutPropertySlot.h +++ b/Source/JavaScriptCore/runtime/PutPropertySlot.h @@ -45,14 +45,14 @@ namespace JSC { { } - void setExistingProperty(JSObject* base, size_t offset) + void setExistingProperty(DeprecatedPtr<JSObject> base, size_t offset) { m_type = ExistingProperty; m_base = base; m_offset = offset; } - void setNewProperty(JSObject* base, size_t offset) + void setNewProperty(DeprecatedPtr<JSObject> base, size_t offset) { m_type = NewProperty; m_base = base; @@ -60,7 +60,7 @@ namespace JSC { } Type type() const { return m_type; } - JSObject* base() const { return m_base; } + JSObject* base() const { return m_base.get(); } bool isStrictMode() const { return m_isStrictMode; } bool isCacheable() const { return m_type != Uncachable; } @@ -70,7 +70,7 @@ namespace JSC { } private: Type m_type; - JSObject* m_base; + DeprecatedPtr<JSObject> m_base; size_t m_offset; bool m_isStrictMode; }; diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 31a1abe..95ce5e9 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -25,6 +25,7 @@ #include "Lexer.h" #include "yarr/Yarr.h" +#include "yarr/YarrJIT.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -230,11 +231,12 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* #if ENABLE(YARR_JIT) Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode; - char jitAddr[20]; + const size_t jitAddrSize = 20; + char jitAddr[jitAddrSize]; if (m_state == JITCode) - sprintf(jitAddr, "fallback"); + snprintf(jitAddr, jitAddrSize, "fallback"); else - sprintf(jitAddr, "0x%014lx", reinterpret_cast<unsigned long int>(codeBlock.getAddr())); + snprintf(jitAddr, jitAddrSize, "0x%014lx", reinterpret_cast<unsigned long int>(codeBlock.getAddr())); #else const char* jitAddr = "JIT Off"; #endif diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 30d3eab..1b30514 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -100,10 +100,10 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje , d(adoptPtr(new RegExpConstructorPrivate)) { // ECMA 15.10.5.1 RegExp.prototype - putDirectWithoutTransition(exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum); } RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp index 54c5082..976cff6 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.cpp +++ b/Source/JavaScriptCore/runtime/ScopeChain.cpp @@ -35,12 +35,12 @@ void ScopeChainNode::print() const { ScopeChainIterator scopeEnd = end(); for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) { - JSObject* o = *scopeIter; + DeprecatedPtr<JSObject> o = *scopeIter; PropertyNameArray propertyNames(globalObject->globalExec()); o->getPropertyNames(globalObject->globalExec(), propertyNames); PropertyNameArray::const_iterator propEnd = propertyNames.end(); - fprintf(stderr, "----- [scope %p] -----\n", o); + fprintf(stderr, "----- [scope %p] -----\n", o.get()); for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) { Identifier name = *propIter; fprintf(stderr, "%s, ", name.ustring().utf8().data()); diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h index b104e75..11f3692 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.h +++ b/Source/JavaScriptCore/runtime/ScopeChain.h @@ -21,6 +21,7 @@ #ifndef ScopeChain_h #define ScopeChain_h +#include "WriteBarrier.h" #include <wtf/FastAllocBase.h> namespace JSC { @@ -52,7 +53,6 @@ namespace JSC { ~ScopeChainNode() { next = 0; - object = 0; globalData = 0; globalObject = 0; globalThis = 0; @@ -60,7 +60,7 @@ namespace JSC { #endif ScopeChainNode* next; - JSObject* object; + DeprecatedPtr<JSObject> object; JSGlobalData* globalData; JSGlobalObject* globalObject; JSObject* globalThis; @@ -131,8 +131,8 @@ namespace JSC { { } - JSObject* const & operator*() const { return m_node->object; } - JSObject* const * operator->() const { return &(operator*()); } + DeprecatedPtr<JSObject> const & operator*() const { return m_node->object; } + DeprecatedPtr<JSObject> const * operator->() const { return &(operator*()); } ScopeChainIterator& operator++() { m_node = m_node->next; return *this; } @@ -195,7 +195,7 @@ namespace JSC { ScopeChainNode* node() const { return m_node; } - JSObject* top() const { return m_node->object; } + JSObject* top() const { return m_node->object.get(); } ScopeChainIterator begin() const { return m_node->begin(); } ScopeChainIterator end() const { return m_node->end(); } diff --git a/Source/JavaScriptCore/runtime/ScopeChainMark.h b/Source/JavaScriptCore/runtime/ScopeChainMark.h index 984d101..faa4824 100644 --- a/Source/JavaScriptCore/runtime/ScopeChainMark.h +++ b/Source/JavaScriptCore/runtime/ScopeChainMark.h @@ -28,7 +28,7 @@ namespace JSC { inline void ScopeChain::markAggregate(MarkStack& markStack) const { for (ScopeChainNode* n = m_node; n; n = n->next) - markStack.append(n->object); + markStack.append(&n->object); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp index 5614932..9b193f5 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.cpp +++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp @@ -35,9 +35,9 @@ namespace JSC { static const unsigned numCharactersToStore = 0x100; -static inline bool isMarked(JSString* string) +static inline bool isMarked(JSCell* string) { - return string && Heap::isCellMarked(string); + return string && Heap::isMarked(string); } class SmallStringsStorage { @@ -83,9 +83,9 @@ void SmallStrings::markChildren(MarkStack& markStack) so, it's probably reasonable to mark the rest. If not, we clear the cache. */ - bool isAnyStringMarked = isMarked(m_emptyString); + bool isAnyStringMarked = isMarked(m_emptyString.get()); for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i) - isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); + isAnyStringMarked = isMarked(m_singleCharacterStrings[i].get()); if (!isAnyStringMarked) { clear(); @@ -93,10 +93,10 @@ void SmallStrings::markChildren(MarkStack& markStack) } if (m_emptyString) - markStack.append(m_emptyString); + markStack.append(&m_emptyString); for (unsigned i = 0; i < numCharactersToStore; ++i) { if (m_singleCharacterStrings[i]) - markStack.append(m_singleCharacterStrings[i]); + markStack.append(&m_singleCharacterStrings[i]); } } diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h index ac84fe8..ee795b6 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.h +++ b/Source/JavaScriptCore/runtime/SmallStrings.h @@ -27,6 +27,7 @@ #define SmallStrings_h #include "UString.h" +#include "WriteBarrier.h" #include <wtf/FixedArray.h> #include <wtf/OwnPtr.h> @@ -47,13 +48,13 @@ namespace JSC { { if (!m_emptyString) createEmptyString(globalData); - return m_emptyString; + return m_emptyString.get(); } JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character) { if (!m_singleCharacterStrings[character]) createSingleCharacterString(globalData, character); - return m_singleCharacterStrings[character]; + return m_singleCharacterStrings[character].get(); } StringImpl* singleCharacterStringRep(unsigned char character); @@ -63,14 +64,14 @@ namespace JSC { unsigned count() const; #if ENABLE(JIT) - JSString** singleCharacterStrings() { return m_singleCharacterStrings.data(); } + JSCell** singleCharacterStrings() { return m_singleCharacterStrings[0].slot(); } #endif private: void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); - JSString* m_emptyString; - FixedArray<JSString*, 0x100> m_singleCharacterStrings; + DeprecatedPtr<JSString> m_emptyString; + FixedArray<DeprecatedPtr<JSString>, 0x100> m_singleCharacterStrings; OwnPtr<SmallStringsStorage> m_storage; }; diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp index 101650c..604473b 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.cpp +++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp @@ -53,7 +53,7 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, stringPrototype->classInfo()->className)) { // ECMA 15.5.3.1 String.prototype - putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete); // ECMA 15.5.3.2 fromCharCode() #if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL) @@ -62,7 +62,7 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum); #endif // no. of arguments for constructor - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); } // ECMA 15.5.2 diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index dc27618..eb9cfa3 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -30,21 +30,21 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::info = { "String", 0, 0, 0 }; StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) + : JSWrapperObject(exec->globalData(), structure) { - setInternalValue(jsEmptyString(exec)); + setInternalValue(exec->globalData(), jsEmptyString(exec)); } -StringObject::StringObject(NonNullPassRefPtr<Structure> structure, JSString* string) - : JSWrapperObject(structure) +StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string) + : JSWrapperObject(globalData, structure) { - setInternalValue(string); + setInternalValue(globalData, string); } StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) - : JSWrapperObject(structure) + : JSWrapperObject(exec->globalData(), structure) { - setInternalValue(jsString(exec, string)); + setInternalValue(exec->globalData(), jsString(exec, string)); } bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index e3add77..03488f5 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -53,7 +53,7 @@ namespace JSC { protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; - StringObject(NonNullPassRefPtr<Structure>, JSString*); + StringObject(JSGlobalData&, NonNullPassRefPtr<Structure>, JSString*); }; StringObject* asStringObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index 8b3d056..545c93e 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -134,9 +134,9 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) : StringObject(exec, structure) { - putAnonymousValue(0, globalObject); + putAnonymousValue(exec->globalData(), 0, globalObject); // The constructor will be added later, after StringConstructor has been built - putDirectWithoutTransition(exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum); } bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot) diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index 0179eed..e8f5d7a 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -242,7 +242,7 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anony m_transitions.m_singleTransition = 0; ASSERT(m_prototype); - ASSERT(m_prototype.isObject() || m_prototype.isNull()); + ASSERT(m_prototype->isObject() || m_prototype->isNull()); #ifndef NDEBUG #if ENABLE(JSC_MULTIPLE_THREADS) @@ -476,7 +476,7 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con return transition.release(); } - RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount()); + RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount()); transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; transition->m_previous = structure; @@ -595,7 +595,7 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di { ASSERT(!structure->isUncacheableDictionary()); - RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount()); + RefPtr<Structure> transition = create(structure->m_prototype.get(), structure->typeInfo(), structure->anonymousSlotCount()); transition->m_dictionaryKind = kind; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; @@ -620,7 +620,7 @@ PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* st return toDictionaryTransition(structure, UncachedDictionaryKind); } -PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object) +PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object) { ASSERT(isDictionary()); if (isUncacheableDictionary()) { @@ -651,7 +651,7 @@ PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object) // Copy the original property values into their final locations for (unsigned i = 0; i < propertyCount; i++) - object->putDirectOffset(anonymousSlotCount + i, values[i]); + object->putDirectOffset(globalData, anonymousSlotCount + i, values[i]); if (m_propertyTable->deletedOffsets) { delete m_propertyTable->deletedOffsets; diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index f480051..77724ac 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -80,7 +80,7 @@ namespace JSC { static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*); static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*); - PassRefPtr<Structure> flattenDictionaryStructure(JSObject*); + PassRefPtr<Structure> flattenDictionaryStructure(JSGlobalData&, JSObject*); ~Structure(); @@ -94,7 +94,8 @@ namespace JSC { const TypeInfo& typeInfo() const { return m_typeInfo; } - JSValue storedPrototype() const { return m_prototype; } + JSValue storedPrototype() const { return m_prototype.get(); } + DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; } JSValue prototypeForLookup(ExecState*) const; StructureChain* prototypeChain(ExecState*) const; @@ -206,7 +207,7 @@ namespace JSC { TypeInfo m_typeInfo; - JSValue m_prototype; + DeprecatedPtr<Unknown> m_prototype; mutable RefPtr<StructureChain> m_cachedPrototypeChain; RefPtr<Structure> m_previous; diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp index 085876c..e4523c3 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.cpp +++ b/Source/JavaScriptCore/runtime/StructureChain.cpp @@ -38,7 +38,7 @@ StructureChain::StructureChain(Structure* head) for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) ++size; - m_vector.set(new RefPtr<Structure>[size + 1]); + m_vector = adoptArrayPtr(new RefPtr<Structure>[size + 1]); size_t i = 0; for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h index 316794f..7bf4503 100644 --- a/Source/JavaScriptCore/runtime/WeakGCMap.h +++ b/Source/JavaScriptCore/runtime/WeakGCMap.h @@ -46,22 +46,31 @@ class WeakGCMap { */ public: - typedef typename HashMap<KeyType, MappedType>::iterator iterator; - typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator; + typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::iterator iterator; + typedef typename HashMap<KeyType, DeprecatedPtr<MappedType> >::const_iterator const_iterator; bool isEmpty() { return m_map.isEmpty(); } void clear() { m_map.clear(); } - MappedType get(const KeyType& key) const; - pair<iterator, bool> set(const KeyType&, const MappedType&); - MappedType take(const KeyType& key); + MappedType* get(const KeyType&) const; + pair<iterator, bool> set(const KeyType&, MappedType*); + MappedType* take(const KeyType&); // These unchecked functions provide access to a value even if the value's // mark bit is not set. This is used, among other things, to retrieve values // during the GC mark phase, which begins by clearing all mark bits. - - MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); } - bool uncheckedRemove(const KeyType&, const MappedType&); + + size_t uncheckedSize() { return m_map.size(); } + + MappedType* uncheckedGet(const KeyType& key) const { return m_map.get(key).get(); } + DeprecatedPtr<MappedType>* uncheckedGetSlot(const KeyType& key) + { + iterator iter = m_map.find(key); + if (iter == m_map.end()) + return 0; + return &iter->second; + } + bool uncheckedRemove(const KeyType&, MappedType*); iterator uncheckedBegin() { return m_map.begin(); } iterator uncheckedEnd() { return m_map.end(); } @@ -69,51 +78,54 @@ public: const_iterator uncheckedBegin() const { return m_map.begin(); } const_iterator uncheckedEnd() const { return m_map.end(); } + bool isValid(iterator it) const { return Heap::isMarked(it->second.get()); } + bool isValid(const_iterator it) const { return Heap::isMarked(it->second.get()); } + private: - HashMap<KeyType, MappedType> m_map; + HashMap<KeyType, DeprecatedPtr<MappedType> > m_map; }; template<typename KeyType, typename MappedType> -inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const +inline MappedType* WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const { - MappedType result = m_map.get(key); - if (result == HashTraits<MappedType>::emptyValue()) + MappedType* result = m_map.get(key).get(); + if (result == HashTraits<MappedType*>::emptyValue()) return result; - if (!Heap::isCellMarked(result)) - return HashTraits<MappedType>::emptyValue(); + if (!Heap::isMarked(result)) + return HashTraits<MappedType*>::emptyValue(); return result; } template<typename KeyType, typename MappedType> -MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key) +MappedType* WeakGCMap<KeyType, MappedType>::take(const KeyType& key) { - MappedType result = m_map.take(key); - if (result == HashTraits<MappedType>::emptyValue()) + MappedType* result = m_map.take(key).get(); + if (result == HashTraits<MappedType*>::emptyValue()) return result; - if (!Heap::isCellMarked(result)) - return HashTraits<MappedType>::emptyValue(); + if (!Heap::isMarked(result)) + return HashTraits<MappedType*>::emptyValue(); return result; } template<typename KeyType, typename MappedType> -pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value) +pair<typename WeakGCMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, MappedType* value) { - Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now. + Heap::setMarked(value); // If value is newly allocated, it's not marked, so mark it now. pair<iterator, bool> result = m_map.add(key, value); if (!result.second) { // pre-existing entry - result.second = !Heap::isCellMarked(result.first->second); + result.second = !Heap::isMarked(result.first->second.get()); result.first->second = value; } return result; } template<typename KeyType, typename MappedType> -bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value) +bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, MappedType* value) { iterator it = m_map.find(key); if (it == m_map.end()) return false; - if (it->second != value) + if (it->second.get() != value) return false; m_map.remove(it); return true; diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h new file mode 100644 index 0000000..64150ed --- /dev/null +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WriteBarrier_h +#define WriteBarrier_h + +#include "JSValue.h" + +namespace JSC { +class JSCell; +class JSGlobalData; + +typedef enum { } Unknown; + +template <class T> class DeprecatedPtr { +public: + DeprecatedPtr() : m_cell(0) { } + DeprecatedPtr(T* cell) : m_cell(reinterpret_cast<JSCell*>(cell)) { } + T* get() const { return reinterpret_cast<T*>(m_cell); } + T* operator*() const { return static_cast<T*>(m_cell); } + T* operator->() const { return static_cast<T*>(m_cell); } + + JSCell** slot() { return &m_cell; } + + typedef T* (DeprecatedPtr::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + + bool operator!() const { return !m_cell; } + +protected: + JSCell* m_cell; +}; + +template <> class DeprecatedPtr<Unknown> { +public: + DeprecatedPtr() { } + DeprecatedPtr(JSValue value) : m_value(value) { } + DeprecatedPtr(JSCell* value) : m_value(value) { } + const JSValue& get() const { return m_value; } + const JSValue* operator*() const { return &m_value; } + const JSValue* operator->() const { return &m_value; } + + JSValue* slot() { return &m_value; } + + typedef JSValue (DeprecatedPtr::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + bool operator!() const { return !m_value; } + +private: + JSValue m_value; +}; + +template <typename T> struct WriteBarrierCheck { + static const bool IsJSValue = false; +}; + +template <> struct WriteBarrierCheck<JSValue> { + static const bool IsJSValue = true; +}; + +template <typename T> class WriteBarrierBase { +public: + COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); + void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } + + T* get() const { return reinterpret_cast<T*>(m_cell); } + T* operator*() const { return static_cast<T*>(m_cell); } + T* operator->() const { return static_cast<T*>(m_cell); } + void clear() { m_cell = 0; } + + JSCell** slot() { return &m_cell; } + + typedef T* (WriteBarrierBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + + bool operator!() const { return !m_cell; } + + void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } + +protected: + JSCell* m_cell; +}; + +template <typename T> class WriteBarrier : public WriteBarrierBase<T> { +public: + WriteBarrier() { this->m_cell = 0; } + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) + { + this->set(globalData, owner, value); + } + +}; + +template <> class WriteBarrierBase<Unknown> { +public: + void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); } + void setWithoutWriteBarrier(JSValue value) { m_value = JSValue::encode(value); } + JSValue get() const { return JSValue::decode(m_value); } + void clear() { m_value = JSValue::encode(JSValue()); } + void setUndefined() { m_value = JSValue::encode(jsUndefined()); } + bool isNumber() const { return get().isNumber(); } + bool isGetterSetter() const { return get().isGetterSetter(); } + + JSValue* slot() + { + union { + EncodedJSValue* v; + JSValue* slot; + } u; + u.v = &m_value; + return u.slot; + } + + typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + bool operator!() const { return !get(); } + +protected: + EncodedJSValue m_value; +}; + +template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> { +public: + WriteBarrier() { m_value = JSValue::encode(JSValue()); } + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value) + { + this->set(globalData, owner, value); + } +}; + +template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) +{ + return lhs.get() == rhs.get(); +} + +template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs) +{ + return lhs.get() == rhs.get(); +} + +} + +#endif // WriteBarrier_h |