diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/JavaScriptCore/runtime | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/JavaScriptCore/runtime')
133 files changed, 1738 insertions, 4797 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 950bb4e..b5aa46b 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -92,7 +92,7 @@ namespace JSC { d->registers = &activation->registerAt(0); } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -143,7 +143,7 @@ namespace JSC { } inline Arguments::Arguments(CallFrame* callFrame) - : JSNonFinalObject(callFrame->lexicalGlobalObject()->argumentsStructure()) + : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) , d(adoptPtr(new ArgumentsData)) { ASSERT(inherits(&s_info)); @@ -185,7 +185,7 @@ namespace JSC { } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) - : JSNonFinalObject(callFrame->lexicalGlobalObject()->argumentsStructure()) + : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) , d(adoptPtr(new ArgumentsData)) { ASSERT(inherits(&s_info)); @@ -247,7 +247,7 @@ namespace JSC { int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize; size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; - OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize); + OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1); WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset; setRegisters(registers, registerArray.release()); } diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index e0f4b23..050e989 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -37,7 +37,7 @@ ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor); static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*); -ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* functionStructure) +ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype, Structure* functionStructure) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className)) { // ECMA 15.4.3.1 Array.prototype @@ -59,7 +59,7 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi uint32_t n = args.at(0).toUInt32(exec); if (n != args.at(0).toNumber(exec)) return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer.")); - return new (exec) JSArray(globalObject->arrayStructure(), n, CreateInitialized); + return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), n, CreateInitialized); } // otherwise the array is constructed with the arguments in it diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h index 5e1408f..97b26c5 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.h +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ArrayConstructor : public InternalFunction { public: - ArrayConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*); + ArrayConstructor(ExecState*, JSGlobalObject*, Structure*, ArrayPrototype*, Structure*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index fdbcd95..29caece 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -114,8 +114,8 @@ const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecStat */ // ECMA 15.4.4 -ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) - : JSArray(structure) +ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure) + : JSArray(globalObject->globalData(), structure) { ASSERT(inherits(&s_info)); putAnonymousValue(globalObject->globalData(), 0, globalObject); @@ -514,10 +514,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { JSValue iObj = thisObj->get(exec, i); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); unsigned themin = i; JSValue minObj = iObj; for (unsigned j = i + 1; j < length; ++j) { JSValue jObj = thisObj->get(exec, j); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); double compareResult; if (jObj.isUndefined()) compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) @@ -570,7 +574,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) deleteCount = static_cast<unsigned>(deleteDouble); } - JSArray* resObj = new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact); + JSArray* resObj = new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact); JSValue result = resObj; JSGlobalData& globalData = exec->globalData(); for (unsigned k = 0; k < deleteCount; k++) @@ -682,20 +686,19 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) } for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValue v = slot.getValue(exec, k); - MarkedArgumentBuffer eachArguments; + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + MarkedArgumentBuffer eachArguments; eachArguments.append(v); eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result.toBoolean(exec)) resultArray->put(exec, filterIndex++, v); } @@ -739,15 +742,19 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) PropertySlot slot(thisObj); if (!thisObj->getPropertySlot(exec, k, slot)) continue; - JSValue v = slot.getValue(exec, k); - MarkedArgumentBuffer eachArguments; + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + MarkedArgumentBuffer eachArguments; eachArguments.append(v); eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); resultArray->put(exec, k, result); } @@ -797,18 +804,18 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) } for (; k < length && !exec->hadException(); ++k) { PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) continue; MarkedArgumentBuffer eachArguments; - eachArguments.append(slot.getValue(exec, k)); eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (!predicateResult) { result = jsBoolean(false); break; @@ -860,6 +867,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + call(exec, function, callType, callData, applyThis, eachArguments); } return JSValue::encode(jsUndefined()); @@ -910,8 +920,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) eachArguments.append(jsNumber(k)); eachArguments.append(thisObj); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (predicateResult) { result = jsBoolean(true); break; @@ -979,6 +991,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) for (; i < length && !exec->hadException(); ++i) { JSValue prop = getProperty(exec, thisObj, i); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); if (!prop) continue; @@ -1051,6 +1065,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) for (; i < length && !exec->hadException(); ++i) { unsigned idx = length - i - 1; JSValue prop = getProperty(exec, thisObj, idx); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); if (!prop) continue; diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index 96641bd..6dadf51 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -28,14 +28,14 @@ namespace JSC { class ArrayPrototype : public JSArray { public: - explicit ArrayPrototype(JSGlobalObject*, NonNullPassRefPtr<Structure>); + explicit ArrayPrototype(JSGlobalObject*, Structure*); bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index 0f6a646..df7b7f6 100644 --- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -39,7 +39,7 @@ namespace JSC { , m_object(object) { if (!m_object->structure()->isDictionary()) - m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure())); + m_object->setStructure(globalData, Structure::toCacheableDictionaryTransition(globalData, m_object->structure())); } ~BatchedTransitionOptimizer() diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index e5b0f3d..a1a4ed4 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -28,7 +28,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor); -BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype) +BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, booleanPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h index 2550b3b..fa0d05e 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.h +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class BooleanConstructor : public InternalFunction { public: - BooleanConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, BooleanPrototype*); + BooleanConstructor(ExecState*, JSGlobalObject*, Structure*, BooleanPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index 2945c0e..e24a30a 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::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0 }; -BooleanObject::BooleanObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure) + : JSWrapperObject(globalData, structure) { ASSERT(inherits(&s_info)); } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index ef2d403..def44b4 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -27,11 +27,11 @@ namespace JSC { class BooleanObject : public JSWrapperObject { public: - explicit BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure>); + explicit BooleanObject(JSGlobalData&, Structure*); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp index d0a64af..20990e1 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -37,7 +37,7 @@ static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*); // ECMA 15.6.4 -BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) +BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure) : BooleanObject(exec->globalData(), structure) { setInternalValue(exec->globalData(), jsBoolean(false)); diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.h b/Source/JavaScriptCore/runtime/BooleanPrototype.h index d6d3d9f..5ccbd2b 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.h +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class BooleanPrototype : public BooleanObject { public: - BooleanPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure); + BooleanPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.cpp b/Source/JavaScriptCore/runtime/ConservativeSet.cpp deleted file mode 100644 index 8872023..0000000 --- a/Source/JavaScriptCore/runtime/ConservativeSet.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 ConservativeRoots::grow() -{ - size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; - JSCell** newRoots = static_cast<JSCell**>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); - memcpy(newRoots, m_roots, m_size * sizeof(JSCell*)); - if (m_roots != m_inlineRoots) - OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); - m_capacity = newCapacity; - m_roots = newRoots; -} - -void ConservativeRoots::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) - add(*it); -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.h b/Source/JavaScriptCore/runtime/ConservativeSet.h deleted file mode 100644 index d078606..0000000 --- a/Source/JavaScriptCore/runtime/ConservativeSet.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 ConservativeRoots_h -#define ConservativeRoots_h - -#include "Heap.h" -#include <wtf/OSAllocator.h> -#include <wtf/Vector.h> - -namespace JSC { - -class JSCell; -class Heap; - -// May contain duplicates. - -class ConservativeRoots { -public: - ConservativeRoots(Heap*); - ~ConservativeRoots(); - - void add(void*); - void add(void* begin, void* end); - - size_t size(); - JSCell** roots(); - -private: - static const size_t inlineCapacity = 128; - static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*); - - void grow(); - - Heap* m_heap; - JSCell** m_roots; - size_t m_size; - size_t m_capacity; - JSCell* m_inlineRoots[inlineCapacity]; -}; - -inline ConservativeRoots::ConservativeRoots(Heap* heap) - : m_heap(heap) - , m_roots(m_inlineRoots) - , m_size(0) - , m_capacity(inlineCapacity) -{ -} - -inline ConservativeRoots::~ConservativeRoots() -{ - if (m_roots != m_inlineRoots) - OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); -} - -inline void ConservativeRoots::add(void* p) -{ - if (!m_heap->contains(p)) - return; - - if (m_size == m_capacity) - grow(); - - m_roots[m_size++] = reinterpret_cast<JSCell*>(p); -} - -inline size_t ConservativeRoots::size() -{ - return m_size; -} - -inline JSCell** ConservativeRoots::roots() -{ - return m_roots; -} - -} // namespace JSC - -#endif // ConservativeRoots_h diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 0a06148..9bbb688 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -57,7 +57,7 @@ static EncodedJSValue JSC_HOST_CALL dateParse(ExecState*); static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*); static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*); -DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure, DatePrototype* datePrototype) +DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure, DatePrototype* datePrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className)) { putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly); diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h index bd529f1..23a0311 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.h +++ b/Source/JavaScriptCore/runtime/DateConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class DateConstructor : public InternalFunction { public: - DateConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure, DatePrototype*); + DateConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure, DatePrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp index 74adda4..d8ca072 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.cpp +++ b/Source/JavaScriptCore/runtime/DateInstance.cpp @@ -34,15 +34,15 @@ namespace JSC { const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0}; -DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +DateInstance::DateInstance(ExecState* exec, Structure* structure) + : JSWrapperObject(exec->globalData(), structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsNaN()); } -DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time) - : JSWrapperObject(structure) +DateInstance::DateInstance(ExecState* exec, Structure* structure, double time) + : JSWrapperObject(exec->globalData(), structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsNumber(timeClip(time))); diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h index d0dcf0b..6195c85 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.h +++ b/Source/JavaScriptCore/runtime/DateInstance.h @@ -31,8 +31,8 @@ namespace JSC { class DateInstance : public JSWrapperObject { public: - DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double); - explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>); + DateInstance(ExecState*, Structure*, double); + explicit DateInstance(ExecState*, Structure*); double internalNumber() const { return internalValue().uncheckedGetNumber(); } @@ -52,7 +52,7 @@ namespace JSC { return calculateGregorianDateTimeUTC(exec); } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 314baa4..444fa98 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -429,7 +429,7 @@ const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecS // ECMA 15.9.4 -DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) +DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) : DateInstance(exec, structure) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/DatePrototype.h b/Source/JavaScriptCore/runtime/DatePrototype.h index 0ebbedc..2e1030d 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.h +++ b/Source/JavaScriptCore/runtime/DatePrototype.h @@ -29,14 +29,14 @@ namespace JSC { class DatePrototype : public DateInstance { public: - DatePrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); + DatePrototype(ExecState*, JSGlobalObject*, Structure*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp index b84f5ea..7eda19f 100644 --- a/Source/JavaScriptCore/runtime/Error.cpp +++ b/Source/JavaScriptCore/runtime/Error.cpp @@ -167,7 +167,7 @@ JSObject* throwSyntaxError(ExecState* exec) class StrictModeTypeErrorFunction : public InternalFunction { public: - StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& message) + StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& message) : InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier) , m_message(message) { diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp index 7f4f82c..df112dd 100644 --- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -29,7 +29,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor); -ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype) +ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ErrorPrototype* errorPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, errorPrototype->classInfo()->className)) { // ECMA 15.11.3.1 Error.prototype diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.h b/Source/JavaScriptCore/runtime/ErrorConstructor.h index 3d0d706..ceec005 100644 --- a/Source/JavaScriptCore/runtime/ErrorConstructor.h +++ b/Source/JavaScriptCore/runtime/ErrorConstructor.h @@ -30,7 +30,7 @@ namespace JSC { class ErrorConstructor : public InternalFunction { public: - ErrorConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ErrorPrototype*); + ErrorConstructor(ExecState*, JSGlobalObject*, Structure*, ErrorPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp index 0db2af8..ed95ba4 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp +++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp @@ -25,28 +25,28 @@ namespace JSC { const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0 }; -ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure) - : JSNonFinalObject(structure) +ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure) + : JSNonFinalObject(*globalData, structure) , m_appendSourceToMessage(false) { ASSERT(inherits(&s_info)); putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, "")); } -ErrorInstance::ErrorInstance(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message) - : JSNonFinalObject(structure) +ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure, const UString& message) + : JSNonFinalObject(*globalData, structure) , m_appendSourceToMessage(false) { ASSERT(inherits(&s_info)); putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message)); } -ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const UString& message) +ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, Structure* structure, const UString& message) { return new (globalData) ErrorInstance(globalData, structure, message); } -ErrorInstance* ErrorInstance::create(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSValue message) +ErrorInstance* ErrorInstance::create(ExecState* exec, Structure* structure, JSValue message) { if (message.isUndefined()) return new (exec) ErrorInstance(&exec->globalData(), structure); diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h index 82dbf0f..afcf158 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.h +++ b/Source/JavaScriptCore/runtime/ErrorInstance.h @@ -29,13 +29,13 @@ namespace JSC { public: static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - static ErrorInstance* create(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&); - static ErrorInstance* create(ExecState* exec, NonNullPassRefPtr<Structure>, JSValue message); + static ErrorInstance* create(JSGlobalData*, Structure*, const UString&); + static ErrorInstance* create(ExecState*, Structure*, JSValue message); bool appendSourceToMessage() { return m_appendSourceToMessage; } @@ -45,8 +45,8 @@ namespace JSC { virtual bool isErrorInstance() const { return true; } protected: - explicit ErrorInstance(JSGlobalData*, NonNullPassRefPtr<Structure>); - explicit ErrorInstance(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&); + explicit ErrorInstance(JSGlobalData*, Structure*); + explicit ErrorInstance(JSGlobalData*, Structure*, const UString&); bool m_appendSourceToMessage; }; diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp index e13251c..a57e947 100644 --- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -35,7 +35,7 @@ ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype); static EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*); // ECMA 15.9.4 -ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) +ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure) : ErrorInstance(&exec->globalData(), structure) { // The constructor will be added later in ErrorConstructor's constructor diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.h b/Source/JavaScriptCore/runtime/ErrorPrototype.h index 3c2fed3..9437d3a 100644 --- a/Source/JavaScriptCore/runtime/ErrorPrototype.h +++ b/Source/JavaScriptCore/runtime/ErrorPrototype.h @@ -29,7 +29,7 @@ namespace JSC { class ErrorPrototype : public ErrorInstance { public: - ErrorPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure); + ErrorPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp index d3c637e..1d74315 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -44,7 +44,7 @@ namespace JSC { class InterruptedExecutionError : public JSNonFinalObject { public: InterruptedExecutionError(JSGlobalData* globalData) - : JSNonFinalObject(globalData->interruptedExecutionErrorStructure) + : JSNonFinalObject(*globalData, globalData->interruptedExecutionErrorStructure.get()) { } @@ -61,7 +61,7 @@ JSObject* createInterruptedExecutionException(JSGlobalData* globalData) class TerminatedExecutionError : public JSNonFinalObject { public: TerminatedExecutionError(JSGlobalData* globalData) - : JSNonFinalObject(globalData->terminatedExecutionErrorStructure) + : JSNonFinalObject(*globalData, globalData->terminatedExecutionErrorStructure.get()) { } diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index a059ed2..fa14ad5 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -40,13 +40,15 @@ namespace JSC { +const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 }; + +const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 }; + NativeExecutable::~NativeExecutable() { } -VPtrHackExecutable::~VPtrHackExecutable() -{ -} +const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0 }; EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext) @@ -57,6 +59,8 @@ EvalExecutable::~EvalExecutable() { } +const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0 }; + ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false) { @@ -66,6 +70,8 @@ ProgramExecutable::~ProgramExecutable() { } +const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0 }; + FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) : ScriptExecutable(globalData->functionExecutableStructure.get(), globalData, source, inStrictContext) , m_numCapturedVariables(0) diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index f15df07..fbe33cf 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -52,8 +52,8 @@ namespace JSC { static const int NUM_PARAMETERS_NOT_COMPILED = -1; public: - ExecutableBase(Structure* structure, int numParameters) - : JSCell(structure) + ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters) + : JSCell(globalData, structure) , m_numParametersForCall(numParameters) , m_numParametersForConstruct(numParameters) { @@ -65,10 +65,11 @@ namespace JSC { return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = 0; + static const ClassInfo s_info; int m_numParametersForCall; int m_numParametersForConstruct; @@ -115,10 +116,12 @@ namespace JSC { NativeFunction function() { return m_function; } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(LeafType, StructureFlags), AnonymousSlotCount, &s_info); } + private: #if ENABLE(JIT) NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor) - : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) + : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -129,7 +132,7 @@ namespace JSC { } #else NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) - : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) + : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -140,22 +143,13 @@ namespace JSC { // Probably should be a NativeConstructor, but this will currently require rewriting the JIT // trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList. NativeFunction m_constructor; - }; - - class VPtrHackExecutable : public ExecutableBase { - public: - VPtrHackExecutable(Structure* structure) - : ExecutableBase(structure, NUM_PARAMETERS_IS_HOST) - { - } - - ~VPtrHackExecutable(); + static const ClassInfo s_info; }; class ScriptExecutable : public ExecutableBase { public: ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) + : ExecutableBase(*globalData, structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -169,7 +163,7 @@ namespace JSC { } ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) + : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -238,10 +232,11 @@ namespace JSC { return generatedJITCodeForCall(); } #endif - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; + static const ClassInfo s_info; EvalExecutable(ExecState*, const SourceCode&, bool); JSObject* compileInternal(ExecState*, ScopeChainNode*); @@ -284,10 +279,11 @@ namespace JSC { } #endif - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; + static const ClassInfo s_info; ProgramExecutable(ExecState*, const SourceCode&); JSObject* compileInternal(ExecState*, ScopeChainNode*); @@ -376,7 +372,7 @@ namespace JSC { void discardCode(); void markChildren(MarkStack&); static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); @@ -386,6 +382,7 @@ namespace JSC { JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; + static const ClassInfo s_info; unsigned m_numCapturedVariables : 31; bool m_forceUsesArguments : 1; diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index a9f0a06..9e7d8d5 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -37,7 +37,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor); -FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) +FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h index 7f21b20..31a04c9 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.h +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class FunctionConstructor : public InternalFunction { public: - FunctionConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, FunctionPrototype*); + FunctionConstructor(ExecState*, JSGlobalObject*, Structure*, FunctionPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index c2d8ad3..e2a4941 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -37,7 +37,7 @@ static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*); static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*); static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*); -FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) +FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) : InternalFunction(&exec->globalData(), globalObject, structure, exec->propertyNames().nullIdentifier) { putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum); diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.h b/Source/JavaScriptCore/runtime/FunctionPrototype.h index 447f00b..ab708dd 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.h +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.h @@ -27,10 +27,10 @@ namespace JSC { class FunctionPrototype : public InternalFunction { public: - FunctionPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); + FunctionPrototype(ExecState*, JSGlobalObject*, Structure*); void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h index 8241275..a222c7a 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.h +++ b/Source/JavaScriptCore/runtime/GetterSetter.h @@ -26,6 +26,7 @@ #include "JSCell.h" #include "CallFrame.h" +#include "Structure.h" namespace JSC { @@ -37,7 +38,7 @@ namespace JSC { friend class JIT; public: GetterSetter(ExecState* exec) - : JSCell(exec->globalData().getterSetterStructure.get()) + : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get()) { } @@ -47,7 +48,7 @@ namespace JSC { 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(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0); } diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp deleted file mode 100644 index e3ef8bb..0000000 --- a/Source/JavaScriptCore/runtime/Heap.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * 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 - * - */ - -#include "config.h" -#include "Heap.h" - -#include "CodeBlock.h" -#include "ConservativeSet.h" -#include "GCActivityCallback.h" -#include "Interpreter.h" -#include "JSGlobalData.h" -#include "JSGlobalObject.h" -#include "JSLock.h" -#include "JSONObject.h" -#include "Tracing.h" -#include <algorithm> - -#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0 - -using namespace std; - -namespace JSC { - -const size_t minBytesPerCycle = 512 * 1024; - -Heap::Heap(JSGlobalData* globalData) - : m_operationInProgress(NoOperation) - , m_markedSpace(globalData) - , m_markListSet(0) - , m_activityCallback(DefaultGCActivityCallback::create(this)) - , m_globalData(globalData) - , m_machineThreads(this) - , m_markStack(globalData->jsArrayVPtr) - , m_handleHeap(globalData) - , m_extraCost(0) -{ - m_markedSpace.setHighWaterMark(minBytesPerCycle); - (*m_activityCallback)(); -} - -Heap::~Heap() -{ - // The destroy function must already have been called, so assert this. - ASSERT(!m_globalData); -} - -void Heap::destroy() -{ - JSLock lock(SilenceAssertionsOnly); - - if (!m_globalData) - return; - - ASSERT(!m_globalData->dynamicGlobalObject); - ASSERT(m_operationInProgress == NoOperation); - - // The global object is not GC protected at this point, so sweeping may delete it - // (and thus the global data) before other objects that may use the global data. - RefPtr<JSGlobalData> protect(m_globalData); - -#if ENABLE(JIT) - m_globalData->jitStubs->clearHostFunctionStubs(); -#endif - - delete m_markListSet; - m_markListSet = 0; - m_markedSpace.clearMarks(); - m_handleHeap.clearWeakPointers(); - m_markedSpace.destroy(); - - m_globalData = 0; -} - -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 - // that hold on to a great deal of memory that's not in the form of other JS values, - // that is not good enough - in some cases a lot of those objects can pile up and - // use crazy amounts of memory without a GC happening. So we track these extra - // memory costs. Only unusually large objects are noted, and we only keep track - // of this extra cost until the next GC. In garbage collected languages, most values - // are either very short lived temporaries, or have extremely long lifetimes. So - // 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.highWaterMark() / 2) - collectAllGarbage(); - m_extraCost += cost; -} - -void* Heap::allocateSlowCase(size_t bytes) -{ - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - ASSERT(JSLock::lockCount() > 0); - ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT(bytes <= MarkedSpace::maxCellSize); - ASSERT(m_operationInProgress == NoOperation); - -#if COLLECT_ON_EVERY_SLOW_ALLOCATION - collectAllGarbage(); - ASSERT(m_operationInProgress == NoOperation); -#endif - - reset(DoNotSweep); - - m_operationInProgress = Allocation; - void* result = m_markedSpace.allocate(bytes); - m_operationInProgress = NoOperation; - - ASSERT(result); - return result; -} - -void Heap::protect(JSValue k) -{ - ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); - - if (!k.isCell()) - return; - - m_protectedValues.add(k.asCell()); -} - -bool Heap::unprotect(JSValue k) -{ - ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); - - if (!k.isCell()) - return false; - - return m_protectedValues.remove(k.asCell()); -} - -void Heap::markProtectedObjects(HeapRootMarker& heapRootMarker) -{ - ProtectCountSet::iterator end = m_protectedValues.end(); - for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - heapRootMarker.mark(&it->first); -} - -void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) -{ - m_tempSortingVectors.append(tempVector); -} - -void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) -{ - ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last()); - m_tempSortingVectors.removeLast(); -} - -void Heap::markTempSortVectors(HeapRootMarker& heapRootMarker) -{ - typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; - - VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end(); - for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) { - Vector<ValueStringPair>* tempSortingVector = *it; - - Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); - for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) { - if (vectorIt->first) - heapRootMarker.mark(&vectorIt->first); - } - } -} - -inline RegisterFile& Heap::registerFile() -{ - return m_globalData->interpreter->registerFile(); -} - -void Heap::markRoots() -{ -#ifndef NDEBUG - if (m_globalData->isSharedInstance()) { - ASSERT(JSLock::lockCount() > 0); - ASSERT(JSLock::currentThreadIsHoldingLock()); - } -#endif - - void* dummy; - - ASSERT(m_operationInProgress == NoOperation); - if (m_operationInProgress != NoOperation) - CRASH(); - - m_operationInProgress = Collection; - - MarkStack& markStack = m_markStack; - HeapRootMarker heapRootMarker(markStack); - - // We gather conservative roots before clearing mark bits because - // conservative gathering uses the mark bits from our last mark pass to - // determine whether a reference is valid. - ConservativeRoots machineThreadRoots(this); - m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy); - - ConservativeRoots registerFileRoots(this); - registerFile().gatherConservativeRoots(registerFileRoots); - - m_markedSpace.clearMarks(); - - markStack.append(machineThreadRoots); - markStack.drain(); - - markStack.append(registerFileRoots); - markStack.drain(); - - markProtectedObjects(heapRootMarker); - markStack.drain(); - - markTempSortVectors(heapRootMarker); - markStack.drain(); - - if (m_markListSet && m_markListSet->size()) - MarkedArgumentBuffer::markLists(heapRootMarker, *m_markListSet); - if (m_globalData->exception) - heapRootMarker.mark(&m_globalData->exception); - markStack.drain(); - - m_handleHeap.markStrongHandles(heapRootMarker); - m_handleStack.mark(heapRootMarker); - - // Mark the small strings cache last, since it will clear itself if nothing - // else has marked it. - m_globalData->smallStrings.markChildren(heapRootMarker); - - markStack.drain(); - markStack.compact(); - - m_handleHeap.updateAfterMark(); - - m_operationInProgress = NoOperation; -} - -size_t Heap::objectCount() const -{ - return m_markedSpace.objectCount(); -} - -size_t Heap::size() const -{ - return m_markedSpace.size(); -} - -size_t Heap::capacity() const -{ - return m_markedSpace.capacity(); -} - -size_t Heap::globalObjectCount() -{ - return m_globalData->globalObjectCount; -} - -size_t Heap::protectedGlobalObjectCount() -{ - size_t count = m_handleHeap.protectedGlobalObjectCount(); - - ProtectCountSet::iterator end = m_protectedValues.end(); - for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) { - if (it->first->isObject() && asObject(it->first)->isGlobalObject()) - count++; - } - - return count; -} - -size_t Heap::protectedObjectCount() -{ - return m_protectedValues.size(); -} - -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"; - if (cell->isGetterSetter()) - return "Getter-Setter"; - if (cell->isAPIValueWrapper()) - return "API wrapper"; - if (cell->isPropertyNameIterator()) - return "For-in iterator"; - if (!cell->isObject()) - return "[empty cell]"; - const ClassInfo* info = cell->classInfo(); - return info ? info->className : "Object"; -} - -inline void TypeCounter::operator()(JSCell* cell) -{ - m_typeCountSet->add(typeName(cell)); -} - -inline PassOwnPtr<TypeCountSet> TypeCounter::take() -{ - return m_typeCountSet.release(); -} - -PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts() -{ - TypeCounter typeCounter; - - ProtectCountSet::iterator end = m_protectedValues.end(); - for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - typeCounter(it->first); - - return typeCounter.take(); -} - -PassOwnPtr<TypeCountSet> Heap::objectTypeCounts() -{ - TypeCounter typeCounter; - forEach(typeCounter); - return typeCounter.take(); -} - -bool Heap::isBusy() -{ - return m_operationInProgress != NoOperation; -} - -void Heap::collectAllGarbage() -{ - reset(DoSweep); -} - -void Heap::reset(SweepToggle sweepToggle) -{ - ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); - JAVASCRIPTCORE_GC_BEGIN(); - - markRoots(); - - JAVASCRIPTCORE_GC_MARKED(); - - m_markedSpace.reset(); - m_extraCost = 0; - -#if ENABLE(JSC_ZOMBIES) - sweepToggle = DoSweep; -#endif - - if (sweepToggle == DoSweep) { - m_markedSpace.sweep(); - m_markedSpace.shrink(); - } - - // To avoid pathological GC churn in large heaps, we set the allocation high - // water mark to be proportional to the current size of the heap. The exact - // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : - // new bytes allocated) proportion, and seems to work well in benchmarks. - size_t proportionalBytes = 2 * m_markedSpace.size(); - m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle)); - - JAVASCRIPTCORE_GC_END(); - - (*m_activityCallback)(); -} - -void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) -{ - m_activityCallback = activityCallback; -} - -GCActivityCallback* Heap::activityCallback() -{ - return m_activityCallback.get(); -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h deleted file mode 100644 index c2d3bac..0000000 --- a/Source/JavaScriptCore/runtime/Heap.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 Heap_h -#define Heap_h - -#include "HandleHeap.h" -#include "HandleStack.h" -#include "MarkStack.h" -#include "MarkedSpace.h" -#include <wtf/Forward.h> -#include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> - -namespace JSC { - - class GCActivityCallback; - class GlobalCodeBlock; - class HeapRootMarker; - class JSCell; - class JSGlobalData; - class JSValue; - class LiveObjectIterator; - 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: - static Heap* heap(JSValue); // 0 for immediate values - static Heap* heap(JSCell*); - - 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(). - - JSGlobalData* globalData() const { return m_globalData; } - MarkedSpace& markedSpace() { return m_markedSpace; } - MachineThreads& machineThreads() { return m_machineThreads; } - - GCActivityCallback* activityCallback(); - void setActivityCallback(PassOwnPtr<GCActivityCallback>); - - bool isBusy(); // true if an allocation or collection is in progress - void* allocate(size_t); - void collectAllGarbage(); - - void reportExtraMemoryCost(size_t cost); - - void protect(JSValue); - bool unprotect(JSValue); // True when the protect count drops to 0. - - bool contains(void*); - - size_t size() const; - size_t capacity() const; - size_t objectCount() const; - size_t globalObjectCount(); - size_t protectedObjectCount(); - size_t protectedGlobalObjectCount(); - PassOwnPtr<TypeCountSet> protectedObjectTypeCounts(); - PassOwnPtr<TypeCountSet> objectTypeCounts(); - - void pushTempSortVector(Vector<ValueStringPair>*); - void popTempSortVector(Vector<ValueStringPair>*); - - HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } - - template <typename Functor> void forEach(Functor&); - - HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); } - HandleSlot allocateLocalHandle() { return m_handleStack.push(); } - - HandleStack* handleStack() { return &m_handleStack; } - - private: - friend class JSGlobalData; - - static const size_t minExtraCost = 256; - static const size_t maxExtraCost = 1024 * 1024; - - void* allocateSlowCase(size_t); - void reportExtraMemoryCostSlowCase(size_t); - - void markRoots(); - void markProtectedObjects(HeapRootMarker&); - void markTempSortVectors(HeapRootMarker&); - - enum SweepToggle { DoNotSweep, DoSweep }; - void reset(SweepToggle); - - RegisterFile& registerFile(); - - OperationInProgress m_operationInProgress; - MarkedSpace m_markedSpace; - - ProtectCountSet m_protectedValues; - Vector<Vector<ValueStringPair>* > m_tempSortingVectors; - - HashSet<MarkedArgumentBuffer*>* m_markListSet; - - OwnPtr<GCActivityCallback> m_activityCallback; - - JSGlobalData* m_globalData; - - MachineThreads m_machineThreads; - MarkStack m_markStack; - HandleHeap m_handleHeap; - HandleStack m_handleStack; - - size_t m_extraCost; - }; - - inline bool Heap::isMarked(const JSCell* cell) - { - return MarkedSpace::isMarked(cell); - } - - inline bool Heap::testAndSetMarked(const JSCell* cell) - { - return MarkedSpace::testAndSetMarked(cell); - } - - inline void Heap::setMarked(JSCell* 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) - reportExtraMemoryCostSlowCase(cost); - } - - template <typename Functor> inline void Heap::forEach(Functor& functor) - { - m_markedSpace.forEach(functor); - } - -} // namespace JSC - -#endif // Heap_h diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp index aef60c8..27611b7 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp @@ -59,7 +59,6 @@ static void initializeThreadingOnce() s_dtoaP5Mutex = new Mutex; initializeDates(); RegisterFile::initializeThreading(); - Structure::initializeThreading(); #endif } diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp index 27106a1..c3b07f8 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.cpp +++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp @@ -36,13 +36,12 @@ ASSERT_CLASS_FITS_IN_CELL(InternalFunction); const ClassInfo InternalFunction::s_info = { "Function", &JSObjectWithGlobalObject::s_info, 0, 0 }; -InternalFunction::InternalFunction(NonNullPassRefPtr<Structure> structure) - : JSObjectWithGlobalObject(structure) +InternalFunction::InternalFunction(VPtrStealingHackType) + : JSObjectWithGlobalObject(VPtrStealingHack) { - ASSERT(inherits(&s_info)); } -InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const Identifier& name) +InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, Structure* structure, const Identifier& name) : JSObjectWithGlobalObject(globalObject, structure) { ASSERT(inherits(&s_info)); @@ -51,12 +50,12 @@ InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* glo const UString& InternalFunction::name(ExecState* exec) { - return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue(); + return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue(); } const UString InternalFunction::displayName(ExecState* exec) { - JSValue displayName = getDirect(exec->globalData().propertyNames->displayName); + JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName); if (displayName && isJSString(&exec->globalData(), displayName)) return asString(displayName)->tryGetValue(); diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h index 08c98a5..28e260e 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.h +++ b/Source/JavaScriptCore/runtime/InternalFunction.h @@ -39,7 +39,7 @@ namespace JSC { const UString displayName(ExecState*); const UString calculatedDisplayName(ExecState*); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -48,9 +48,9 @@ namespace JSC { static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags; // Only used to allow us to determine the JSFunction vptr - InternalFunction(NonNullPassRefPtr<Structure> structure); + InternalFunction(VPtrStealingHackType); - InternalFunction(JSGlobalData*, JSGlobalObject*, NonNullPassRefPtr<Structure>, const Identifier&); + InternalFunction(JSGlobalData*, JSGlobalObject*, Structure*, const Identifier&); private: virtual CallType getCallData(CallData&) = 0; diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h index 54fe909..0165488 100644 --- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -25,6 +25,7 @@ #include "JSCell.h" #include "CallFrame.h" +#include "Structure.h" namespace JSC { @@ -35,7 +36,7 @@ namespace JSC { virtual bool isAPIValueWrapper() const { return true; } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0); } @@ -43,7 +44,7 @@ namespace JSC { private: JSAPIValueWrapper(ExecState* exec, JSValue value) - : JSCell(exec->globalData().apiWrapperStructure.get()) + : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get()) { m_value.set(exec->globalData(), this, value); ASSERT(!value.isCell()); diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index d0c50dd..4e36641 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -40,7 +40,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 }; JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable) - : Base(callFrame->globalData().activationStructure, functionExecutable->symbolTable(), callFrame->registers()) + : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers()) , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount())) , m_numCapturedVars(functionExecutable->capturedVariableCount()) , m_requiresDynamicChecks(functionExecutable->usesEval()) @@ -142,7 +142,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert if (symbolTableGet(propertyName, slot)) return true; - if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) { + if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) { slot.setValue(location->get()); return true; } diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 7463f47..65642f1 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -66,7 +66,7 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 1d621fe..bf61097 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -127,26 +127,12 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif JSArray::JSArray(VPtrStealingHackType) - : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) + : JSNonFinalObject(VPtrStealingHack) { - ASSERT(inherits(&s_info)); - - unsigned initialCapacity = 0; - - m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity))); - m_storage->m_allocBase = m_storage; - m_indexBias = 0; - m_vectorLength = initialCapacity; - - checkConsistency(); - - // It's not safe to call Heap::heap(this) in order to report extra memory - // cost here, because the VPtrStealingHackType JSArray is not allocated on - // the heap. For the same reason, it's OK not to report extra cost. } -JSArray::JSArray(NonNullPassRefPtr<Structure> structure) - : JSNonFinalObject(structure) +JSArray::JSArray(JSGlobalData& globalData, Structure* structure) + : JSNonFinalObject(globalData, structure) { ASSERT(inherits(&s_info)); @@ -162,8 +148,8 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure) Heap::heap(this)->reportExtraMemoryCost(storageSize(0)); } -JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, ArrayCreationMode creationMode) - : JSNonFinalObject(structure) +JSArray::JSArray(JSGlobalData& globalData, Structure* structure, unsigned initialLength, ArrayCreationMode creationMode) + : JSNonFinalObject(globalData, structure) { ASSERT(inherits(&s_info)); @@ -204,8 +190,8 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity)); } -JSArray::JSArray(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, const ArgList& list) - : JSNonFinalObject(structure) +JSArray::JSArray(JSGlobalData& globalData, Structure* structure, const ArgList& list) + : JSNonFinalObject(globalData, structure) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index 1a6eba8..8be8513 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -61,12 +61,11 @@ namespace JSC { friend class Walker; public: - enum VPtrStealingHackType { VPtrStealingHack }; JSArray(VPtrStealingHackType); - explicit JSArray(NonNullPassRefPtr<Structure>); - JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength, ArrayCreationMode); - JSArray(JSGlobalData&, NonNullPassRefPtr<Structure>, const ArgList& initialValues); + explicit JSArray(JSGlobalData&, Structure*); + JSArray(JSGlobalData&, Structure*, unsigned initialLength, ArrayCreationMode); + JSArray(JSGlobalData&, Structure*, const ArgList& initialValues); virtual ~JSArray(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -124,7 +123,7 @@ namespace JSC { void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToRegisters(ExecState*, Register*, uint32_t); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp index fbaea1d..c2abaee 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp @@ -35,8 +35,8 @@ namespace JSC { const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", &Base::s_info, 0, 0 }; -JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage) - : JSNonFinalObject(structure) +JSByteArray::JSByteArray(ExecState* exec, Structure* structure, ByteArray* storage) + : JSNonFinalObject(exec->globalData(), structure) , m_storage(storage) { putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete); @@ -50,7 +50,7 @@ JSByteArray::~JSByteArray() #endif -PassRefPtr<Structure> JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo) +Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo); } diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h index e674958..c481bb4 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ b/Source/JavaScriptCore/runtime/JSByteArray.h @@ -75,8 +75,8 @@ namespace JSC { setIndex(i, byteValue); } - JSByteArray(ExecState*, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage); - static PassRefPtr<Structure> createStructure(JSGlobalData&, JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo); + JSByteArray(ExecState*, Structure*, WTF::ByteArray* storage); + static Structure* createStructure(JSGlobalData&, JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); @@ -100,9 +100,8 @@ namespace JSC { static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; private: - enum VPtrStealingHackType { VPtrStealingHack }; JSByteArray(VPtrStealingHackType) - : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) + : JSNonFinalObject(VPtrStealingHack) { } diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index ce7fe22..afd8450 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -209,4 +209,14 @@ JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const return 0; } +bool isZombie(const JSCell* cell) +{ +#if ENABLE(JSC_ZOMBIES) + return cell && cell->isZombie(); +#else + UNUSED_PARAM(cell); + return false; +#endif +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index ab0e237..7ee871c 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -24,18 +24,18 @@ #define JSCell_h #include "CallData.h" +#include "CallFrame.h" #include "ConstructData.h" #include "Heap.h" -#include "JSImmediate.h" #include "JSLock.h" -#include "JSValue.h" +#include "JSValueInlineMethods.h" #include "MarkStack.h" -#include "Structure.h" #include <wtf/Noncopyable.h> namespace JSC { class JSGlobalObject; + class Structure; #if COMPILER(MSVC) // If WTF_MAKE_NONCOPYABLE is applied to JSCell we end up with a bunch of @@ -68,17 +68,19 @@ namespace JSC { friend class MarkedSpace; friend class MarkedBlock; friend class ScopeChainNode; + friend class Structure; friend class StructureChain; + protected: + enum VPtrStealingHackType { VPtrStealingHack }; + private: - explicit JSCell(Structure*); + explicit JSCell(VPtrStealingHackType) { } + JSCell(JSGlobalData&, Structure*); virtual ~JSCell(); public: - static PassRefPtr<Structure> createDummyStructure(JSGlobalData& globalData) - { - return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); - } + static Structure* createDummyStructure(JSGlobalData&); // Querying the type. bool isString() const; @@ -122,7 +124,7 @@ namespace JSC { #endif // Object operations, with the toObject operation included. - const ClassInfo* classInfo() const { return m_structure->classInfo(); } + const ClassInfo* classInfo() const; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); virtual bool deleteProperty(ExecState*, const Identifier& propertyName); @@ -144,7 +146,7 @@ namespace JSC { return OBJECT_OFFSETOF(JSCell, m_structure); } - Structure* const * addressOfStructure() const + const void* addressOfStructure() const { return &m_structure; } @@ -157,35 +159,28 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - Structure* m_structure; + WriteBarrier<Structure> m_structure; }; - inline JSCell::JSCell(Structure* structure) - : m_structure(structure) + inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure) + : m_structure(globalData, this, structure) { + // Very first set of allocations won't have a real structure. + ASSERT(m_structure || !globalData.dummyMarkableCellStructure); } inline JSCell::~JSCell() { } - inline bool JSCell::isObject() const - { - return m_structure->typeInfo().type() == ObjectType; - } - - inline bool JSCell::isString() const - { - return m_structure->typeInfo().type() == StringType; - } - inline Structure* JSCell::structure() const { - return m_structure; + return m_structure.get(); } - inline void JSCell::markChildren(MarkStack&) + inline void JSCell::markChildren(MarkStack& markStack) { + markStack.append(&m_structure); } // --- JSValue inlines ---------------------------- @@ -254,14 +249,6 @@ namespace JSC { return false; } -#if USE(JSVALUE64) - ALWAYS_INLINE JSCell* JSValue::asCell() const - { - ASSERT(isCell()); - return m_ptr; - } -#endif // USE(JSVALUE64) - inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue(); @@ -321,13 +308,6 @@ namespace JSC { return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0. } - inline bool JSValue::needsThisConversion() const - { - if (UNLIKELY(!isCell())) - return true; - return asCell()->structure()->typeInfo().needsThisConversion(); - } - inline JSValue JSValue::getJSNumber() { if (isInt32() || isDouble()) @@ -351,16 +331,6 @@ namespace JSC { { return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); } - - ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) - { - ASSERT(!m_isCheckingForDefaultMarkViolation); - ASSERT(cell); - if (Heap::testAndSetMarked(cell)) - return; - if (cell->structure()->typeInfo().type() >= CompoundType) - m_values.append(cell); - } inline Heap* Heap::heap(JSValue v) { @@ -377,7 +347,7 @@ namespace JSC { #if ENABLE(JSC_ZOMBIES) inline bool JSValue::isZombie() const { - return isCell() && asCell() && asCell()->isZombie(); + return isCell() && asCell() > (JSCell*)0x1ffffffffL && asCell()->isZombie(); } #endif diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index dbfc606..a18e973 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -56,14 +56,12 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure, VPtrHackExecutable* executable) - : Base(structure) +JSFunction::JSFunction(VPtrStealingHackType) + : Base(VPtrStealingHack) { - ASSERT(inherits(&s_info)); - m_executable.setWithoutWriteBarrier(executable); } -JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk) +JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeExecutable* thunk) : Base(globalObject, structure) , m_executable(exec->globalData(), this, thunk) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) @@ -73,7 +71,7 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } -JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) +JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeFunction func) : Base(globalObject, structure) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { @@ -112,12 +110,12 @@ static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescrip const UString& JSFunction::name(ExecState* exec) { - return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue(); + return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue(); } const UString JSFunction::displayName(ExecState* exec) { - JSValue displayName = getDirect(exec->globalData().propertyNames->displayName); + JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName); if (displayName && isJSString(&exec->globalData(), displayName)) return asString(displayName)->tryGetValue(); @@ -186,13 +184,13 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); if (propertyName == exec->propertyNames().prototype) { - WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName); + WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName); if (!location) { JSObject* prototype = constructEmptyObject(exec, scope()->globalObject->emptyObjectStructure()); prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, this, DontEnum); putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum); - location = getDirectLocation(propertyName); + location = getDirectLocation(exec->globalData(), propertyName); } slot.setValue(this, location->get(), offsetForLocation(location)); diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 505b9de..174cd38 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -45,8 +45,8 @@ namespace JSC { typedef JSObjectWithGlobalObject Base; public: - JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); - JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*); + JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeFunction); + JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeExecutable*); JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); virtual ~JSFunction(); @@ -73,7 +73,7 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -87,7 +87,7 @@ namespace JSC { const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; private: - JSFunction(NonNullPassRefPtr<Structure>, VPtrHackExecutable*); + explicit JSFunction(VPtrStealingHackType); bool isHostFunctionNonInline() const; diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index ee1829b..d9e5df0 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -45,6 +45,7 @@ #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" #include "JSStaticScopeObject.h" +#include "JSZombie.h" #include "Lexer.h" #include "Lookup.h" #include "Nodes.h" @@ -106,6 +107,15 @@ void* JSGlobalData::jsByteArrayVPtr; void* JSGlobalData::jsStringVPtr; void* JSGlobalData::jsFunctionVPtr; +#if COMPILER(GCC) +// Work around for gcc trying to coalesce our reads of the various cell vptrs +#define CLOBBER_MEMORY() do { \ + asm volatile ("" : : : "memory"); \ +} while (false) +#else +#define CLOBBER_MEMORY() do { } while (false) +#endif + void JSGlobalData::storeVPtrs() { // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction. @@ -114,27 +124,23 @@ void JSGlobalData::storeVPtrs() COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage); JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack); + CLOBBER_MEMORY(); JSGlobalData::jsArrayVPtr = jsArray->vptr(); - jsArray->~JSCell(); COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage); JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); + CLOBBER_MEMORY(); JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr(); - jsByteArray->~JSCell(); COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage); JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); + CLOBBER_MEMORY(); JSGlobalData::jsStringVPtr = jsString->vptr(); - jsString->~JSCell(); COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage); - char executableStorage[sizeof(VPtrHackExecutable)]; - RefPtr<Structure> executableStructure = Structure::create(Structure::VPtrStealingHack, 0); - JSCell* executable = new (executableStorage) VPtrHackExecutable(executableStructure.get()); - JSCell* jsFunction = new (storage) JSFunction(Structure::create(Structure::VPtrStealingHack, &JSFunction::s_info), static_cast<VPtrHackExecutable*>(executable)); + JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack); + CLOBBER_MEMORY(); JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); - executable->~JSCell(); - jsFunction->~JSCell(); } JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType) @@ -168,28 +174,39 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , exclusiveThread(0) #endif { - activationStructure = JSActivation::createStructure(*this, jsNull()); - interruptedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); - terminatedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); - staticScopeStructure = JSStaticScopeObject::createStructure(*this, jsNull()); - strictEvalActivationStructure = StrictEvalActivation::createStructure(*this, jsNull()); - stringStructure = JSString::createStructure(*this, jsNull()); - notAnObjectStructure = JSNotAnObject::createStructure(*this, jsNull()); - propertyNameIteratorStructure = JSPropertyNameIterator::createStructure(*this, jsNull()); - getterSetterStructure = GetterSetter::createStructure(*this, jsNull()); - apiWrapperStructure = JSAPIValueWrapper::createStructure(*this, jsNull()); - scopeChainNodeStructure = ScopeChainNode::createStructure(*this, jsNull()); - executableStructure = ExecutableBase::createStructure(*this, jsNull()); - evalExecutableStructure = EvalExecutable::createStructure(*this, jsNull()); - programExecutableStructure = ProgramExecutable::createStructure(*this, jsNull()); - functionExecutableStructure = FunctionExecutable::createStructure(*this, jsNull()); - dummyMarkableCellStructure = JSCell::createDummyStructure(*this); - structureChainStructure = StructureChain::createStructure(*this, jsNull()); - interpreter = new Interpreter(*this); if (globalDataType == Default) m_stack = wtfThreadData().stack(); + // Need to be careful to keep everything consistent here + IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); + JSLock lock(SilenceAssertionsOnly); + structureStructure.set(*this, Structure::createStructure(*this)); + activationStructure.set(*this, JSActivation::createStructure(*this, jsNull())); + interruptedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull())); + terminatedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull())); + staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, jsNull())); + strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, jsNull())); + stringStructure.set(*this, JSString::createStructure(*this, jsNull())); + notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, jsNull())); + propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, jsNull())); + getterSetterStructure.set(*this, GetterSetter::createStructure(*this, jsNull())); + apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, jsNull())); + scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, jsNull())); + executableStructure.set(*this, ExecutableBase::createStructure(*this, jsNull())); + nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, jsNull())); + evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, jsNull())); + programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, jsNull())); + functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, jsNull())); + dummyMarkableCellStructure.set(*this, JSCell::createDummyStructure(*this)); + structureChainStructure.set(*this, StructureChain::createStructure(*this, jsNull())); + +#if ENABLE(JSC_ZOMBIES) + zombieStructure.set(*this, JSZombie::createStructure(*this, jsNull())); +#endif + + wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); + #if PLATFORM(MAC) startProfilerServerIfNeeded(); #endif @@ -221,6 +238,33 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread #endif } +void JSGlobalData::clearBuiltinStructures() +{ + structureStructure.clear(); + activationStructure.clear(); + interruptedExecutionErrorStructure.clear(); + terminatedExecutionErrorStructure.clear(); + staticScopeStructure.clear(); + strictEvalActivationStructure.clear(); + stringStructure.clear(); + notAnObjectStructure.clear(); + propertyNameIteratorStructure.clear(); + getterSetterStructure.clear(); + apiWrapperStructure.clear(); + scopeChainNodeStructure.clear(); + executableStructure.clear(); + nativeExecutableStructure.clear(); + evalExecutableStructure.clear(); + programExecutableStructure.clear(); + functionExecutableStructure.clear(); + dummyMarkableCellStructure.clear(); + structureChainStructure.clear(); + +#if ENABLE(JSC_ZOMBIES) + zombieStructure.clear(); +#endif +} + JSGlobalData::~JSGlobalData() { // By the time this is destroyed, heap.destroy() must already have been called. @@ -281,10 +325,7 @@ PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type) PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type) { - Structure::startIgnoringLeaks(); - RefPtr<JSGlobalData> data = create(type); - Structure::stopIgnoringLeaks(); - return data.release(); + return create(type); } bool JSGlobalData::sharedInstanceExists() diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 34ea75d..f1085af 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -33,6 +33,7 @@ #include "Heap.h" #include "DateInstanceCache.h" #include "ExecutableAllocator.h" +#include "Strong.h" #include "JITStubs.h" #include "JSValue.h" #include "NumericStrings.h" @@ -145,23 +146,29 @@ namespace JSC { const HashTable* regExpConstructorTable; const HashTable* stringTable; - RefPtr<Structure> activationStructure; - RefPtr<Structure> interruptedExecutionErrorStructure; - RefPtr<Structure> terminatedExecutionErrorStructure; - RefPtr<Structure> staticScopeStructure; - RefPtr<Structure> strictEvalActivationStructure; - RefPtr<Structure> stringStructure; - RefPtr<Structure> notAnObjectStructure; - RefPtr<Structure> propertyNameIteratorStructure; - RefPtr<Structure> getterSetterStructure; - RefPtr<Structure> apiWrapperStructure; - RefPtr<Structure> scopeChainNodeStructure; - RefPtr<Structure> executableStructure; - RefPtr<Structure> evalExecutableStructure; - RefPtr<Structure> programExecutableStructure; - RefPtr<Structure> functionExecutableStructure; - RefPtr<Structure> dummyMarkableCellStructure; - RefPtr<Structure> structureChainStructure; + Strong<Structure> structureStructure; + Strong<Structure> activationStructure; + Strong<Structure> interruptedExecutionErrorStructure; + Strong<Structure> terminatedExecutionErrorStructure; + Strong<Structure> staticScopeStructure; + Strong<Structure> strictEvalActivationStructure; + Strong<Structure> stringStructure; + Strong<Structure> notAnObjectStructure; + Strong<Structure> propertyNameIteratorStructure; + Strong<Structure> getterSetterStructure; + Strong<Structure> apiWrapperStructure; + Strong<Structure> scopeChainNodeStructure; + Strong<Structure> executableStructure; + Strong<Structure> nativeExecutableStructure; + Strong<Structure> evalExecutableStructure; + Strong<Structure> programExecutableStructure; + Strong<Structure> functionExecutableStructure; + Strong<Structure> dummyMarkableCellStructure; + Strong<Structure> structureChainStructure; + +#if ENABLE(JSC_ZOMBIES) + Strong<Structure> zombieStructure; +#endif static void storeVPtrs(); static JS_EXPORTDATA void* jsArrayVPtr; @@ -260,6 +267,7 @@ namespace JSC { void dumpRegExpTrace(); HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); } HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); } + void clearBuiltinStructures(); private: JSGlobalData(GlobalDataType, ThreadStackType); @@ -271,6 +279,11 @@ namespace JSC { StackBounds m_stack; }; + inline HandleSlot allocateGlobalHandle(JSGlobalData& globalData) + { + return globalData.allocateGlobalHandle(); + } + } // namespace JSC #endif // JSGlobalData_h diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index a2bbfbd..b82949a 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -84,14 +84,6 @@ template <typename T> static inline void markIfNeeded(MarkStack& markStack, Writ markStack.append(v); } -static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s) -{ - if (s && s->storedPrototype()) - markStack.append(s->storedPrototypeSlot()); - if (s && *s->cachedPrototypeChainSlot()) - markStack.append(s->cachedPrototypeChainSlot()); -} - JSGlobalObject::~JSGlobalObject() { ASSERT(JSLock::currentThreadIsHoldingLock()); @@ -139,11 +131,11 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes)) return; - JSValue valueBefore = getDirect(propertyName); + JSValue valueBefore = getDirect(exec->globalData(), propertyName); PutPropertySlot slot; JSVariableObject::put(exec, propertyName, value, slot); if (!valueBefore) { - JSValue valueAfter = getDirect(propertyName); + JSValue valueAfter = getDirect(exec->globalData(), propertyName); if (valueAfter) JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes); } @@ -178,46 +170,46 @@ void JSGlobalObject::reset(JSValue prototype) // Prototypes m_functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(exec->globalData(), jsNull()))); // The real prototype will be set once ObjectPrototype is created. - m_functionStructure = JSFunction::createStructure(exec->globalData(), m_functionPrototype.get()); - m_internalFunctionStructure = InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get()); + m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), m_functionPrototype.get())); + m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get())); JSFunction* callFunction = 0; JSFunction* applyFunction = 0; m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction); m_callFunction.set(exec->globalData(), this, callFunction); m_applyFunction.set(exec->globalData(), this, applyFunction); m_objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(exec->globalData(), jsNull()), m_functionStructure.get())); - m_functionPrototype->structure()->setPrototypeWithoutTransition(m_objectPrototype.get()); + m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get()); - m_emptyObjectStructure = m_objectPrototype->inheritorID(exec->globalData()); + m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData())); - m_callbackFunctionStructure = JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get()); - m_argumentsStructure = Arguments::createStructure(exec->globalData(), m_objectPrototype.get()); - m_callbackConstructorStructure = JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get()); - m_callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(exec->globalData(), m_objectPrototype.get()); + m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get())); + m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), m_objectPrototype.get())); + m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get())); + m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSObjectWithGlobalObject>::createStructure(exec->globalData(), m_objectPrototype.get())); m_arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_arrayStructure = JSArray::createStructure(exec->globalData(), m_arrayPrototype.get()); - m_regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get()); + m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), m_arrayPrototype.get())); + m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get())); m_stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_stringObjectStructure = StringObject::createStructure(exec->globalData(), m_stringPrototype.get()); + m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), m_stringPrototype.get())); m_booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); - m_booleanObjectStructure = BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get()); + m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get())); m_numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); - m_numberObjectStructure = NumberObject::createStructure(exec->globalData(), m_numberPrototype.get()); + m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), m_numberPrototype.get())); m_datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_dateStructure = DateInstance::createStructure(exec->globalData(), m_datePrototype.get()); + m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), m_datePrototype.get())); m_regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); - m_regExpStructure = RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get()); + m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get())); m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()); - m_errorStructure = ErrorInstance::createStructure(exec->globalData(), errorPrototype); + m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), errorPrototype)); // Constructors @@ -233,8 +225,8 @@ void JSGlobalObject::reset(JSValue prototype) m_errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), errorPrototype)); - RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype); - RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()); + Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype); + Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()); m_evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); m_rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); m_referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); @@ -301,18 +293,18 @@ void JSGlobalObject::reset(JSValue prototype) putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif - resetPrototype(prototype); + resetPrototype(exec->globalData(), prototype); } // Set prototype, and also insert the object prototype at the end of the chain. -void JSGlobalObject::resetPrototype(JSValue prototype) +void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype) { - setPrototype(prototype); + setPrototype(globalData, prototype); JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); JSObject* objectPrototype = m_objectPrototype.get(); if (oldLastInPrototypeChain != objectPrototype) - oldLastInPrototypeChain->setPrototype(objectPrototype); + oldLastInPrototypeChain->setPrototype(globalData, objectPrototype); } void JSGlobalObject::markChildren(MarkStack& markStack) @@ -344,21 +336,21 @@ void JSGlobalObject::markChildren(MarkStack& markStack) markIfNeeded(markStack, &m_datePrototype); markIfNeeded(markStack, &m_regExpPrototype); - markIfNeeded(markStack, m_argumentsStructure); - markIfNeeded(markStack, m_arrayStructure); - markIfNeeded(markStack, m_booleanObjectStructure); - markIfNeeded(markStack, m_callbackConstructorStructure); - markIfNeeded(markStack, m_callbackFunctionStructure); - markIfNeeded(markStack, m_callbackObjectStructure); - markIfNeeded(markStack, m_dateStructure); - markIfNeeded(markStack, m_emptyObjectStructure); - markIfNeeded(markStack, m_errorStructure); - markIfNeeded(markStack, m_functionStructure); - markIfNeeded(markStack, m_numberObjectStructure); - markIfNeeded(markStack, m_regExpMatchesArrayStructure); - markIfNeeded(markStack, m_regExpStructure); - markIfNeeded(markStack, m_stringObjectStructure); - markIfNeeded(markStack, m_internalFunctionStructure); + markIfNeeded(markStack, &m_argumentsStructure); + markIfNeeded(markStack, &m_arrayStructure); + markIfNeeded(markStack, &m_booleanObjectStructure); + markIfNeeded(markStack, &m_callbackConstructorStructure); + markIfNeeded(markStack, &m_callbackFunctionStructure); + markIfNeeded(markStack, &m_callbackObjectStructure); + markIfNeeded(markStack, &m_dateStructure); + markIfNeeded(markStack, &m_emptyObjectStructure); + markIfNeeded(markStack, &m_errorStructure); + markIfNeeded(markStack, &m_functionStructure); + markIfNeeded(markStack, &m_numberObjectStructure); + markIfNeeded(markStack, &m_regExpMatchesArrayStructure); + markIfNeeded(markStack, &m_regExpStructure); + markIfNeeded(markStack, &m_stringObjectStructure); + markIfNeeded(markStack, &m_internalFunctionStructure); if (m_registerArray) { // Outside the execution of global code, when our variables are torn off, @@ -393,7 +385,7 @@ void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) return; } - OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData(), reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.lastGlobal()), numGlobals); + OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData(), reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.lastGlobal()), numGlobals, numGlobals); WriteBarrier<Unknown>* registers = registerArray.get() + numGlobals; setRegisters(registers, registerArray.release(), numGlobals); } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 04f63eb..0e36920 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -87,21 +87,21 @@ namespace JSC { WriteBarrier<DatePrototype> m_datePrototype; WriteBarrier<RegExpPrototype> m_regExpPrototype; - RefPtr<Structure> m_argumentsStructure; - RefPtr<Structure> m_arrayStructure; - RefPtr<Structure> m_booleanObjectStructure; - RefPtr<Structure> m_callbackConstructorStructure; - RefPtr<Structure> m_callbackFunctionStructure; - RefPtr<Structure> m_callbackObjectStructure; - RefPtr<Structure> m_dateStructure; - RefPtr<Structure> m_emptyObjectStructure; - RefPtr<Structure> m_errorStructure; - RefPtr<Structure> m_functionStructure; - RefPtr<Structure> m_numberObjectStructure; - RefPtr<Structure> m_regExpMatchesArrayStructure; - RefPtr<Structure> m_regExpStructure; - RefPtr<Structure> m_stringObjectStructure; - RefPtr<Structure> m_internalFunctionStructure; + WriteBarrier<Structure> m_argumentsStructure; + WriteBarrier<Structure> m_arrayStructure; + WriteBarrier<Structure> m_booleanObjectStructure; + WriteBarrier<Structure> m_callbackConstructorStructure; + WriteBarrier<Structure> m_callbackFunctionStructure; + WriteBarrier<Structure> m_callbackObjectStructure; + WriteBarrier<Structure> m_dateStructure; + WriteBarrier<Structure> m_emptyObjectStructure; + WriteBarrier<Structure> m_errorStructure; + WriteBarrier<Structure> m_functionStructure; + WriteBarrier<Structure> m_numberObjectStructure; + WriteBarrier<Structure> m_regExpMatchesArrayStructure; + WriteBarrier<Structure> m_regExpStructure; + WriteBarrier<Structure> m_stringObjectStructure; + WriteBarrier<Structure> m_internalFunctionStructure; unsigned m_profileGroup; Debugger* m_debugger; @@ -115,7 +115,7 @@ namespace JSC { void* operator new(size_t, JSGlobalData*); explicit JSGlobalObject(JSGlobalData& globalData) - : JSVariableObject(JSGlobalObject::createStructure(globalData, jsNull()), &m_symbolTable, 0) + : JSVariableObject(globalData, JSGlobalObject::createStructure(globalData, jsNull()), &m_symbolTable, 0) , m_registerArraySize(0) , m_globalScopeChain() , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) @@ -125,8 +125,8 @@ namespace JSC { init(this); } - explicit JSGlobalObject(NonNullPassRefPtr<Structure> structure) - : JSVariableObject(structure, &m_symbolTable, 0) + explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure) + : JSVariableObject(globalData, structure, &m_symbolTable, 0) , m_registerArraySize(0) , m_globalScopeChain() , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) @@ -137,8 +137,8 @@ namespace JSC { } protected: - JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSObject* thisValue) - : JSVariableObject(structure, &m_symbolTable, 0) + JSGlobalObject(JSGlobalData& globalData, Structure* structure, JSObject* thisValue) + : JSVariableObject(globalData, structure, &m_symbolTable, 0) , m_registerArraySize(0) , m_globalScopeChain() , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) @@ -235,11 +235,11 @@ namespace JSC { void copyGlobalsTo(RegisterFile&); void resizeRegisters(int oldSize, int newSize); - void resetPrototype(JSValue prototype); + void resetPrototype(JSGlobalData&, JSValue prototype); JSGlobalData& globalData() const { return *m_globalData.get(); } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -363,7 +363,7 @@ namespace JSC { // We cache our prototype chain so our clients can share it. if (!isValid(exec, m_cachedPrototypeChain.get())) { JSValue prototype = prototypeForLookup(exec); - m_cachedPrototypeChain = StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()); + m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure())); } return m_cachedPrototypeChain.get(); } @@ -374,9 +374,9 @@ namespace JSC { return false; JSValue prototype = prototypeForLookup(exec); - RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head(); + WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head(); while(*cachedStructure && !prototype.isNull()) { - if (asObject(prototype)->structure() != *cachedStructure) + if (asObject(prototype)->structure() != cachedStructure->get()) return false; ++cachedStructure; prototype = asObject(prototype)->prototype(); @@ -407,17 +407,17 @@ namespace JSC { inline JSArray* constructEmptyArray(ExecState* exec) { - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure()); + return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure()); } inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject) { - return new (exec) JSArray(globalObject->arrayStructure()); + return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure()); } inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) { - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength, CreateInitialized); + return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), initialLength, CreateInitialized); } inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue) diff --git a/Source/JavaScriptCore/runtime/JSImmediate.cpp b/Source/JavaScriptCore/runtime/JSImmediate.cpp deleted file mode 100644 index 846238d..0000000 --- a/Source/JavaScriptCore/runtime/JSImmediate.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2003-2006, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "JSImmediate.h" - -namespace JSC { - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSImmediate.h b/Source/JavaScriptCore/runtime/JSImmediate.h deleted file mode 100644 index 68ba75c..0000000 --- a/Source/JavaScriptCore/runtime/JSImmediate.h +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef JSImmediate_h -#define JSImmediate_h - -#if USE(JSVALUE64) - -#include <wtf/Assertions.h> -#include <wtf/AlwaysInline.h> -#include <wtf/MathExtras.h> -#include <wtf/StdLibExtras.h> -#include "JSValue.h" -#include <limits> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdlib.h> - -namespace JSC { - - class ExecState; - class JSCell; - class JSGlobalData; - class JSObject; - class UString; - - inline intptr_t reinterpretDoubleToIntptr(double value) - { - return WTF::bitwise_cast<intptr_t>(value); - } - - inline double reinterpretIntptrToDouble(intptr_t value) - { - return WTF::bitwise_cast<double>(value); - } - - /* - * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged - * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging - * because allocator alignment guarantees they will be 00 in cell pointers. - * - * For example, on a 32 bit system: - * - * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00 - * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ] - * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT - * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ] - * - * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed - * integer, or they mark the value as being an immediate of a type other than integer, with a secondary - * tag used to indicate the exact type. - * - * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value. - * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next - * two bits will form an extended tag. - * - * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1 - * [ high 30 bits of the value ] [ high bit part of value ] - * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10 - * [ extended 'payload' ] [ extended tag ] [ tag 'other' ] - * - * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following - * bit would flag the value as undefined. If neither bits are set, the value is null. - * - * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10 - * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ] - * - * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero. - * For undefined or null immediates the payload is zero. - * - * Boolean: 000000000000000000000000000V 01 10 - * [ boolean value ] [ bool ] [ tag 'other' ] - * Undefined: 0000000000000000000000000000 10 10 - * [ zero ] [ undefined ] [ tag 'other' ] - * Null: 0000000000000000000000000000 00 10 - * [ zero ] [ zero ] [ tag 'other' ] - */ - - /* - * On 64-bit platforms, we support an alternative encoding form for immediates, if - * USE(JSVALUE64) is defined. When this format is used, double precision - * floating point values may also be encoded as JSImmediates. - * - * The encoding makes use of unused NaN space in the IEEE754 representation. Any value - * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values - * can encode a 51-bit payload. Hardware produced and C-library payloads typically - * have a payload of zero. We assume that non-zero payloads are available to encode - * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are - * all set represents a NaN with a non-zero payload, we can use this space in the NaN - * ranges to encode other values (however there are also other ranges of NaN space that - * could have been selected). This range of NaN space is represented by 64-bit numbers - * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no - * valid double-precision numbers will begin fall in these ranges. - * - * The scheme we have implemented encodes double precision values by adding 2^48 to the - * 64-bit integer representation of the number. After this manipulation, no encoded - * double-precision value will begin with the pattern 0x0000 or 0xFFFF. - * - * The top 16-bits denote the type of the encoded JSImmediate: - * - * Pointer: 0000:PPPP:PPPP:PPPP - * 0001:****:****:**** - * Double:{ ... - * FFFE:****:****:**** - * Integer: FFFF:0000:IIII:IIII - * - * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000 - * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined - * values are encoded in the same manner as the default format. - */ - - class JSImmediate { - private: - friend class JIT; - friend class JSValue; - friend class JSInterfaceJIT; - friend class SpecializedThunkJIT; - friend JSValue jsNumber(ExecState* exec, double d); - friend JSValue jsNumber(ExecState*, char i); - friend JSValue jsNumber(ExecState*, unsigned char i); - friend JSValue jsNumber(ExecState*, short i); - friend JSValue jsNumber(ExecState*, unsigned short i); - friend JSValue jsNumber(ExecState* exec, int i); - friend JSValue jsNumber(ExecState* exec, unsigned i); - friend JSValue jsNumber(ExecState* exec, long i); - friend JSValue jsNumber(ExecState* exec, unsigned long i); - friend JSValue jsNumber(ExecState* exec, long long i); - friend JSValue jsNumber(ExecState* exec, unsigned long long i); - friend JSValue jsNumber(JSGlobalData* globalData, double d); - friend JSValue jsNumber(JSGlobalData* globalData, short i); - friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i); - friend JSValue jsNumber(JSGlobalData* globalData, int i); - friend JSValue jsNumber(JSGlobalData* globalData, unsigned i); - friend JSValue jsNumber(JSGlobalData* globalData, long i); - friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i); - friend JSValue jsNumber(JSGlobalData* globalData, long long i); - friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i); - - // If all bits in the mask are set, this indicates an integer number, - // if any but not all are set this value is a double precision number. - static const intptr_t TagTypeNumber = 0xffff000000000000ll; - // This value is 2^48, used to encode doubles such that the encoded value will begin - // with a 16-bit pattern within the range 0x0001..0xFFFE. - static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; - static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer - static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther; - - static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits - static const intptr_t ExtendedTagBitBool = 0x4; - static const intptr_t ExtendedTagBitUndefined = 0x8; - - static const intptr_t FullTagTypeMask = TagMask | ExtendedTagMask; - static const intptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool; - static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; - static const intptr_t FullTagTypeNull = TagBitTypeOther; - - static const int32_t IntegerPayloadShift = 0; - static const int32_t ExtendedPayloadShift = 4; - - static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift; - - static const int32_t signBit = 0x80000000; - - static ALWAYS_INLINE bool isImmediate(JSValue v) - { - return rawValue(v) & TagMask; - } - - static ALWAYS_INLINE bool isNumber(JSValue v) - { - return rawValue(v) & TagTypeNumber; - } - - static ALWAYS_INLINE bool isIntegerNumber(JSValue v) - { - return (rawValue(v) & TagTypeNumber) == TagTypeNumber; - } - - static ALWAYS_INLINE bool isDouble(JSValue v) - { - return isNumber(v) && !isIntegerNumber(v); - } - - static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v) - { - // A single mask to check for the sign bit and the number tag all at once. - return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber; - } - - static ALWAYS_INLINE bool isBoolean(JSValue v) - { - return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool; - } - - static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v) - { - // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. - return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull; - } - - static JSValue from(char); - static JSValue from(signed char); - static JSValue from(unsigned char); - static JSValue from(short); - static JSValue from(unsigned short); - static JSValue from(int); - static JSValue from(unsigned); - static JSValue from(long); - static JSValue from(unsigned long); - static JSValue from(long long); - static JSValue from(unsigned long long); - static JSValue from(double); - - static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2) - { - return (rawValue(v1) | rawValue(v2)) & TagMask; - } - - static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2) - { - return isImmediate(v1) & isImmediate(v2); - } - - static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2) - { - return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; - } - - static double toDouble(JSValue); - static bool toBoolean(JSValue); - - static bool getUInt32(JSValue, uint32_t&); - static bool getTruncatedInt32(JSValue, int32_t&); - static bool getTruncatedUInt32(JSValue, uint32_t&); - - static int32_t getTruncatedInt32(JSValue); - static uint32_t getTruncatedUInt32(JSValue); - - static JSValue trueImmediate(); - static JSValue falseImmediate(); - static JSValue undefinedImmediate(); - static JSValue nullImmediate(); - static JSValue zeroImmediate(); - static JSValue oneImmediate(); - - private: - static const int minImmediateInt = ((-INT_MAX) - 1); - static const int maxImmediateInt = INT_MAX; - static const unsigned maxImmediateUInt = maxImmediateInt; - - static ALWAYS_INLINE JSValue makeValue(intptr_t integer) - { - return JSValue::makeImmediate(integer); - } - - // With USE(JSVALUE64) we want the argument to be zero extended, so the - // integer doesn't interfere with the tag bits in the upper word. In the default encoding, - // if intptr_t id larger then int32_t we sign extend the value through the upper word. - static ALWAYS_INLINE JSValue makeInt(uint32_t value) - { - return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); - } - - static ALWAYS_INLINE JSValue makeDouble(double value) - { - return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); - } - - static ALWAYS_INLINE JSValue makeBool(bool b) - { - return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool); - } - - static ALWAYS_INLINE JSValue makeUndefined() - { - return makeValue(FullTagTypeUndefined); - } - - static ALWAYS_INLINE JSValue makeNull() - { - return makeValue(FullTagTypeNull); - } - - template<typename T> - static JSValue fromNumberOutsideIntegerRange(T); - - static ALWAYS_INLINE double doubleValue(JSValue v) - { - return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); - } - - static ALWAYS_INLINE int32_t intValue(JSValue v) - { - return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift); - } - - static ALWAYS_INLINE uint32_t uintValue(JSValue v) - { - return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift); - } - - static ALWAYS_INLINE bool boolValue(JSValue v) - { - return rawValue(v) & ExtendedPayloadBitBoolValue; - } - - static ALWAYS_INLINE intptr_t rawValue(JSValue v) - { - return v.immediateValue(); - } - }; - - ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); } - ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); } - ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); } - ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); } - ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); } - ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); } - - inline bool doubleToBoolean(double value) - { - return value < 0.0 || value > 0.0; - } - - ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v) - { - ASSERT(isImmediate(v)); - return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate() - : doubleToBoolean(doubleValue(v)) : v == trueImmediate(); - } - - ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v) - { - // FIXME: should probably be asserting isPositiveIntegerNumber here. - ASSERT(isIntegerNumber(v)); - return intValue(v); - } - - template<typename T> - inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value) - { - return makeDouble(static_cast<double>(value)); - } - - ALWAYS_INLINE JSValue JSImmediate::from(char i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(signed char i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(short i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(int i) - { - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(unsigned i) - { - if (i > maxImmediateUInt) - return fromNumberOutsideIntegerRange(i); - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(long i) - { - if ((i < minImmediateInt) | (i > maxImmediateInt)) - return fromNumberOutsideIntegerRange(i); - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i) - { - if (i > maxImmediateUInt) - return fromNumberOutsideIntegerRange(i); - return makeInt(i); - } - - ALWAYS_INLINE JSValue JSImmediate::from(long long i) - { - if ((i < minImmediateInt) | (i > maxImmediateInt)) - return JSValue(); - return makeInt(static_cast<intptr_t>(i)); - } - - ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i) - { - if (i > maxImmediateUInt) - return fromNumberOutsideIntegerRange(i); - return makeInt(static_cast<intptr_t>(i)); - } - - ALWAYS_INLINE JSValue JSImmediate::from(double d) - { - const int intVal = static_cast<int>(d); - - // Check for data loss from conversion to int. - if (intVal != d || (!intVal && signbit(d))) - return fromNumberOutsideIntegerRange(d); - - return from(intVal); - } - - ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v) - { - ASSERT(isIntegerNumber(v)); - return intValue(v); - } - - ALWAYS_INLINE double JSImmediate::toDouble(JSValue v) - { - ASSERT(isImmediate(v)); - - if (isIntegerNumber(v)) - return intValue(v); - - if (isNumber(v)) { - ASSERT(isDouble(v)); - return doubleValue(v); - } - - if (rawValue(v) == FullTagTypeUndefined) - return nonInlineNaN(); - - ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate())); - return rawValue(v) >> ExtendedPayloadShift; - } - - ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i) - { - i = uintValue(v); - return isPositiveIntegerNumber(v); - } - - ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i) - { - i = intValue(v); - return isIntegerNumber(v); - } - - ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i) - { - return getUInt32(v, i); - } - - inline JSValue::JSValue(JSNullTag) - { - *this = JSImmediate::nullImmediate(); - } - - inline JSValue::JSValue(JSUndefinedTag) - { - *this = JSImmediate::undefinedImmediate(); - } - - inline JSValue::JSValue(JSTrueTag) - { - *this = JSImmediate::trueImmediate(); - } - - inline JSValue::JSValue(JSFalseTag) - { - *this = JSImmediate::falseImmediate(); - } - - inline bool JSValue::isUndefinedOrNull() const - { - return JSImmediate::isUndefinedOrNull(asValue()); - } - - inline bool JSValue::isBoolean() const - { - return JSImmediate::isBoolean(asValue()); - } - - inline bool JSValue::isTrue() const - { - return asValue() == JSImmediate::trueImmediate(); - } - - inline bool JSValue::isFalse() const - { - return asValue() == JSImmediate::falseImmediate(); - } - - inline bool JSValue::getBoolean(bool& v) const - { - if (JSImmediate::isBoolean(asValue())) { - v = JSImmediate::toBoolean(asValue()); - return true; - } - - return false; - } - - inline bool JSValue::getBoolean() const - { - return asValue() == jsBoolean(true); - } - - inline bool JSValue::isCell() const - { - return !JSImmediate::isImmediate(asValue()); - } - - inline bool JSValue::isInt32() const - { - return JSImmediate::isIntegerNumber(asValue()); - } - - inline int32_t JSValue::asInt32() const - { - ASSERT(isInt32()); - return JSImmediate::getTruncatedInt32(asValue()); - } - - inline bool JSValue::isUInt32() const - { - return JSImmediate::isPositiveIntegerNumber(asValue()); - } - - inline uint32_t JSValue::asUInt32() const - { - ASSERT(isUInt32()); - return JSImmediate::getTruncatedUInt32(asValue()); - } - -} // namespace JSC - -#endif // USE(JSVALUE64) - -#endif // JSImmediate_h diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h index 75bca18..4c6806a 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.h +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h @@ -39,11 +39,11 @@ namespace JSC { class JSNotAnObject : public JSNonFinalObject { public: JSNotAnObject(ExecState* exec) - : JSNonFinalObject(exec->globalData().notAnObjectStructure) + : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get()) { } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.cpp b/Source/JavaScriptCore/runtime/JSNumberCell.cpp deleted file mode 100644 index 79f2d2a..0000000 --- a/Source/JavaScriptCore/runtime/JSNumberCell.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "JSNumberCell.h" -#include "JSObject.h" -#include "ScopeChain.h" - -// Keep our exported symbols lists happy. -namespace JSC { - -JSValue jsNumberCell(ExecState*, double); - -JSValue jsNumberCell(ExecState*, double) -{ - ASSERT_NOT_REACHED(); - return JSValue(); -} - -} // namespace JSC - diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.h b/Source/JavaScriptCore/runtime/JSNumberCell.h deleted file mode 100644 index 1ccdf50..0000000 --- a/Source/JavaScriptCore/runtime/JSNumberCell.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef JSNumberCell_h -#define JSNumberCell_h - -#include "CallFrame.h" -#include "JSCell.h" -#include "JSImmediate.h" -#include "Heap.h" -#include "UString.h" -#include <stddef.h> // for size_t - -namespace JSC { - - extern const double NaN; - extern const double Inf; - -#if USE(JSVALUE64) - ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) - { - *this = JSImmediate::fromNumberOutsideIntegerRange(d); - } - - inline JSValue::JSValue(double d) - { - JSValue v = JSImmediate::from(d); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(int i) - { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(unsigned i) - { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(long i) - { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(unsigned long i) - { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(long long i) - { - JSValue v = JSImmediate::from(static_cast<double>(i)); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(unsigned long long i) - { - JSValue v = JSImmediate::from(static_cast<double>(i)); - ASSERT(v); - *this = v; - } - - inline bool JSValue::isDouble() const - { - return JSImmediate::isDouble(asValue()); - } - - inline double JSValue::asDouble() const - { - return JSImmediate::doubleValue(asValue()); - } - - inline bool JSValue::isNumber() const - { - return JSImmediate::isNumber(asValue()); - } - - inline double JSValue::uncheckedGetNumber() const - { - ASSERT(isNumber()); - return JSImmediate::toDouble(asValue()); - } - -#endif // USE(JSVALUE64) - -#if USE(JSVALUE64) - - inline JSValue::JSValue(char i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(unsigned char i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(short i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(unsigned short i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue jsNaN() - { - return jsNumber(NaN); - } - - // --- JSValue inlines ---------------------------- - - ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const - { - return isNumber() ? asValue() : jsNumber(this->toNumber(exec)); - } - - inline bool JSValue::getNumber(double &result) const - { - if (isInt32()) - result = asInt32(); - else if (LIKELY(isDouble())) - result = asDouble(); - else { - ASSERT(!isNumber()); - return false; - } - return true; - } - -#endif // USE(JSVALUE64) - -} // namespace JSC - -#endif // JSNumberCell_h diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 8fc7ac9..27fc569 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -53,7 +53,7 @@ static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*); namespace JSC { -JSONObject::JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) +JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure) : JSObjectWithGlobalObject(globalObject, structure) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h index a52c543..c87c641 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.h +++ b/Source/JavaScriptCore/runtime/JSONObject.h @@ -34,9 +34,9 @@ namespace JSC { class JSONObject : public JSObjectWithGlobalObject { public: - JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure); + JSONObject(JSGlobalObject*, Structure*); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index b307540..9677f23 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -109,7 +109,7 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. if (!value.isObject() && !value.isNull()) return; - if (!setPrototypeWithCycleCheck(value)) + if (!setPrototypeWithCycleCheck(exec->globalData(), value)) throwError(exec, createError(exec, "cyclic __proto__ value")); return; } @@ -127,14 +127,14 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu unsigned attributes; JSCell* specificValue; - if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) { + if ((m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) { if (slot.isStrictMode()) throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); return; } for (JSObject* obj = this; ; obj = asObject(prototype)) { - if (JSValue gs = obj->getDirect(propertyName)) { + if (JSValue gs = obj->getDirect(exec->globalData(), propertyName)) { if (gs.isGetterSetter()) { JSObject* setterFunc = asGetterSetter(gs)->setter(); if (!setterFunc) { @@ -218,10 +218,10 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { unsigned attributes; JSCell* specificValue; - if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) { + if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) { if ((attributes & DontDelete)) return false; - removeDirect(propertyName); + removeDirect(exec->globalData(), propertyName); return true; } @@ -312,34 +312,33 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) { - JSValue object = getDirect(propertyName); + JSValue object = getDirect(exec->globalData(), propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setGetter(exec->globalData(), getterFunction); return; } + JSGlobalData& globalData = exec->globalData(); PutPropertySlot slot; GetterSetter* getterSetter = new (exec) GetterSetter(exec); - putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot); + putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. if (slot.type() != PutPropertySlot::NewProperty) { - if (!m_structure->isDictionary()) { - RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure); - setStructure(structure.release()); - } + if (!m_structure->isDictionary()) + setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, m_structure.get())); } m_structure->setHasGetterSetterProperties(true); - getterSetter->setGetter(exec->globalData(), getterFunction); + getterSetter->setGetter(globalData, getterFunction); } void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes) { - JSValue object = getDirect(propertyName); + JSValue object = getDirect(exec->globalData(), propertyName); if (object && object.isGetterSetter()) { ASSERT(m_structure->hasGetterSetterProperties()); asGetterSetter(object)->setSetter(exec->globalData(), setterFunction); @@ -354,21 +353,19 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. if (slot.type() != PutPropertySlot::NewProperty) { - if (!m_structure->isDictionary()) { - RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure); - setStructure(structure.release()); - } + if (!m_structure->isDictionary()) + setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), m_structure.get())); } m_structure->setHasGetterSetterProperties(true); getterSetter->setSetter(exec->globalData(), setterFunction); } -JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName) +JSValue JSObject::lookupGetter(ExecState* exec, const Identifier& propertyName) { JSObject* object = this; while (true) { - if (JSValue value = object->getDirect(propertyName)) { + if (JSValue value = object->getDirect(exec->globalData(), propertyName)) { if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->getter(); @@ -383,11 +380,11 @@ JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName) } } -JSValue JSObject::lookupSetter(ExecState*, const Identifier& propertyName) +JSValue JSObject::lookupSetter(ExecState* exec, const Identifier& propertyName) { JSObject* object = this; while (true) { - if (JSValue value = object->getDirect(propertyName)) { + if (JSValue value = object->getDirect(exec->globalData(), propertyName)) { if (!value.isGetterSetter()) return jsUndefined(); JSObject* functionObject = asGetterSetter(value)->setter(); @@ -428,10 +425,10 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN return descriptor.enumerable(); } -bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const +bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const { unsigned attributes; - if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) + if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) return true; // This could be a function within the static table? - should probably @@ -464,7 +461,7 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_structure->getPropertyNames(propertyNames, mode); + m_structure->getPropertyNames(exec->globalData(), propertyNames, mode); getClassPropertyNames(exec, classInfo(), propertyNames, mode); } @@ -509,34 +506,33 @@ JSObject* JSObject::unwrappedObject() return this; } -void JSObject::seal() +void JSObject::seal(JSGlobalData& globalData) { - setStructure(Structure::sealTransition(m_structure)); + setStructure(globalData, Structure::sealTransition(globalData, m_structure.get())); } -void JSObject::freeze() +void JSObject::freeze(JSGlobalData& globalData) { - setStructure(Structure::freezeTransition(m_structure)); + setStructure(globalData, Structure::freezeTransition(globalData, m_structure.get())); } -void JSObject::preventExtensions() +void JSObject::preventExtensions(JSGlobalData& globalData) { if (isExtensible()) - setStructure(Structure::preventExtensionsTransition(m_structure)); + setStructure(globalData, Structure::preventExtensionsTransition(globalData, m_structure.get())); } -void JSObject::removeDirect(const Identifier& propertyName) +void JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName) { size_t offset; if (m_structure->isUncacheableDictionary()) { - offset = m_structure->removePropertyWithoutTransition(propertyName); + offset = m_structure->removePropertyWithoutTransition(globalData, propertyName); if (offset != WTF::notFound) putUndefinedAtDirectOffset(offset); return; } - RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset); - setStructure(structure.release()); + setStructure(globalData, Structure::removePropertyTransition(globalData, m_structure.get(), propertyName, offset)); if (offset != WTF::notFound) putUndefinedAtDirectOffset(offset); } @@ -574,7 +570,8 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr Structure* JSObject::createInheritorID(JSGlobalData& globalData) { - m_inheritorID = createEmptyObjectStructure(globalData, this); + m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, this)); + ASSERT(m_inheritorID->isEmpty()); return m_inheritorID.get(); } @@ -598,11 +595,11 @@ void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize) m_propertyStorage = newPropertyStorage; } -bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor) +bool JSObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { unsigned attributes = 0; JSCell* cell = 0; - size_t offset = m_structure->get(propertyName, attributes, cell); + size_t offset = m_structure->get(exec->globalData(), propertyName, attributes, cell); if (offset == WTF::notFound) return false; descriptor.setDescriptor(getDirectOffset(offset), attributes); @@ -754,7 +751,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return false; } } - JSValue accessor = getDirect(propertyName); + JSValue accessor = getDirect(exec->globalData(), propertyName); if (!accessor) return false; GetterSetter* getterSetter = asGetterSetter(accessor); diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 578b3cf..80735f8 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -29,7 +29,6 @@ #include "Completion.h" #include "CallFrame.h" #include "JSCell.h" -#include "JSNumberCell.h" #include "MarkStack.h" #include "PropertySlot.h" #include "PutPropertySlot.h" @@ -88,10 +87,10 @@ namespace JSC { virtual ~JSObject(); JSValue prototype() const; - void setPrototype(JSValue prototype); - bool setPrototypeWithCycleCheck(JSValue prototype); + void setPrototype(JSGlobalData&, JSValue prototype); + bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype); - void setStructure(NonNullPassRefPtr<Structure>); + void setStructure(JSGlobalData&, Structure*); Structure* inheritorID(JSGlobalData&); virtual UString className() const; @@ -147,22 +146,22 @@ namespace JSC { bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. - JSValue getDirect(const Identifier& propertyName) const + JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const { - size_t offset = m_structure->get(propertyName); + size_t offset = m_structure->get(globalData, propertyName); return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); } - WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName) + WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName) { - size_t offset = m_structure->get(propertyName); + size_t offset = m_structure->get(globalData, propertyName); return offset != WTF::notFound ? locationForOffset(offset) : 0; } - WriteBarrierBase<Unknown>* getDirectLocation(const Identifier& propertyName, unsigned& attributes) + WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes) { JSCell* specificFunction; - size_t offset = m_structure->get(propertyName, attributes, specificFunction); + size_t offset = m_structure->get(globalData, propertyName, attributes, specificFunction); return offset != WTF::notFound ? locationForOffset(offset) : 0; } @@ -171,9 +170,9 @@ namespace JSC { return location - propertyStorage(); } - void transitionTo(Structure*); + void transitionTo(JSGlobalData&, Structure*); - void removeDirect(const Identifier& propertyName); + void removeDirect(JSGlobalData&, const Identifier& propertyName); bool hasCustomProperties() { return !m_structure->isEmpty(); } bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); } @@ -210,17 +209,17 @@ namespace JSC { virtual bool isStrictModeFunction() const { return false; } virtual bool isErrorInstance() const { return false; } - void seal(); - void freeze(); - void preventExtensions(); - bool isSealed() { return m_structure->isSealed(); } - bool isFrozen() { return m_structure->isFrozen(); } + void seal(JSGlobalData&); + void freeze(JSGlobalData&); + void preventExtensions(JSGlobalData&); + bool isSealed(JSGlobalData& globalData) { return m_structure->isSealed(globalData); } + bool isFrozen(JSGlobalData& globalData) { return m_structure->isFrozen(globalData); } bool isExtensible() { return m_structure->isExtensible(); } virtual ComplType exceptionType() const { return Throw; } void allocatePropertyStorage(size_t oldSize, size_t newSize); - bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } + bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); } static const unsigned baseExternalStorageCapacity = 16; @@ -250,7 +249,7 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; protected: - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -264,7 +263,12 @@ namespace JSC { // To instantiate objects you likely want JSFinalObject, below. // To create derived types you likely want JSNonFinalObject, below. - JSObject(NonNullPassRefPtr<Structure>, PropertyStorage inlineStorage); + JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage); + JSObject(VPtrStealingHackType, PropertyStorage inlineStorage) + : JSCell(VPtrStealingHack) + , m_propertyStorage(inlineStorage) + { + } private: // Nobody should ever ask any of these questions on something already known to be a JSObject. @@ -299,7 +303,7 @@ namespace JSC { Structure* createInheritorID(JSGlobalData&); PropertyStorage m_propertyStorage; - RefPtr<Structure> m_inheritorID; + WriteBarrier<Structure> m_inheritorID; }; @@ -320,14 +324,19 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt friend class JSObject; public: - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - explicit JSNonFinalObject(NonNullPassRefPtr<Structure> structure) - : JSObject(structure, m_inlineStorage) + explicit JSNonFinalObject(VPtrStealingHackType) + : JSObject(VPtrStealingHack, m_inlineStorage) + { + } + + explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure) + : JSObject(globalData, structure, m_inlineStorage) { ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double))); ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity); @@ -343,19 +352,19 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt friend class JSObject; public: - static JSFinalObject* create(ExecState* exec, NonNullPassRefPtr<Structure> structure) + static JSFinalObject* create(ExecState* exec, Structure* structure) { - return new (exec) JSFinalObject(structure); + return new (exec) JSFinalObject(exec->globalData(), structure); } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: - explicit JSFinalObject(NonNullPassRefPtr<Structure> structure) - : JSObject(structure, m_inlineStorage) + explicit JSFinalObject(JSGlobalData& globalData, Structure* structure) + : JSObject(globalData, structure, m_inlineStorage) { ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0); ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity); @@ -372,12 +381,12 @@ inline size_t JSObject::offsetOfInlineStorage() return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage); } -inline JSObject* constructEmptyObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) +inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure) { return JSFinalObject::create(exec, structure); } -inline PassRefPtr<Structure> createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype) +inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype) { return JSFinalObject::createStructure(globalData, prototype); } @@ -393,22 +402,22 @@ inline JSObject* asObject(JSValue value) return asObject(value.asCell()); } -inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure, PropertyStorage inlineStorage) - : JSCell(structure.releaseRef()) // ~JSObject balances this ref() +inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage) + : JSCell(globalData, structure) , m_propertyStorage(inlineStorage) { ASSERT(inherits(&s_info)); ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); + ASSERT(static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1)); + ASSERT(m_structure->typeInfo().type() == ObjectType); } inline JSObject::~JSObject() { - ASSERT(m_structure); if (!isUsingInlineStorage()) delete [] m_propertyStorage; - m_structure->deref(); } inline JSValue JSObject::prototype() const @@ -416,7 +425,7 @@ inline JSValue JSObject::prototype() const return m_structure->storedPrototype(); } -inline bool JSObject::setPrototypeWithCycleCheck(JSValue prototype) +inline bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype) { JSValue nextPrototypeValue = prototype; while (nextPrototypeValue && nextPrototypeValue.isObject()) { @@ -425,27 +434,27 @@ inline bool JSObject::setPrototypeWithCycleCheck(JSValue prototype) return false; nextPrototypeValue = nextPrototype->prototype(); } - setPrototype(prototype); + setPrototype(globalData, prototype); return true; } -inline void JSObject::setPrototype(JSValue prototype) +inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype) { ASSERT(prototype); - RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype); - setStructure(newStructure.release()); + setStructure(globalData, Structure::changePrototypeTransition(globalData, m_structure.get(), prototype)); } -inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure) +inline void JSObject::setStructure(JSGlobalData& globalData, Structure* structure) { - m_structure->deref(); - m_structure = structure.leakRef(); // ~JSObject balances this ref() + m_structure.set(globalData, this, structure); } inline Structure* JSObject::inheritorID(JSGlobalData& globalData) { - if (m_inheritorID) + if (m_inheritorID) { + ASSERT(m_inheritorID->isEmpty()); return m_inheritorID.get(); + } return createInheritorID(globalData); } @@ -471,7 +480,7 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (WriteBarrierBase<Unknown>* location = getDirectLocation(propertyName)) { + if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) { if (m_structure->hasGetterSetterProperties() && location->isGetterSetter()) fillGetterPropertySlot(slot, location); else @@ -557,12 +566,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if (m_structure->isDictionary()) { unsigned currentAttributes; JSCell* currentSpecificFunction; - size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); + size_t offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { // If there is currently a specific function, and there now either isn't, // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) - m_structure->despecifyDictionaryFunction(propertyName); + m_structure->despecifyDictionaryFunction(globalData, propertyName); if (checkReadOnly && currentAttributes & ReadOnly) return false; @@ -582,7 +591,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return false; size_t currentCapacity = m_structure->propertyStorageCapacity(); - offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction); + offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); @@ -596,12 +605,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi size_t offset; size_t currentCapacity = m_structure->propertyStorageCapacity(); - if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) { + if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(m_structure.get(), propertyName, attributes, specificFunction, offset)) { if (currentCapacity != structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(structure.release()); + setStructure(globalData, structure); 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. @@ -612,7 +621,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi unsigned currentAttributes; JSCell* currentSpecificFunction; - offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); + offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { if (checkReadOnly && currentAttributes & ReadOnly) return false; @@ -633,7 +642,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } // case (2) Despecify, fall through to (3). - setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); + setStructure(globalData, Structure::despecifyFunctionTransition(globalData, m_structure.get(), propertyName)); } // case (3) set the slot, do the put, return. @@ -645,13 +654,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if (!isExtensible()) return false; - RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset); + Structure* structure = Structure::addPropertyTransition(globalData, m_structure.get(), propertyName, attributes, specificFunction, offset); if (currentCapacity != structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(structure.release()); + setStructure(globalData, structure); 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. @@ -707,7 +716,7 @@ inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifi 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); + size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, 0); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); putDirectOffset(globalData, offset, value); @@ -716,17 +725,17 @@ inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const 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); + size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, value); if (currentCapacity != m_structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity()); putDirectOffset(globalData, offset, value); } -inline void JSObject::transitionTo(Structure* newStructure) +inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure) { if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity()) allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); - setStructure(newStructure); + setStructure(globalData, newStructure); } inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const @@ -814,13 +823,12 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) { JSCell::markChildren(markStack); - - markStack.append(m_structure->storedPrototypeSlot()); - if (*m_structure->cachedPrototypeChainSlot()) - markStack.append(m_structure->cachedPrototypeChainSlot()); + PropertyStorage storage = propertyStorage(); size_t storageSize = m_structure->propertyStorageSize(); markStack.appendValues(storage, storageSize); + if (m_inheritorID) + markStack.append(&m_inheritorID); } // --- JSValue inlines ---------------------------- diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp index 9370139..2b489a2 100644 --- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp @@ -30,8 +30,8 @@ namespace JSC { -JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) - : JSNonFinalObject(structure) +JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, Structure* structure) + : JSNonFinalObject(globalObject->globalData(), structure) { COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one); ASSERT(!globalObject || globalObject->isGlobalObject()); @@ -41,9 +41,15 @@ JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, putAnonymousValue(globalObject->globalData(), GlobalObjectSlot, globalObject); } -JSGlobalObject* JSObjectWithGlobalObject::globalObject() const +JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure) + : JSNonFinalObject(globalData, structure) { - return asGlobalObject((getAnonymousValue(GlobalObjectSlot).asCell())); + COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one); + ASSERT(!globalObject || globalObject->isGlobalObject()); + if (!globalObject) + clearAnonymousValue(GlobalObjectSlot); + else + putAnonymousValue(globalData, GlobalObjectSlot, globalObject); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h index 8380514..844bcd8 100644 --- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h @@ -26,7 +26,7 @@ #ifndef JSObjectWithGlobalObject_h #define JSObjectWithGlobalObject_h -#include "JSObject.h" +#include "JSGlobalObject.h" namespace JSC { @@ -34,18 +34,22 @@ class JSGlobalObject; class JSObjectWithGlobalObject : public JSNonFinalObject { public: - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - JSGlobalObject* globalObject() const; + JSGlobalObject* globalObject() const + { + return asGlobalObject((getAnonymousValue(GlobalObjectSlot).asCell())); + } protected: - JSObjectWithGlobalObject(JSGlobalObject*, NonNullPassRefPtr<Structure>); + JSObjectWithGlobalObject(JSGlobalObject*, Structure*); + JSObjectWithGlobalObject(JSGlobalData&, JSGlobalObject*, Structure*); - JSObjectWithGlobalObject(NonNullPassRefPtr<Structure> structure) - : JSNonFinalObject(structure) + JSObjectWithGlobalObject(VPtrStealingHackType) + : JSNonFinalObject(VPtrStealingHack) { // Should only be used by JSFunction when we aquire the JSFunction vptr. } diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index 6f31f99..d5af044 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -35,9 +35,10 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator); +const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0 }; + inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots) - : JSCell(exec->globalData().propertyNameIteratorStructure.get()) - , m_cachedStructure(0) + : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get()) , m_numCacheableSlots(numCacheableSlots) , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) , m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize])) @@ -71,14 +72,14 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject size_t count = normalizePrototypeChain(exec, o); StructureChain* structureChain = o->structure()->prototypeChain(exec); - RefPtr<Structure>* structure = structureChain->head(); + WriteBarrier<Structure>* structure = structureChain->head(); for (size_t i = 0; i < count; ++i) { if (structure[i]->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; } jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain); - jsPropertyNameIterator->setCachedStructure(o->structure()); + jsPropertyNameIterator->setCachedStructure(exec->globalData(), o->structure()); o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator); return jsPropertyNameIterator; } @@ -86,7 +87,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) { JSValue identifier = m_jsStrings[i].get(); - if (m_cachedStructure == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec)) + if (m_cachedStructure.get() == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec)) return identifier; if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec)))) @@ -101,12 +102,4 @@ void JSPropertyNameIterator::markChildren(MarkStack& markStack) markStack.append(&m_cachedPrototypeChain); } -#if !ASSERT_DISABLED - -JSPropertyNameIterator::~JSPropertyNameIterator() -{ - ASSERT(!m_cachedStructure || m_cachedStructure->enumerationCache() != this); -} - -#endif } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h index 499396c..b857dc0 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -45,9 +45,9 @@ namespace JSC { public: static JSPropertyNameIterator* create(ExecState*, JSObject*); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, &s_info); } virtual bool isPropertyNameIterator() const { return true; } @@ -65,11 +65,11 @@ namespace JSC { JSValue get(ExecState*, JSObject*, size_t i); size_t size() { return m_jsStringsSize; } - void setCachedStructure(Structure* structure) + void setCachedStructure(JSGlobalData& globalData, Structure* structure) { ASSERT(!m_cachedStructure); ASSERT(structure); - m_cachedStructure = structure; + m_cachedStructure.set(globalData, this, structure); } Structure* cachedStructure() { return m_cachedStructure.get(); } @@ -77,13 +77,10 @@ namespace JSC { StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } private: + static const ClassInfo s_info; JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot); - -#if !ASSERT_DISABLED - virtual ~JSPropertyNameIterator(); -#endif - RefPtr<Structure> m_cachedStructure; + WriteBarrier<Structure> m_cachedStructure; WriteBarrier<StructureChain> m_cachedPrototypeChain; uint32_t m_numCacheableSlots; uint32_t m_jsStringsSize; @@ -93,12 +90,7 @@ namespace JSC { inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache) { ASSERT(!isDictionary()); - m_enumerationCache.set(globalData, enumerationCache, 0); - } - - inline void Structure::clearEnumerationCache() - { - m_enumerationCache.clear(); + m_enumerationCache.set(globalData, this, enumerationCache); } inline JSPropertyNameIterator* Structure::enumerationCache() diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h index 3e19bbc..8c3a249 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -33,7 +33,7 @@ namespace JSC{ class JSStaticScopeObject : public JSVariableObject { public: JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes) - : JSVariableObject(exec->globalData().staticScopeStructure, &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1)) + : JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1)) { m_registerStore.set(exec->globalData(), this, value); symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes)); @@ -47,7 +47,7 @@ namespace JSC{ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 9113d4a..3422dad 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -26,10 +26,10 @@ #include "CallFrame.h" #include "CommonIdentifiers.h" #include "Identifier.h" -#include "JSNumberCell.h" #include "PropertyDescriptor.h" #include "PropertySlot.h" #include "RopeImpl.h" +#include "Structure.h" namespace JSC { @@ -185,7 +185,7 @@ namespace JSC { }; ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(value.length()) , m_value(value) , m_fiberCount(0) @@ -196,7 +196,7 @@ namespace JSC { enum HasOtherOwnerType { HasOtherOwner }; JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(value.length()) , m_value(value) , m_fiberCount(0) @@ -204,7 +204,7 @@ namespace JSC { ASSERT(!m_value.isNull()); } JSString(JSGlobalData* globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(value->length()) , m_value(value) , m_fiberCount(0) @@ -212,7 +212,7 @@ namespace JSC { ASSERT(!m_value.isNull()); } JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(rope->length()) , m_fiberCount(1) { @@ -221,7 +221,7 @@ namespace JSC { // This constructor constructs a new string by concatenating s1 & s2. // This should only be called with fiberCount <= 3. JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(s1->length() + s2->length()) , m_fiberCount(fiberCount) { @@ -234,7 +234,7 @@ namespace JSC { // This constructor constructs a new string by concatenating s1 & s2. // This should only be called with fiberCount <= 3. JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(s1->length() + u2.length()) , m_fiberCount(fiberCount) { @@ -247,7 +247,7 @@ namespace JSC { // This constructor constructs a new string by concatenating s1 & s2. // This should only be called with fiberCount <= 3. JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(u1.length() + s2->length()) , m_fiberCount(fiberCount) { @@ -262,7 +262,7 @@ namespace JSC { // value must require a fiberCount of at least one implies that the length // for each value must be exactly 1! JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3) - : JSCell(exec->globalData().stringStructure.get()) + : JSCell(exec->globalData(), exec->globalData().stringStructure.get()) , m_length(0) , m_fiberCount(s_maxInternalRopeLength) { @@ -275,7 +275,7 @@ namespace JSC { // This constructor constructs a new string by concatenating u1 & u2. JSString(JSGlobalData* globalData, const UString& u1, const UString& u2) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(u1.length() + u2.length()) , m_fiberCount(2) { @@ -287,7 +287,7 @@ namespace JSC { // This constructor constructs a new string by concatenating u1, u2 & u3. JSString(JSGlobalData* globalData, const UString& u1, const UString& u2, const UString& u3) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(u1.length() + u2.length() + u3.length()) , m_fiberCount(s_maxInternalRopeLength) { @@ -299,7 +299,7 @@ namespace JSC { } JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context) - : JSCell(globalData->stringStructure.get()) + : JSCell(*globalData, globalData->stringStructure.get()) , m_length(value.length()) , m_value(value) , m_fiberCount(0) @@ -349,12 +349,11 @@ namespace JSC { JSValue replaceCharacter(ExecState*, UChar, const UString& replacement); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } private: - enum VPtrStealingHackType { VPtrStealingHack }; JSString(VPtrStealingHackType) - : JSCell(0) + : JSCell(VPtrStealingHack) , m_fiberCount(0) { } diff --git a/Source/JavaScriptCore/runtime/JSType.h b/Source/JavaScriptCore/runtime/JSType.h index 882b218..dba03f6 100644 --- a/Source/JavaScriptCore/runtime/JSType.h +++ b/Source/JavaScriptCore/runtime/JSType.h @@ -33,10 +33,11 @@ namespace JSC { NumberType = 3, NullType = 4, StringType = 5, + LeafType = 6, // The CompoundType value must come before any JSType that may have children - CompoundType = 6, - ObjectType = 7, - GetterSetterType = 8 + CompoundType = 7, + ObjectType = 8, + GetterSetterType = 9 }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h index 284d2b2..acde81f 100644 --- a/Source/JavaScriptCore/runtime/JSTypeInfo.h +++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h @@ -54,6 +54,7 @@ namespace JSC { { ASSERT(flags <= 0x1FF); ASSERT(type <= 0xFF); + ASSERT(type >= CompoundType || !(flags & OverridesMarkChildren)); // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance) if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance) m_flags |= ImplementsDefaultHasInstance; diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index 098123e..de50011 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -30,15 +30,18 @@ #include <wtf/Assertions.h> #include <wtf/HashTraits.h> #include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> namespace JSC { + extern const double NaN; + extern const double Inf; + class ExecState; class Identifier; class JSCell; class JSGlobalData; class JSGlobalObject; - class JSImmediate; class JSObject; class JSString; class PropertySlot; @@ -48,7 +51,6 @@ namespace JSC { struct ClassInfo; struct Instruction; - template <class T> class DeprecatedPtr; template <class T> class WriteBarrierBase; enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; @@ -61,7 +63,7 @@ namespace JSC { #endif union EncodedValueDescriptor { - EncodedJSValue asEncodedJSValue; + int64_t asInt64; #if USE(JSVALUE32_64) double asDouble; #elif USE(JSVALUE64) @@ -95,7 +97,6 @@ namespace JSC { } class JSValue { - friend class JSImmediate; friend struct EncodedJSValueHashTraits; friend class JIT; friend class JITStubs; @@ -104,14 +105,9 @@ namespace JSC { friend class SpecializedThunkJIT; public: - static EncodedJSValue encode(JSValue value); - static JSValue decode(EncodedJSValue ptr); -#if USE(JSVALUE64) - private: - static JSValue makeImmediate(intptr_t value); - intptr_t immediateValue(); - public: -#endif + static EncodedJSValue encode(JSValue); + static JSValue decode(EncodedJSValue); + enum JSNullTag { JSNull }; enum JSUndefinedTag { JSUndefined }; enum JSTrueTag { JSTrue }; @@ -239,7 +235,6 @@ namespace JSC { #endif private: - template <class T> JSValue(DeprecatedPtr<T>); template <class T> JSValue(WriteBarrierBase<T>); enum HashTableDeletedValueTag { HashTableDeletedValue }; @@ -253,24 +248,120 @@ namespace JSC { JSObject* synthesizeObject(ExecState*) const; #if USE(JSVALUE32_64) - enum { NullTag = 0xffffffff }; - enum { UndefinedTag = 0xfffffffe }; - enum { Int32Tag = 0xfffffffd }; - enum { CellTag = 0xfffffffc }; - enum { TrueTag = 0xfffffffb }; - enum { FalseTag = 0xfffffffa }; - enum { EmptyValueTag = 0xfffffff9 }; - enum { DeletedValueTag = 0xfffffff8 }; - + /* + * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded + * form for immediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). + * + * For JSValues that do not contain a double value, the high 32 bits contain the tag + * values listed in the enums below, which all correspond to NaN-space. In the case of + * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer + * integer or boolean value; in the case of all other tags the payload is 0. + */ + enum { Int32Tag = 0xffffffff }; + enum { BooleanTag = 0xfffffffe }; + enum { NullTag = 0xfffffffd }; + enum { UndefinedTag = 0xfffffffc }; + enum { CellTag = 0xfffffffb }; + enum { EmptyValueTag = 0xfffffffa }; + enum { DeletedValueTag = 0xfffffff9 }; + enum { LowestTag = DeletedValueTag }; uint32_t tag() const; int32_t payload() const; - - EncodedValueDescriptor u; #elif USE(JSVALUE64) - JSCell* m_ptr; + /* + * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded + * form for immediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). + * + * This range of NaN space is represented by 64-bit numbers begining with the 16-bit + * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision + * numbers will begin fall in these ranges. + * + * The top 16-bits denote the type of the encoded JSValue: + * + * Pointer { 0000:PPPP:PPPP:PPPP + * / 0001:****:****:**** + * Double { ... + * \ FFFE:****:****:**** + * Integer { FFFF:0000:IIII:IIII + * + * The scheme we have implemented encodes double precision values by performing a + * 64-bit integer addition of the value 2^48 to the number. After this manipulation + * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF. + * Values must be decoded by reversing this operation before subsequent floating point + * operations my be peformed. + * + * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. + * + * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean, + * null and undefined values are represented by specific, invalid pointer values: + * + * False: 0x06 + * True: 0x07 + * Undefined: 0x0a + * Null: 0x02 + * + * These values have the following properties: + * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be + * quickly distinguished from all immediate values, including these invalid pointers. + * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the + * same value, allowing null & undefined to be quickly detected. + * + * No valid JSValue will have the bit pattern 0x0, this is used to represent array + * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0). + */ + + // These values are #defines since using static const integers here is a ~1% regression! + + // This value is 2^48, used to encode doubles such that the encoded value will begin + // with a 16-bit pattern within the range 0x0001..0xFFFE. + #define DoubleEncodeOffset 0x1000000000000ll + // If all bits in the mask are set, this indicates an integer number, + // if any but not all are set this value is a double precision number. + #define TagTypeNumber 0xffff000000000000ll + + // All non-numeric (bool, null, undefined) immediates have bit 2 set. + #define TagBitTypeOther 0x2ll + #define TagBitBool 0x4ll + #define TagBitUndefined 0x8ll + // Combined integer value for non-numeric immediates. + #define ValueFalse (TagBitTypeOther | TagBitBool | false) + #define ValueTrue (TagBitTypeOther | TagBitBool | true) + #define ValueUndefined (TagBitTypeOther | TagBitUndefined) + #define ValueNull (TagBitTypeOther) + + // TagMask is used to check for all types of immediate values (either number or 'other'). + #define TagMask (TagTypeNumber | TagBitTypeOther) + + // These special values are never visible to JavaScript code; Empty is used to represent + // Array holes, and for uninitialized JSValues. Deleted is used in hash table code. + // These values would map to cell types in the JSValue encoding, but not valid GC cell + // pointer should have either of these values (Empty is null, deleted is at an invalid + // alignment for a GC cell, and in the zero page). + #define ValueEmpty 0x0ll + #define ValueDeleted 0x4ll #endif + + EncodedValueDescriptor u; }; #if USE(JSVALUE32_64) @@ -373,409 +464,7 @@ namespace JSC { inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } - ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const - { - if (isInt32()) - return asInt32(); - return JSC::toInt32(toNumber(exec)); - } - - inline uint32_t JSValue::toUInt32(ExecState* exec) const - { - // See comment on JSC::toUInt32, above. - return toInt32(exec); - } - -#if USE(JSVALUE32_64) - inline JSValue jsNaN() - { - return JSValue(nonInlineNaN()); - } - - // JSValue member functions. - inline EncodedJSValue JSValue::encode(JSValue value) - { - return value.u.asEncodedJSValue; - } - - inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) - { - JSValue v; - v.u.asEncodedJSValue = encodedJSValue; - return v; - } - - inline JSValue::JSValue() - { - u.asBits.tag = EmptyValueTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(JSNullTag) - { - u.asBits.tag = NullTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(JSUndefinedTag) - { - u.asBits.tag = UndefinedTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(JSTrueTag) - { - u.asBits.tag = TrueTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(JSFalseTag) - { - u.asBits.tag = FalseTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(HashTableDeletedValueTag) - { - u.asBits.tag = DeletedValueTag; - u.asBits.payload = 0; - } - - inline JSValue::JSValue(JSCell* ptr) - { - if (ptr) - u.asBits.tag = CellTag; - else - u.asBits.tag = EmptyValueTag; - u.asBits.payload = reinterpret_cast<int32_t>(ptr); -#if ENABLE(JSC_ZOMBIES) - ASSERT(!isZombie()); -#endif - } - - inline JSValue::JSValue(const JSCell* ptr) - { - if (ptr) - u.asBits.tag = CellTag; - else - u.asBits.tag = EmptyValueTag; - u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); -#if ENABLE(JSC_ZOMBIES) - ASSERT(!isZombie()); -#endif - } - - inline JSValue::operator bool() const - { - ASSERT(tag() != DeletedValueTag); - return tag() != EmptyValueTag; - } - - inline bool JSValue::operator==(const JSValue& other) const - { - return u.asEncodedJSValue == other.u.asEncodedJSValue; - } - - inline bool JSValue::operator!=(const JSValue& other) const - { - return u.asEncodedJSValue != other.u.asEncodedJSValue; - } - - inline bool JSValue::isUndefined() const - { - return tag() == UndefinedTag; - } - - inline bool JSValue::isNull() const - { - return tag() == NullTag; - } - - inline bool JSValue::isUndefinedOrNull() const - { - return isUndefined() || isNull(); - } - - inline bool JSValue::isCell() const - { - return tag() == CellTag; - } - - inline bool JSValue::isInt32() const - { - return tag() == Int32Tag; - } - - inline bool JSValue::isUInt32() const - { - return tag() == Int32Tag && asInt32() > -1; - } - - inline bool JSValue::isDouble() const - { - return tag() < LowestTag; - } - - inline bool JSValue::isTrue() const - { - return tag() == TrueTag; - } - - inline bool JSValue::isFalse() const - { - return tag() == FalseTag; - } - - inline uint32_t JSValue::tag() const - { - return u.asBits.tag; - } - - inline int32_t JSValue::payload() const - { - return u.asBits.payload; - } - - inline int32_t JSValue::asInt32() const - { - ASSERT(isInt32()); - return u.asBits.payload; - } - - inline uint32_t JSValue::asUInt32() const - { - ASSERT(isUInt32()); - return u.asBits.payload; - } - - inline double JSValue::asDouble() const - { - ASSERT(isDouble()); - return u.asDouble; - } - - ALWAYS_INLINE JSCell* JSValue::asCell() const - { - ASSERT(isCell()); - return reinterpret_cast<JSCell*>(u.asBits.payload); - } - - ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) - { - u.asDouble = d; - } - - inline JSValue::JSValue(double d) - { - const int32_t asInt32 = static_cast<int32_t>(d); - if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 - u.asDouble = d; - return; - } - *this = JSValue(static_cast<int32_t>(d)); - } - - inline JSValue::JSValue(char i) - { - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(unsigned char i) - { - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(short i) - { - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(unsigned short i) - { - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(int i) - { - u.asBits.tag = Int32Tag; - u.asBits.payload = i; - } - - inline JSValue::JSValue(unsigned i) - { - if (static_cast<int32_t>(i) < 0) { - *this = JSValue(static_cast<double>(i)); - return; - } - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(long i) - { - if (static_cast<int32_t>(i) != i) { - *this = JSValue(static_cast<double>(i)); - return; - } - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(unsigned long i) - { - if (static_cast<uint32_t>(i) != i) { - *this = JSValue(static_cast<double>(i)); - return; - } - *this = JSValue(static_cast<uint32_t>(i)); - } - - inline JSValue::JSValue(long long i) - { - if (static_cast<int32_t>(i) != i) { - *this = JSValue(static_cast<double>(i)); - return; - } - *this = JSValue(static_cast<int32_t>(i)); - } - - inline JSValue::JSValue(unsigned long long i) - { - if (static_cast<uint32_t>(i) != i) { - *this = JSValue(static_cast<double>(i)); - return; - } - *this = JSValue(static_cast<uint32_t>(i)); - } - - inline bool JSValue::isNumber() const - { - return isInt32() || isDouble(); - } - - inline bool JSValue::isBoolean() const - { - return isTrue() || isFalse(); - } - - inline bool JSValue::getBoolean(bool& v) const - { - if (isTrue()) { - v = true; - return true; - } - if (isFalse()) { - v = false; - return true; - } - - return false; - } - - inline bool JSValue::getBoolean() const - { - ASSERT(isBoolean()); - return tag() == TrueTag; - } - - inline double JSValue::uncheckedGetNumber() const - { - ASSERT(isNumber()); - return isInt32() ? asInt32() : asDouble(); - } - - ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const - { - return isNumber() ? asValue() : jsNumber(this->toNumber(exec)); - } - - inline bool JSValue::getNumber(double& result) const - { - if (isInt32()) { - result = asInt32(); - return true; - } - if (isDouble()) { - result = asDouble(); - return true; - } - return false; - } - -#else // USE(JSVALUE32_64) - - // JSValue member functions. - inline EncodedJSValue JSValue::encode(JSValue value) - { - return reinterpret_cast<EncodedJSValue>(value.m_ptr); - } - - inline JSValue JSValue::decode(EncodedJSValue ptr) - { - return JSValue(reinterpret_cast<JSCell*>(ptr)); - } - - inline JSValue JSValue::makeImmediate(intptr_t value) - { - return JSValue(reinterpret_cast<JSCell*>(value)); - } - - inline intptr_t JSValue::immediateValue() - { - return reinterpret_cast<intptr_t>(m_ptr); - } - - // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page. - inline JSValue::JSValue() - : m_ptr(0) - { - } - - // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page. - inline JSValue::JSValue(HashTableDeletedValueTag) - : m_ptr(reinterpret_cast<JSCell*>(0x4)) - { - } - - inline JSValue::JSValue(JSCell* ptr) - : m_ptr(ptr) - { -#if ENABLE(JSC_ZOMBIES) - ASSERT(!isZombie()); -#endif - } - - inline JSValue::JSValue(const JSCell* ptr) - : m_ptr(const_cast<JSCell*>(ptr)) - { -#if ENABLE(JSC_ZOMBIES) - ASSERT(!isZombie()); -#endif - } - - inline JSValue::operator bool() const - { - return m_ptr; - } - - inline bool JSValue::operator==(const JSValue& other) const - { - return m_ptr == other.m_ptr; - } - - inline bool JSValue::operator!=(const JSValue& other) const - { - return m_ptr != other.m_ptr; - } - - inline bool JSValue::isUndefined() const - { - return asValue() == jsUndefined(); - } - - inline bool JSValue::isNull() const - { - return asValue() == jsNull(); - } -#endif // USE(JSVALUE32_64) + bool isZombie(const JSCell*); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h new file mode 100644 index 0000000..b4f6f80 --- /dev/null +++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h @@ -0,0 +1,532 @@ +/* + * 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. ``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 JSValueInlineMethods_h +#define JSValueInlineMethods_h + +#include "JSValue.h" + +namespace JSC { + + ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const + { + if (isInt32()) + return asInt32(); + return JSC::toInt32(toNumber(exec)); + } + + inline uint32_t JSValue::toUInt32(ExecState* exec) const + { + // See comment on JSC::toUInt32, above. + return toInt32(exec); + } + + inline bool JSValue::isUInt32() const + { + return isInt32() && asInt32() >= 0; + } + + inline uint32_t JSValue::asUInt32() const + { + ASSERT(isUInt32()); + return asInt32(); + } + + inline double JSValue::uncheckedGetNumber() const + { + ASSERT(isNumber()); + return isInt32() ? asInt32() : asDouble(); + } + + ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const + { + return isNumber() ? asValue() : jsNumber(this->toNumber(exec)); + } + + inline JSValue jsNaN() + { + return JSValue(nonInlineNaN()); + } + + inline bool JSValue::getNumber(double& result) const + { + if (isInt32()) { + result = asInt32(); + return true; + } + if (isDouble()) { + result = asDouble(); + return true; + } + return false; + } + + inline bool JSValue::getBoolean(bool& v) const + { + if (isTrue()) { + v = true; + return true; + } + if (isFalse()) { + v = false; + return true; + } + + return false; + } + + inline JSValue::JSValue(char i) + { + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(unsigned char i) + { + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(short i) + { + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(unsigned short i) + { + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(unsigned i) + { + if (static_cast<int32_t>(i) < 0) { + *this = JSValue(EncodeAsDouble, static_cast<double>(i)); + return; + } + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(long i) + { + if (static_cast<int32_t>(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast<double>(i)); + return; + } + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(unsigned long i) + { + if (static_cast<uint32_t>(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast<double>(i)); + return; + } + *this = JSValue(static_cast<uint32_t>(i)); + } + + inline JSValue::JSValue(long long i) + { + if (static_cast<int32_t>(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast<double>(i)); + return; + } + *this = JSValue(static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(unsigned long long i) + { + if (static_cast<uint32_t>(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast<double>(i)); + return; + } + *this = JSValue(static_cast<uint32_t>(i)); + } + + inline JSValue::JSValue(double d) + { + const int32_t asInt32 = static_cast<int32_t>(d); + if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 + *this = JSValue(EncodeAsDouble, d); + return; + } + *this = JSValue(static_cast<int32_t>(d)); + } + +#if USE(JSVALUE32_64) + inline EncodedJSValue JSValue::encode(JSValue value) + { + return value.u.asInt64; + } + + inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) + { + JSValue v; + v.u.asInt64 = encodedJSValue; + return v; + } + + inline JSValue::JSValue() + { + u.asBits.tag = EmptyValueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSNullTag) + { + u.asBits.tag = NullTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSUndefinedTag) + { + u.asBits.tag = UndefinedTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSTrueTag) + { + u.asBits.tag = BooleanTag; + u.asBits.payload = 1; + } + + inline JSValue::JSValue(JSFalseTag) + { + u.asBits.tag = BooleanTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(HashTableDeletedValueTag) + { + u.asBits.tag = DeletedValueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSCell* ptr) + { + if (ptr) + u.asBits.tag = CellTag; + else + u.asBits.tag = EmptyValueTag; + u.asBits.payload = reinterpret_cast<int32_t>(ptr); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif + } + + inline JSValue::JSValue(const JSCell* ptr) + { + if (ptr) + u.asBits.tag = CellTag; + else + u.asBits.tag = EmptyValueTag; + u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif + } + + inline JSValue::operator bool() const + { + ASSERT(tag() != DeletedValueTag); + return tag() != EmptyValueTag; + } + + inline bool JSValue::operator==(const JSValue& other) const + { + return u.asInt64 == other.u.asInt64; + } + + inline bool JSValue::operator!=(const JSValue& other) const + { + return u.asInt64 != other.u.asInt64; + } + + inline bool JSValue::isUndefined() const + { + return tag() == UndefinedTag; + } + + inline bool JSValue::isNull() const + { + return tag() == NullTag; + } + + inline bool JSValue::isUndefinedOrNull() const + { + return isUndefined() || isNull(); + } + + inline bool JSValue::isCell() const + { + return tag() == CellTag; + } + + inline bool JSValue::isInt32() const + { + return tag() == Int32Tag; + } + + inline bool JSValue::isDouble() const + { + return tag() < LowestTag; + } + + inline bool JSValue::isTrue() const + { + return tag() == BooleanTag && payload(); + } + + inline bool JSValue::isFalse() const + { + return tag() == BooleanTag && !payload(); + } + + inline uint32_t JSValue::tag() const + { + return u.asBits.tag; + } + + inline int32_t JSValue::payload() const + { + return u.asBits.payload; + } + + inline int32_t JSValue::asInt32() const + { + ASSERT(isInt32()); + return u.asBits.payload; + } + + inline double JSValue::asDouble() const + { + ASSERT(isDouble()); + return u.asDouble; + } + + ALWAYS_INLINE JSCell* JSValue::asCell() const + { + ASSERT(isCell()); + return reinterpret_cast<JSCell*>(u.asBits.payload); + } + + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) + { + u.asDouble = d; + } + + inline JSValue::JSValue(int i) + { + u.asBits.tag = Int32Tag; + u.asBits.payload = i; + } + + inline bool JSValue::isNumber() const + { + return isInt32() || isDouble(); + } + + inline bool JSValue::isBoolean() const + { + return isTrue() || isFalse(); + } + + inline bool JSValue::getBoolean() const + { + ASSERT(isBoolean()); + return payload(); + } + +#else // USE(JSVALUE32_64) + + // JSValue member functions. + inline EncodedJSValue JSValue::encode(JSValue value) + { + return value.u.ptr; + } + + inline JSValue JSValue::decode(EncodedJSValue ptr) + { + return JSValue(reinterpret_cast<JSCell*>(ptr)); + } + + // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page. + inline JSValue::JSValue() + { + u.asInt64 = ValueEmpty; + } + + // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page. + inline JSValue::JSValue(HashTableDeletedValueTag) + { + u.asInt64 = ValueDeleted; + } + + inline JSValue::JSValue(JSCell* ptr) + { + u.ptr = ptr; +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif + } + + inline JSValue::JSValue(const JSCell* ptr) + { + u.ptr = const_cast<JSCell*>(ptr); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif + } + + inline JSValue::operator bool() const + { + return u.ptr; + } + + inline bool JSValue::operator==(const JSValue& other) const + { + return u.ptr == other.u.ptr; + } + + inline bool JSValue::operator!=(const JSValue& other) const + { + return u.ptr != other.u.ptr; + } + + inline bool JSValue::isUndefined() const + { + return asValue() == jsUndefined(); + } + + inline bool JSValue::isNull() const + { + return asValue() == jsNull(); + } + + inline bool JSValue::isTrue() const + { + return asValue() == JSValue(JSTrue); + } + + inline bool JSValue::isFalse() const + { + return asValue() == JSValue(JSFalse); + } + + inline bool JSValue::getBoolean() const + { + ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false)); + return asValue() == jsBoolean(true); + } + + inline int32_t JSValue::asInt32() const + { + ASSERT(isInt32()); + return static_cast<int32_t>(u.asInt64); + } + + inline bool JSValue::isDouble() const + { + return isNumber() && !isInt32(); + } + + inline JSValue::JSValue(JSNullTag) + { + u.asInt64 = ValueNull; + } + + inline JSValue::JSValue(JSUndefinedTag) + { + u.asInt64 = ValueUndefined; + } + + inline JSValue::JSValue(JSTrueTag) + { + u.asInt64 = ValueTrue; + } + + inline JSValue::JSValue(JSFalseTag) + { + u.asInt64 = ValueFalse; + } + + inline bool JSValue::isUndefinedOrNull() const + { + // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. + return (u.asInt64 & ~TagBitUndefined) == ValueNull; + } + + inline bool JSValue::isBoolean() const + { + return (u.asInt64 & ~1) == ValueFalse; + } + + inline bool JSValue::isCell() const + { + return !(u.asInt64 & TagMask); + } + + inline bool JSValue::isInt32() const + { + return (u.asInt64 & TagTypeNumber) == TagTypeNumber; + } + + inline intptr_t reinterpretDoubleToIntptr(double value) + { + return bitwise_cast<intptr_t>(value); + } + inline double reinterpretIntptrToDouble(intptr_t value) + { + return bitwise_cast<double>(value); + } + + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) + { + u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset; + } + + inline JSValue::JSValue(int i) + { + u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i); + } + + inline double JSValue::asDouble() const + { + return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset); + } + + inline bool JSValue::isNumber() const + { + return u.asInt64 & TagTypeNumber; + } + + ALWAYS_INLINE JSCell* JSValue::asCell() const + { + ASSERT(isCell()); + return u.ptr; + } + +#endif // USE(JSVALUE64) + +} // namespace JSC + +#endif // JSValueInlineMethods_h diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 891ada8..89bb6b0 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -58,7 +58,7 @@ namespace JSC { WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -66,8 +66,8 @@ namespace JSC { protected: static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags; - JSVariableObject(NonNullPassRefPtr<Structure> structure, SymbolTable* symbolTable, Register* registers) - : JSNonFinalObject(structure) + JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers) + : JSNonFinalObject(globalData, structure) , m_symbolTable(symbolTable) , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) { @@ -75,7 +75,7 @@ namespace JSC { COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier); } - PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count); + PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts); void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray); bool symbolTableGet(const Identifier&, PropertySlot&); @@ -137,10 +137,12 @@ namespace JSC { return true; } - inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count) + inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts) { OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]); - for (size_t i = 0; i < count; i++) + for (size_t i = 0; i < callframeStarts; i++) + registerArray[i].set(globalData, this, src[i].get()); + for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++) registerArray[i].set(globalData, this, src[i].get()); return registerArray.release(); diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h index 63833e9..a7dbe0d 100644 --- a/Source/JavaScriptCore/runtime/JSWrapperObject.h +++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h @@ -30,13 +30,13 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSNonFinalObject { protected: - explicit JSWrapperObject(NonNullPassRefPtr<Structure>); + explicit JSWrapperObject(JSGlobalData&, Structure*); public: JSValue internalValue() const; void setInternalValue(JSGlobalData&, JSValue); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -50,8 +50,8 @@ namespace JSC { WriteBarrier<Unknown> m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure) - : JSNonFinalObject(structure) + inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure) + : JSNonFinalObject(globalData, structure) { } diff --git a/Source/JavaScriptCore/runtime/JSZombie.cpp b/Source/JavaScriptCore/runtime/JSZombie.cpp index 23cf135..efabc93 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.cpp +++ b/Source/JavaScriptCore/runtime/JSZombie.cpp @@ -35,16 +35,6 @@ namespace JSC { const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 }; -Structure* JSZombie::leakedZombieStructure() { - static Structure* structure = 0; - if (!structure) { - Structure::startIgnoringLeaks(); - structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &s_info).leakRef(); - Structure::stopIgnoringLeaks(); - } - return structure; -} - } #endif // ENABLE(JSC_ZOMBIES) diff --git a/Source/JavaScriptCore/runtime/JSZombie.h b/Source/JavaScriptCore/runtime/JSZombie.h index 179ff53..0559b96 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.h +++ b/Source/JavaScriptCore/runtime/JSZombie.h @@ -27,21 +27,21 @@ #define JSZombie_h #include "JSCell.h" +#include "Structure.h" #if ENABLE(JSC_ZOMBIES) namespace JSC { class JSZombie : public JSCell { public: - JSZombie(const ClassInfo* oldInfo, Structure* structure) - : JSCell(structure) + JSZombie(JSGlobalData& globalData, const ClassInfo* oldInfo, Structure* structure) + : JSCell(globalData, structure) , m_oldInfo(oldInfo) { ASSERT(inherits(&s_info)); } virtual bool isZombie() const { return true; } - static Structure* leakedZombieStructure(); virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; } virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; } @@ -66,9 +66,9 @@ public: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(globalData, prototype, TypeInfo(ObjectType, 0), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), AnonymousSlotCount, &s_info); } static const ClassInfo s_info; diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp index 307bceb..25b516e 100644 --- a/Source/JavaScriptCore/runtime/Lookup.cpp +++ b/Source/JavaScriptCore/runtime/Lookup.cpp @@ -73,7 +73,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); - WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(propertyName); + WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName); if (!location) { JSFunction* function; @@ -86,7 +86,7 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, entry->function()); thisObj->putDirectFunction(exec->globalData(), propertyName, function, entry->attributes()); - location = thisObj->getDirectLocation(propertyName); + location = thisObj->getDirectLocation(exec->globalData(), propertyName); } slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location)); diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp deleted file mode 100644 index 3e205a1..0000000 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) 2009 Acision BV. 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 - * - */ - -#include "config.h" -#include "MachineStackMarker.h" - -#include "ConservativeSet.h" -#include "Heap.h" -#include "JSArray.h" -#include "JSGlobalData.h" -#include <setjmp.h> -#include <stdlib.h> -#include <wtf/StdLibExtras.h> - -#if USE(PTHREAD_BASED_QT) && !defined(WTF_USE_PTHREADS) -#define WTF_USE_PTHREADS 1 -#endif - -#if OS(DARWIN) - -#include <mach/mach_init.h> -#include <mach/mach_port.h> -#include <mach/task.h> -#include <mach/thread_act.h> -#include <mach/vm_map.h> - -#elif OS(WINDOWS) - -#include <windows.h> -#include <malloc.h> - -#elif OS(HAIKU) - -#include <OS.h> - -#elif OS(UNIX) - -#include <stdlib.h> -#if !OS(HAIKU) -#include <sys/mman.h> -#endif -#include <unistd.h> - -#if OS(SOLARIS) -#include <thread.h> -#else -#include <pthread.h> -#endif - -#if HAVE(PTHREAD_NP_H) -#include <pthread_np.h> -#endif - -#if OS(QNX) -#include <fcntl.h> -#include <sys/procfs.h> -#include <stdio.h> -#include <errno.h> -#endif - -#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) -#include <signal.h> -#ifndef SA_RESTART -#error MachineThreads requires SA_RESTART -#endif -#endif - -#endif - -using namespace WTF; - -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) -typedef mach_port_t PlatformThread; -#elif OS(WINDOWS) -typedef HANDLE PlatformThread; -#elif USE(PTHREADS) -typedef pthread_t PlatformThread; -static const int SigThreadSuspendResume = SIGUSR2; - -static void pthreadSignalHandlerSuspendResume(int signo) -{ - sigset_t signalSet; - sigemptyset(&signalSet); - sigaddset(&signalSet, SigThreadSuspendResume); - sigsuspend(&signalSet); -} -#endif - -class MachineThreads::Thread { -public: - Thread(pthread_t pthread, const PlatformThread& platThread, void* base) - : posixThread(pthread) - , platformThread(platThread) - , stackBase(base) - { -#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) - struct sigaction action; - action.sa_handler = pthreadSignalHandlerSuspendResume; - sigemptyset(&action.sa_mask); - action.sa_flags = SA_RESTART; - sigaction(SigThreadSuspendResume, &action, 0); - - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SigThreadSuspendResume); - pthread_sigmask(SIG_UNBLOCK, &mask, 0); -#endif - } - - Thread* next; - pthread_t posixThread; - PlatformThread platformThread; - void* stackBase; -}; - -#endif - -MachineThreads::MachineThreads(Heap* heap) - : m_heap(heap) -#if ENABLE(JSC_MULTIPLE_THREADS) - , m_registeredThreads(0) - , m_threadSpecific(0) -#endif -{ -} - -MachineThreads::~MachineThreads() -{ -#if ENABLE(JSC_MULTIPLE_THREADS) - if (m_threadSpecific) { - int error = pthread_key_delete(m_threadSpecific); - ASSERT_UNUSED(error, !error); - } - - MutexLocker registeredThreadsLock(m_registeredThreadsMutex); - for (Thread* t = m_registeredThreads; t;) { - Thread* next = t->next; - delete t; - t = next; - } -#endif -} - -#if ENABLE(JSC_MULTIPLE_THREADS) - -static inline PlatformThread getCurrentPlatformThread() -{ -#if OS(DARWIN) - return pthread_mach_thread_np(pthread_self()); -#elif OS(WINDOWS) - return pthread_getw32threadhandle_np(pthread_self()); -#elif USE(PTHREADS) - return pthread_self(); -#endif -} - -void MachineThreads::makeUsableFromMultipleThreads() -{ - if (m_threadSpecific) - return; - - int error = pthread_key_create(&m_threadSpecific, removeThread); - if (error) - CRASH(); -} - -void MachineThreads::addCurrentThread() -{ - ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - - if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) - return; - - pthread_setspecific(m_threadSpecific, this); - Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin()); - - MutexLocker lock(m_registeredThreadsMutex); - - thread->next = m_registeredThreads; - m_registeredThreads = thread; -} - -void MachineThreads::removeThread(void* p) -{ - if (p) - static_cast<MachineThreads*>(p)->removeCurrentThread(); -} - -void MachineThreads::removeCurrentThread() -{ - pthread_t currentPosixThread = pthread_self(); - - MutexLocker lock(m_registeredThreadsMutex); - - if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) { - Thread* t = m_registeredThreads; - m_registeredThreads = m_registeredThreads->next; - delete t; - } else { - Thread* last = m_registeredThreads; - Thread* t; - for (t = m_registeredThreads->next; t; t = t->next) { - if (pthread_equal(t->posixThread, currentPosixThread)) { - last->next = t->next; - break; - } - last = t; - } - ASSERT(t); // If t is NULL, we never found ourselves in the list. - delete t; - } -} - -#endif - -#if COMPILER(GCC) -#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) -#else -#define REGISTER_BUFFER_ALIGNMENT -#endif - -void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, void* stackCurrent) -{ - // setjmp forces volatile registers onto the stack - jmp_buf registers REGISTER_BUFFER_ALIGNMENT; -#if COMPILER(MSVC) -#pragma warning(push) -#pragma warning(disable: 4611) -#endif - setjmp(registers); -#if COMPILER(MSVC) -#pragma warning(pop) -#endif - - void* registersBegin = ®isters; - void* registersEnd = reinterpret_cast<void*>(roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(®isters + 1))); - swapIfBackwards(registersBegin, registersEnd); - conservativeRoots.add(registersBegin, registersEnd); - - void* stackBegin = stackCurrent; - void* stackEnd = m_heap->globalData()->stack().origin(); - swapIfBackwards(stackBegin, stackEnd); - conservativeRoots.add(stackBegin, stackEnd); -} - -#if ENABLE(JSC_MULTIPLE_THREADS) - -static inline void suspendThread(const PlatformThread& platformThread) -{ -#if OS(DARWIN) - thread_suspend(platformThread); -#elif OS(WINDOWS) - SuspendThread(platformThread); -#elif USE(PTHREADS) - pthread_kill(platformThread, SigThreadSuspendResume); -#else -#error Need a way to suspend threads on this platform -#endif -} - -static inline void resumeThread(const PlatformThread& platformThread) -{ -#if OS(DARWIN) - thread_resume(platformThread); -#elif OS(WINDOWS) - ResumeThread(platformThread); -#elif USE(PTHREADS) - pthread_kill(platformThread, SigThreadSuspendResume); -#else -#error Need a way to resume threads on this platform -#endif -} - -typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit - -#if OS(DARWIN) - -#if CPU(X86) -typedef i386_thread_state_t PlatformThreadRegisters; -#elif CPU(X86_64) -typedef x86_thread_state64_t PlatformThreadRegisters; -#elif CPU(PPC) -typedef ppc_thread_state_t PlatformThreadRegisters; -#elif CPU(PPC64) -typedef ppc_thread_state64_t PlatformThreadRegisters; -#elif CPU(ARM) -typedef arm_thread_state_t PlatformThreadRegisters; -#else -#error Unknown Architecture -#endif - -#elif OS(WINDOWS) && CPU(X86) -typedef CONTEXT PlatformThreadRegisters; -#elif USE(PTHREADS) -typedef pthread_attr_t PlatformThreadRegisters; -#else -#error Need a thread register struct for this platform -#endif - -static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) -{ -#if OS(DARWIN) - -#if CPU(X86) - unsigned user_count = sizeof(regs)/sizeof(int); - thread_state_flavor_t flavor = i386_THREAD_STATE; -#elif CPU(X86_64) - unsigned user_count = x86_THREAD_STATE64_COUNT; - thread_state_flavor_t flavor = x86_THREAD_STATE64; -#elif CPU(PPC) - unsigned user_count = PPC_THREAD_STATE_COUNT; - thread_state_flavor_t flavor = PPC_THREAD_STATE; -#elif CPU(PPC64) - unsigned user_count = PPC_THREAD_STATE64_COUNT; - thread_state_flavor_t flavor = PPC_THREAD_STATE64; -#elif CPU(ARM) - unsigned user_count = ARM_THREAD_STATE_COUNT; - thread_state_flavor_t flavor = ARM_THREAD_STATE; -#else -#error Unknown Architecture -#endif - - kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)®s, &user_count); - if (result != KERN_SUCCESS) { - WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, - "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result); - CRASH(); - } - return user_count * sizeof(usword_t); -// end OS(DARWIN) - -#elif OS(WINDOWS) && CPU(X86) - regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; - GetThreadContext(platformThread, ®s); - return sizeof(CONTEXT); -#elif USE(PTHREADS) - pthread_attr_init(®s); -#if HAVE(PTHREAD_NP_H) || OS(NETBSD) - // e.g. on FreeBSD 5.4, neundorf@kde.org - pthread_attr_get_np(platformThread, ®s); -#else - // FIXME: this function is non-portable; other POSIX systems may have different np alternatives - pthread_getattr_np(platformThread, ®s); -#endif - return 0; -#else -#error Need a way to get thread registers on this platform -#endif -} - -static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) -{ -#if OS(DARWIN) - -#if __DARWIN_UNIX03 - -#if CPU(X86) - return reinterpret_cast<void*>(regs.__esp); -#elif CPU(X86_64) - return reinterpret_cast<void*>(regs.__rsp); -#elif CPU(PPC) || CPU(PPC64) - return reinterpret_cast<void*>(regs.__r1); -#elif CPU(ARM) - return reinterpret_cast<void*>(regs.__sp); -#else -#error Unknown Architecture -#endif - -#else // !__DARWIN_UNIX03 - -#if CPU(X86) - return reinterpret_cast<void*>(regs.esp); -#elif CPU(X86_64) - return reinterpret_cast<void*>(regs.rsp); -#elif CPU(PPC) || CPU(PPC64) - return reinterpret_cast<void*>(regs.r1); -#else -#error Unknown Architecture -#endif - -#endif // __DARWIN_UNIX03 - -// end OS(DARWIN) -#elif CPU(X86) && OS(WINDOWS) - return reinterpret_cast<void*>((uintptr_t) regs.Esp); -#elif USE(PTHREADS) - void* stackBase = 0; - size_t stackSize = 0; - int rc = pthread_attr_getstack(®s, &stackBase, &stackSize); - (void)rc; // FIXME: Deal with error code somehow? Seems fatal. - ASSERT(stackBase); - return static_cast<char*>(stackBase) + stackSize; -#else -#error Need a way to get the stack pointer for another thread on this platform -#endif -} - -static void freePlatformThreadRegisters(PlatformThreadRegisters& regs) -{ -#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) - pthread_attr_destroy(®s); -#else - UNUSED_PARAM(regs); -#endif -} - -void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread) -{ - suspendThread(thread->platformThread); - - PlatformThreadRegisters regs; - size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); - - conservativeRoots.add(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); - - void* stackPointer = otherThreadStackPointer(regs); - void* stackBase = thread->stackBase; - swapIfBackwards(stackPointer, stackBase); - conservativeRoots.add(stackPointer, stackBase); - - resumeThread(thread->platformThread); - - freePlatformThreadRegisters(regs); -} - -#endif - -void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent) -{ - gatherFromCurrentThread(conservativeRoots, stackCurrent); - -#if ENABLE(JSC_MULTIPLE_THREADS) - - if (m_threadSpecific) { - - MutexLocker lock(m_registeredThreadsMutex); - -#ifndef NDEBUG - // Forbid malloc during the gather phase. The gather phase suspends - // threads, so a malloc during gather would risk a deadlock with a - // thread that had been suspended while holding the malloc lock. - fastMallocForbid(); -#endif - // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held, - // and since this is a shared heap, they are real locks. - for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { - if (!pthread_equal(thread->posixThread, pthread_self())) - gatherFromOtherThread(conservativeRoots, thread); - } -#ifndef NDEBUG - fastMallocAllow(); -#endif - } -#endif -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h deleted file mode 100644 index c814ac5..0000000 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 MachineThreads_h -#define MachineThreads_h - -#include <wtf/Noncopyable.h> -#include <wtf/ThreadingPrimitives.h> - -#if ENABLE(JSC_MULTIPLE_THREADS) -#include <pthread.h> -#endif - -namespace JSC { - - class Heap; - class ConservativeRoots; - - class MachineThreads { - WTF_MAKE_NONCOPYABLE(MachineThreads); - public: - MachineThreads(Heap*); - ~MachineThreads(); - - void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent); - -#if ENABLE(JSC_MULTIPLE_THREADS) - void makeUsableFromMultipleThreads(); - void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads. -#endif - - private: - void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent); - -#if ENABLE(JSC_MULTIPLE_THREADS) - class Thread; - - static void removeThread(void*); - void removeCurrentThread(); - - void gatherFromOtherThread(ConservativeRoots&, Thread*); -#endif - - Heap* m_heap; - -#if ENABLE(JSC_MULTIPLE_THREADS) - Mutex m_registeredThreadsMutex; - Thread* m_registeredThreads; - pthread_key_t m_threadSpecific; -#endif - }; - -} // namespace JSC - -#endif // MachineThreads_h diff --git a/Source/JavaScriptCore/runtime/MarkStack.cpp b/Source/JavaScriptCore/runtime/MarkStack.cpp deleted file mode 100644 index e9d1b13..0000000 --- a/Source/JavaScriptCore/runtime/MarkStack.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2009, 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. ``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 "MarkStack.h" - -#include "ConservativeSet.h" -#include "Heap.h" -#include "JSArray.h" -#include "JSCell.h" -#include "JSObject.h" -#include "ScopeChain.h" -#include "Structure.h" - -namespace JSC { - -size_t MarkStack::s_pageSize = 0; - -void MarkStack::compact() -{ - ASSERT(s_pageSize); - m_values.shrinkAllocation(s_pageSize); - m_markSets.shrinkAllocation(s_pageSize); -} - -void MarkStack::append(ConservativeRoots& conservativeRoots) -{ - JSCell** roots = conservativeRoots.roots(); - size_t size = conservativeRoots.size(); - for (size_t i = 0; i < size; ++i) - internalAppend(roots[i]); -} - -inline void MarkStack::markChildren(JSCell* cell) -{ - ASSERT(Heap::isMarked(cell)); - if (!cell->structure()->typeInfo().overridesMarkChildren()) { -#ifdef NDEBUG - asObject(cell)->markChildrenDirect(*this); -#else - ASSERT(!m_isCheckingForDefaultMarkViolation); - m_isCheckingForDefaultMarkViolation = true; - cell->markChildren(*this); - ASSERT(m_isCheckingForDefaultMarkViolation); - m_isCheckingForDefaultMarkViolation = false; -#endif - return; - } - if (cell->vptr() == m_jsArrayVPtr) { - asArray(cell)->markChildrenDirect(*this); - return; - } - cell->markChildren(*this); -} - -void MarkStack::drain() -{ -#if !ASSERT_DISABLED - ASSERT(!m_isDraining); - m_isDraining = true; -#endif - while (!m_markSets.isEmpty() || !m_values.isEmpty()) { - while (!m_markSets.isEmpty() && m_values.size() < 50) { - ASSERT(!m_markSets.isEmpty()); - MarkSet& current = m_markSets.last(); - ASSERT(current.m_values); - JSValue* end = current.m_end; - ASSERT(current.m_values); - ASSERT(current.m_values != end); - findNextUnmarkedNullValue: - ASSERT(current.m_values != end); - JSValue value = *current.m_values; - current.m_values++; - - JSCell* cell; - if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) { - if (current.m_values == end) { - m_markSets.removeLast(); - continue; - } - goto findNextUnmarkedNullValue; - } - - if (cell->structure()->typeInfo().type() < CompoundType) { - if (current.m_values == end) { - m_markSets.removeLast(); - continue; - } - goto findNextUnmarkedNullValue; - } - - if (current.m_values == end) - m_markSets.removeLast(); - - markChildren(cell); - } - while (!m_values.isEmpty()) - markChildren(m_values.removeLast()); - } -#if !ASSERT_DISABLED - m_isDraining = false; -#endif -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MarkStack.h b/Source/JavaScriptCore/runtime/MarkStack.h deleted file mode 100644 index 7131917..0000000 --- a/Source/JavaScriptCore/runtime/MarkStack.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2009, 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. ``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 MarkStack_h -#define MarkStack_h - -#include "JSValue.h" -#include "Register.h" -#include "WriteBarrier.h" -#include <wtf/Vector.h> -#include <wtf/Noncopyable.h> -#include <wtf/OSAllocator.h> - -namespace JSC { - - class ConservativeRoots; - class JSGlobalData; - class Register; - - enum MarkSetProperties { MayContainNullValues, NoNullValues }; - - class MarkStack { - WTF_MAKE_NONCOPYABLE(MarkStack); - public: - MarkStack(void* jsArrayVPtr) - : m_jsArrayVPtr(jsArrayVPtr) -#if !ASSERT_DISABLED - , m_isCheckingForDefaultMarkViolation(false) - , m_isDraining(false) -#endif - { - } - - ~MarkStack() - { - ASSERT(m_markSets.isEmpty()); - ASSERT(m_values.isEmpty()); - } - - 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) - { - JSValue* values = reinterpret_cast<JSValue*>(registers); - if (count) - m_markSets.append(MarkSet(values, values + count, properties)); - } - - 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)); - } - - void append(ConservativeRoots&); - - void drain(); - void compact(); - - private: - friend class HeapRootMarker; // Allowed to mark a JSValue* or JSCell** directly. - void append(JSValue*); - void append(JSValue*, size_t count); - void append(JSCell**); - - void internalAppend(JSCell*); - void internalAppend(JSValue); - void markChildren(JSCell*); - - struct MarkSet { - MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties) - : m_values(values) - , m_end(end) - , m_properties(properties) - { - ASSERT(values); - } - JSValue* m_values; - JSValue* m_end; - MarkSetProperties m_properties; - }; - - static void* allocateStack(size_t size) { return OSAllocator::reserveAndCommit(size); } - static void releaseStack(void* addr, size_t size) { OSAllocator::decommitAndRelease(addr, size); } - - static void initializePagesize(); - static size_t pageSize() - { - if (!s_pageSize) - initializePagesize(); - return s_pageSize; - } - - template <typename T> struct MarkStackArray { - MarkStackArray() - : m_top(0) - , m_allocated(MarkStack::pageSize()) - , m_capacity(m_allocated / sizeof(T)) - { - m_data = reinterpret_cast<T*>(allocateStack(m_allocated)); - } - - ~MarkStackArray() - { - releaseStack(m_data, m_allocated); - } - - void expand() - { - size_t oldAllocation = m_allocated; - m_allocated *= 2; - m_capacity = m_allocated / sizeof(T); - void* newData = allocateStack(m_allocated); - memcpy(newData, m_data, oldAllocation); - releaseStack(m_data, oldAllocation); - m_data = reinterpret_cast<T*>(newData); - } - - inline void append(const T& v) - { - if (m_top == m_capacity) - expand(); - m_data[m_top++] = v; - } - - inline T removeLast() - { - ASSERT(m_top); - return m_data[--m_top]; - } - - inline T& last() - { - ASSERT(m_top); - return m_data[m_top - 1]; - } - - inline bool isEmpty() - { - return m_top == 0; - } - - inline size_t size() { return m_top; } - - inline void shrinkAllocation(size_t size) - { - ASSERT(size <= m_allocated); - ASSERT(0 == (size % MarkStack::pageSize())); - if (size == m_allocated) - return; -#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP) - // We cannot release a part of a region with VirtualFree. To get around this, - // we'll release the entire region and reallocate the size that we want. - releaseStack(m_data, m_allocated); - m_data = reinterpret_cast<T*>(allocateStack(size)); -#else - releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size); -#endif - m_allocated = size; - m_capacity = m_allocated / sizeof(T); - } - - private: - size_t m_top; - size_t m_allocated; - size_t m_capacity; - T* m_data; - }; - - void* m_jsArrayVPtr; - MarkStackArray<MarkSet> m_markSets; - MarkStackArray<JSCell*> m_values; - static size_t s_pageSize; - -#if !ASSERT_DISABLED - public: - bool m_isCheckingForDefaultMarkViolation; - bool m_isDraining; -#endif - }; - - inline void MarkStack::append(JSValue* slot, size_t count) - { - if (!count) - return; - m_markSets.append(MarkSet(slot, slot + count, NoNullValues)); - } - - template <typename T> inline void MarkStack::append(DeprecatedPtr<T>* slot) - { - internalAppend(*slot->slot()); - } - - template <typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot) - { - internalAppend(*slot->slot()); - } - - 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::append(JSValue* value) - { - ASSERT(value); - internalAppend(*value); - } - - ALWAYS_INLINE void MarkStack::append(JSCell** 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()) - internalAppend(value.asCell()); - } - - // Privileged class for marking JSValues directly. It is only safe to use - // this class to mark direct heap roots that are marked during every GC pass. - // All other references should be wrapped in WriteBarriers and marked through - // the MarkStack. - class HeapRootMarker { - private: - friend class Heap; - HeapRootMarker(MarkStack&); - - public: - void mark(JSValue*); - void mark(JSValue*, size_t); - void mark(JSString**); - void mark(JSCell**); - - private: - MarkStack& m_markStack; - }; - - inline HeapRootMarker::HeapRootMarker(MarkStack& markStack) - : m_markStack(markStack) - { - } - - inline void HeapRootMarker::mark(JSValue* slot) - { - m_markStack.append(slot); - } - - inline void HeapRootMarker::mark(JSValue* slot, size_t count) - { - m_markStack.append(slot, count); - } - - inline void HeapRootMarker::mark(JSString** slot) - { - m_markStack.append(reinterpret_cast<JSCell**>(slot)); - } - - inline void HeapRootMarker::mark(JSCell** slot) - { - m_markStack.append(slot); - } - -} // namespace JSC - -#endif diff --git a/Source/JavaScriptCore/runtime/MarkStackPosix.cpp b/Source/JavaScriptCore/runtime/MarkStackPosix.cpp deleted file mode 100644 index 2a5b298..0000000 --- a/Source/JavaScriptCore/runtime/MarkStackPosix.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -#include "config.h" -#include "MarkStack.h" - -#if OS(UNIX) && !OS(SYMBIAN) - -#include <unistd.h> -#include <sys/mman.h> - -namespace JSC { - -void MarkStack::initializePagesize() -{ - MarkStack::s_pageSize = getpagesize(); -} - -} - -#endif diff --git a/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp b/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp deleted file mode 100644 index a3893d7..0000000 --- a/Source/JavaScriptCore/runtime/MarkStackSymbian.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" -#include "MarkStack.h" - -#if OS(SYMBIAN) - -#include <e32hal.h> - -namespace JSC { - -void MarkStack::initializePagesize() -{ - TInt page_size; - UserHal::PageSizeInBytes(page_size); - MarkStack::s_pageSize = page_size; -} - -} - -#endif diff --git a/Source/JavaScriptCore/runtime/MarkStackWin.cpp b/Source/JavaScriptCore/runtime/MarkStackWin.cpp deleted file mode 100644 index 2d2a1b3..0000000 --- a/Source/JavaScriptCore/runtime/MarkStackWin.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -#include "config.h" -#include "MarkStack.h" - -#if OS(WINDOWS) - -#include "windows.h" - -namespace JSC { - -void MarkStack::initializePagesize() -{ - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - MarkStack::s_pageSize = system_info.dwPageSize; -} - -} - -#endif diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp deleted file mode 100644 index cae701f..0000000 --- a/Source/JavaScriptCore/runtime/MarkedBlock.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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" -#include "JSObject.h" -#include "JSZombie.h" -#include "ScopeChain.h" - -namespace JSC { - -MarkedBlock* MarkedBlock::create(JSGlobalData* globalData, size_t cellSize) -{ - PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages); - if (!static_cast<bool>(allocation)) - CRASH(); - return new (allocation.base()) MarkedBlock(allocation, globalData, cellSize); -} - -void MarkedBlock::destroy(MarkedBlock* block) -{ - for (size_t i = block->firstAtom(); i < block->m_endAtom; i += block->m_atomsPerCell) - reinterpret_cast<JSCell*>(&block->atoms()[i])->~JSCell(); - block->m_allocation.deallocate(); -} - -MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData, size_t cellSize) - : m_nextAtom(firstAtom()) - , m_allocation(allocation) - , m_heap(&globalData->heap) - , m_prev(0) - , m_next(0) -{ - m_atomsPerCell = (cellSize + atomSize - 1) / atomSize; - m_endAtom = atomsPerBlock - m_atomsPerCell + 1; - - Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get(); - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) - new (&atoms()[i]) JSCell(dummyMarkableCellStructure); -} - -void MarkedBlock::sweep() -{ -#if !ENABLE(JSC_ZOMBIES) - Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get(); -#endif - - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - if (m_marks.get(i)) - continue; - - JSCell* cell = reinterpret_cast<JSCell*>(&atoms()[i]); -#if ENABLE(JSC_ZOMBIES) - if (!cell->isZombie()) { - const ClassInfo* info = cell->classInfo(); - cell->~JSCell(); - new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); - m_marks.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 deleted file mode 100644 index 0e2b59c..0000000 --- a/Source/JavaScriptCore/runtime/MarkedBlock.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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/PageAllocationAligned.h> -#include <wtf/StdLibExtras.h> - -namespace JSC { - - class Heap; - class JSCell; - class JSGlobalData; - - typedef uintptr_t Bits; - - static const size_t KB = 1024; - - class MarkedBlock { - public: - static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types. - - static MarkedBlock* create(JSGlobalData*, size_t cellSize); - static void destroy(MarkedBlock*); - - static bool isAtomAligned(const void*); - static MarkedBlock* blockFor(const void*); - static size_t firstAtom(); - - Heap* heap() const; - - void setPrev(MarkedBlock*); - void setNext(MarkedBlock*); - MarkedBlock* prev() const; - MarkedBlock* next() const; - - void* allocate(); - void reset(); - void sweep(); - - bool isEmpty(); - - void clearMarks(); - size_t markCount(); - - size_t cellSize(); - - size_t size(); - size_t capacity(); - - bool contains(const void*); - size_t atomNumber(const void*); - bool isMarked(const void*); - bool testAndSetMarked(const void*); - void setMarked(const void*); - - template <typename Functor> void forEach(Functor&); - - private: - static const size_t blockSize = 16 * KB; - static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. - - static const size_t atomMask = ~(atomSize - 1); // atomSize must be a power of two. - - static const size_t atomsPerBlock = blockSize / atomSize; - - typedef char Atom[atomSize]; - - MarkedBlock(const PageAllocationAligned&, JSGlobalData*, size_t cellSize); - Atom* atoms(); - - size_t m_nextAtom; - size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom. - size_t m_atomsPerCell; - WTF::Bitmap<blockSize / atomSize> m_marks; - PageAllocationAligned m_allocation; - Heap* m_heap; - MarkedBlock* m_prev; - MarkedBlock* m_next; - }; - - inline size_t MarkedBlock::firstAtom() - { - return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; - } - - inline MarkedBlock::Atom* MarkedBlock::atoms() - { - return reinterpret_cast<Atom*>(this); - } - - inline bool MarkedBlock::isAtomAligned(const void* p) - { - return !((intptr_t)(p) & ~atomMask); - } - - inline MarkedBlock* MarkedBlock::blockFor(const void* p) - { - return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & blockMask); - } - - inline Heap* MarkedBlock::heap() const - { - return m_heap; - } - - inline void MarkedBlock::setPrev(MarkedBlock* prev) - { - m_prev = prev; - } - - inline void MarkedBlock::setNext(MarkedBlock* next) - { - m_next = next; - } - - inline MarkedBlock* MarkedBlock::prev() const - { - return m_prev; - } - - inline MarkedBlock* MarkedBlock::next() const - { - return m_next; - } - - inline void MarkedBlock::reset() - { - m_nextAtom = firstAtom(); - } - - inline bool MarkedBlock::isEmpty() - { - return m_marks.isEmpty(); - } - - inline void MarkedBlock::clearMarks() - { - m_marks.clearAll(); - } - - inline size_t MarkedBlock::markCount() - { - return m_marks.count(); - } - - inline size_t MarkedBlock::cellSize() - { - return m_atomsPerCell * atomSize; - } - - inline size_t MarkedBlock::size() - { - return markCount() * cellSize(); - } - - inline size_t MarkedBlock::capacity() - { - return m_allocation.size(); - } - - inline bool MarkedBlock::contains(const void* p) - { - // Since we mark the first atom of every cell when allocating and/or - // marking, any pointer to a marked atom points to the head of a valid, - // live cell. Checking the mark bit guards against reviving an object - // in a zombie state. - - ASSERT(p && isAtomAligned(p)); - return isMarked(p); - } - - inline size_t MarkedBlock::atomNumber(const void* p) - { - return (reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(this)) / atomSize; - } - - inline bool MarkedBlock::isMarked(const void* p) - { - return m_marks.get(atomNumber(p)); - } - - inline bool MarkedBlock::testAndSetMarked(const void* p) - { - return m_marks.testAndSet(atomNumber(p)); - } - - inline void MarkedBlock::setMarked(const void* p) - { - m_marks.set(atomNumber(p)); - } - - template <typename Functor> inline void MarkedBlock::forEach(Functor& functor) - { - for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { - if (!m_marks.get(i)) - continue; - functor(reinterpret_cast<JSCell*>(&atoms()[i])); - } - } - -} // namespace JSC - -#endif // MarkedSpace_h diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp deleted file mode 100644 index d9a1e42..0000000 --- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * 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 - * - */ - -#include "config.h" -#include "MarkedSpace.h" - -#include "JSCell.h" -#include "JSGlobalData.h" -#include "JSLock.h" -#include "JSObject.h" -#include "ScopeChain.h" - -namespace JSC { - -class Structure; - -MarkedSpace::MarkedSpace(JSGlobalData* globalData) - : m_waterMark(0) - , m_highWaterMark(0) - , m_globalData(globalData) -{ - for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep) - sizeClassFor(cellSize).cellSize = cellSize; - - for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep) - sizeClassFor(cellSize).cellSize = cellSize; -} - -void MarkedSpace::destroy() -{ - clearMarks(); - shrink(); - ASSERT(!size()); -} - -MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass) -{ - MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize); - sizeClass.blockList.append(block); - sizeClass.nextBlock = block; - m_blocks.add(block); - - return block; -} - -void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks) -{ - MarkedBlock* next; - for (MarkedBlock* block = blocks.head(); block; block = next) { - next = block->next(); - - blocks.remove(block); - m_blocks.remove(block); - MarkedBlock::destroy(block); - } -} - -void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass) -{ - for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) { - if (void* result = block->allocate()) - return result; - - m_waterMark += block->capacity(); - } - - if (m_waterMark < m_highWaterMark) - return allocateBlock(sizeClass)->allocate(); - - return 0; -} - -void MarkedSpace::shrink() -{ - // We record a temporary list of empties to avoid modifying m_blocks while iterating it. - DoublyLinkedList<MarkedBlock> empties; - - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) { - MarkedBlock* block = *it; - if (block->isEmpty()) { - SizeClass& sizeClass = sizeClassFor(block->cellSize()); - sizeClass.blockList.remove(block); - sizeClass.nextBlock = sizeClass.blockList.head(); - empties.append(block); - } - } - - freeBlocks(empties); - ASSERT(empties.isEmpty()); -} - -void MarkedSpace::clearMarks() -{ - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - (*it)->clearMarks(); -} - -void MarkedSpace::sweep() -{ - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - (*it)->sweep(); -} - -size_t MarkedSpace::objectCount() const -{ - size_t result = 0; - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - result += (*it)->markCount(); - return result; -} - -size_t MarkedSpace::size() const -{ - size_t result = 0; - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - result += (*it)->size(); - return result; -} - -size_t MarkedSpace::capacity() const -{ - size_t result = 0; - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - result += (*it)->capacity(); - return result; -} - -void MarkedSpace::reset() -{ - m_waterMark = 0; - - for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep) - sizeClassFor(cellSize).reset(); - - for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep) - sizeClassFor(cellSize).reset(); - - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - (*it)->reset(); -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h deleted file mode 100644 index 29a8cd0..0000000 --- a/Source/JavaScriptCore/runtime/MarkedSpace.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 MarkedSpace_h -#define MarkedSpace_h - -#include "MachineStackMarker.h" -#include "MarkedBlock.h" -#include "PageAllocationAligned.h" -#include <wtf/Bitmap.h> -#include <wtf/DoublyLinkedList.h> -#include <wtf/FixedArray.h> -#include <wtf/HashSet.h> -#include <wtf/Noncopyable.h> -#include <wtf/Vector.h> - -#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) < MarkedSpace::maxCellSize, class_fits_in_cell) - -namespace JSC { - - class Heap; - class JSCell; - class JSGlobalData; - class LiveObjectIterator; - class MarkStack; - class WeakGCHandle; - - class MarkedSpace { - WTF_MAKE_NONCOPYABLE(MarkedSpace); - public: - // Currently public for use in assertions. - static const size_t maxCellSize = 1024; - - static Heap* heap(JSCell*); - - static bool isMarked(const JSCell*); - static bool testAndSetMarked(const JSCell*); - static void setMarked(const JSCell*); - - MarkedSpace(JSGlobalData*); - void destroy(); - - JSGlobalData* globalData() { return m_globalData; } - - 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(); - - size_t size() const; - size_t capacity() const; - size_t objectCount() const; - - bool contains(const void*); - - template<typename Functor> void forEach(Functor&); - - private: - // [ 8, 16... 128 ) - static const size_t preciseStep = MarkedBlock::atomSize; - static const size_t preciseCutoff = 128; - static const size_t preciseCount = preciseCutoff / preciseStep - 1; - - // [ 128, 256... 1024 ) - static const size_t impreciseStep = preciseCutoff; - static const size_t impreciseCutoff = maxCellSize; - static const size_t impreciseCount = impreciseCutoff / impreciseStep - 1; - - typedef HashSet<MarkedBlock*>::iterator BlockIterator; - - struct SizeClass { - SizeClass(); - void reset(); - - MarkedBlock* nextBlock; - DoublyLinkedList<MarkedBlock> blockList; - size_t cellSize; - }; - - MarkedBlock* allocateBlock(SizeClass&); - void freeBlocks(DoublyLinkedList<MarkedBlock>&); - - SizeClass& sizeClassFor(size_t); - void* allocateFromSizeClass(SizeClass&); - - void clearMarks(MarkedBlock*); - - SizeClass m_preciseSizeClasses[preciseCount]; - SizeClass m_impreciseSizeClasses[impreciseCount]; - HashSet<MarkedBlock*> m_blocks; - size_t m_waterMark; - size_t m_highWaterMark; - JSGlobalData* m_globalData; - }; - - inline Heap* MarkedSpace::heap(JSCell* cell) - { - return MarkedBlock::blockFor(cell)->heap(); - } - - inline bool MarkedSpace::isMarked(const JSCell* cell) - { - return MarkedBlock::blockFor(cell)->isMarked(cell); - } - - inline bool MarkedSpace::testAndSetMarked(const JSCell* cell) - { - return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); - } - - inline void MarkedSpace::setMarked(const JSCell* cell) - { - MarkedBlock::blockFor(cell)->setMarked(cell); - } - - inline bool MarkedSpace::contains(const void* x) - { - if (!MarkedBlock::isAtomAligned(x)) - return false; - - MarkedBlock* block = MarkedBlock::blockFor(x); - if (!block || !m_blocks.contains(block)) - return false; - - return block->contains(x); - } - - template <typename Functor> inline void MarkedSpace::forEach(Functor& functor) - { - BlockIterator end = m_blocks.end(); - for (BlockIterator it = m_blocks.begin(); it != end; ++it) - (*it)->forEach(functor); - } - - inline MarkedSpace::SizeClass::SizeClass() - : nextBlock(0) - , cellSize(0) - { - } - - inline void MarkedSpace::SizeClass::reset() - { - nextBlock = blockList.head(); - } - -} // namespace JSC - -#endif // MarkedSpace_h diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp index 7b856a1..52bd76a 100644 --- a/Source/JavaScriptCore/runtime/MathObject.cpp +++ b/Source/JavaScriptCore/runtime/MathObject.cpp @@ -86,7 +86,7 @@ const ClassInfo MathObject::s_info = { "Math", &JSObjectWithGlobalObject::s_info @end */ -MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) +MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) : JSObjectWithGlobalObject(globalObject, structure) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/MathObject.h b/Source/JavaScriptCore/runtime/MathObject.h index 26eaae0..75753be 100644 --- a/Source/JavaScriptCore/runtime/MathObject.h +++ b/Source/JavaScriptCore/runtime/MathObject.h @@ -27,14 +27,14 @@ namespace JSC { class MathObject : public JSObjectWithGlobalObject { public: - MathObject(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); + MathObject(ExecState*, JSGlobalObject*, Structure*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp index d8fda69..9cd5dcb 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -32,7 +32,7 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor); const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0 }; -NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString& nameAndMessage) +NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* prototypeStructure, const UString& nameAndMessage) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, nameAndMessage)) { ASSERT(inherits(&s_info)); @@ -41,13 +41,23 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* 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(exec->globalData(), prototype); + m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), prototype)); + ASSERT(m_errorStructure); + ASSERT(m_errorStructure->typeInfo().type() == ObjectType); +} + +void NativeErrorConstructor::markChildren(MarkStack& markStack) +{ + InternalFunction::markChildren(markStack); + if (m_errorStructure) + markStack.append(&m_errorStructure); } static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec) { JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined(); Structure* errorStructure = static_cast<NativeErrorConstructor*>(exec->callee())->errorStructure(); + ASSERT(errorStructure); return JSValue::encode(ErrorInstance::create(exec, errorStructure, message)); } diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h index 23f798e..e96daf6 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h @@ -31,11 +31,11 @@ namespace JSC { class NativeErrorConstructor : public InternalFunction { public: - NativeErrorConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString&); + NativeErrorConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* prototypeStructure, const UString&); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } @@ -43,10 +43,12 @@ namespace JSC { Structure* errorStructure() { return m_errorStructure.get(); } private: + static const unsigned StructureFlags = OverridesMarkChildren | InternalFunction::StructureFlags; virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); + virtual void markChildren(MarkStack&); - RefPtr<Structure> m_errorStructure; + WriteBarrier<Structure> m_errorStructure; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp index 4e10268..de27d59 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp @@ -31,7 +31,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype); -NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const UString& nameAndMessage, NativeErrorConstructor* constructor) +NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& nameAndMessage, NativeErrorConstructor* constructor) : JSObjectWithGlobalObject(globalObject, structure) { putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), 0); diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.h b/Source/JavaScriptCore/runtime/NativeErrorPrototype.h index 30690d5..e1b05ce 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.h +++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.h @@ -28,7 +28,7 @@ namespace JSC { class NativeErrorPrototype : public JSObjectWithGlobalObject { public: - NativeErrorPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, const UString&, NativeErrorConstructor*); + NativeErrorPrototype(ExecState*, JSGlobalObject*, Structure*, const UString&, NativeErrorConstructor*); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp index aee143a..4193f79 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp @@ -54,7 +54,7 @@ const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_i @end */ -NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype) +NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NumberPrototype* numberPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->s_info.className)) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h index ab4507e..69aa8a1 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.h +++ b/Source/JavaScriptCore/runtime/NumberConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class NumberConstructor : public InternalFunction { public: - NumberConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, NumberPrototype*); + NumberConstructor(ExecState*, JSGlobalObject*, Structure*, NumberPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); @@ -37,7 +37,7 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp index 74b5e98..6ee103b 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::s_info = { "Number", &JSWrapperObject::s_info, 0, 0 }; -NumberObject::NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure) + : JSWrapperObject(globalData, structure) { ASSERT(inherits(&s_info)); } diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h index 90d0b26..cba65dd 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.h +++ b/Source/JavaScriptCore/runtime/NumberObject.h @@ -27,11 +27,11 @@ namespace JSC { class NumberObject : public JSWrapperObject { public: - explicit NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure>); + explicit NumberObject(JSGlobalData&, Structure*); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp index 6c027b3..24532dd 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp @@ -45,7 +45,7 @@ static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*); // ECMA 15.7.4 -NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) +NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure) : NumberObject(exec->globalData(), structure) { setInternalValue(exec->globalData(), jsNumber(0)); diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.h b/Source/JavaScriptCore/runtime/NumberPrototype.h index 191ab47..45bdfe7 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.h +++ b/Source/JavaScriptCore/runtime/NumberPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class NumberPrototype : public NumberObject { public: - NumberPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure); + NumberPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index c642a5b..aed5e24 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -75,7 +75,7 @@ const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_i @end */ -ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype) +ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ObjectPrototype* objectPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object")) { // ECMA 15.2.3.1 @@ -342,7 +342,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec) if (!exec->argument(0).isObject() && !exec->argument(0).isNull()) return throwVMError(exec, createTypeError(exec, "Object prototype may only be an Object or null.")); JSObject* newObject = constructEmptyObject(exec); - newObject->setPrototype(exec->argument(0)); + newObject->setPrototype(exec->globalData(), exec->argument(0)); if (exec->argument(1).isUndefined()) return JSValue::encode(newObject); if (!exec->argument(1).isObject()) @@ -355,7 +355,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec) JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, "Object.seal can only be called on Objects.")); - asObject(obj)->seal(); + asObject(obj)->seal(exec->globalData()); return JSValue::encode(obj); } @@ -364,7 +364,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec) JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, "Object.freeze can only be called on Objects.")); - asObject(obj)->freeze(); + asObject(obj)->freeze(exec->globalData()); return JSValue::encode(obj); } @@ -373,7 +373,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec) JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, "Object.preventExtensions can only be called on Objects.")); - asObject(obj)->preventExtensions(); + asObject(obj)->preventExtensions(exec->globalData()); return JSValue::encode(obj); } @@ -382,7 +382,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec) JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, "Object.isSealed can only be called on Objects.")); - return JSValue::encode(jsBoolean(asObject(obj)->isSealed())); + return JSValue::encode(jsBoolean(asObject(obj)->isSealed(exec->globalData()))); } EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec) @@ -390,7 +390,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec) JSValue obj = exec->argument(0); if (!obj.isObject()) return throwVMError(exec, createTypeError(exec, "Object.isFrozen can only be called on Objects.")); - return JSValue::encode(jsBoolean(asObject(obj)->isFrozen())); + return JSValue::encode(jsBoolean(asObject(obj)->isFrozen(exec->globalData()))); } EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.h b/Source/JavaScriptCore/runtime/ObjectConstructor.h index b7bfc1d..6ebafcd 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.h +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.h @@ -29,14 +29,14 @@ namespace JSC { class ObjectConstructor : public InternalFunction { public: - ObjectConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, ObjectPrototype*); + ObjectConstructor(ExecState*, JSGlobalObject*, Structure*, ObjectPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp index 187456f..7469172 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -40,8 +40,8 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*); static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*); static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*); -ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> stucture, Structure* functionStructure) - : JSNonFinalObject(stucture) +ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* stucture, Structure* functionStructure) + : JSNonFinalObject(exec->globalData(), stucture) , m_hasNoPropertiesWithUInt32Names(true) { putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h index 61c8f57..9fb7fae 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.h +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class ObjectPrototype : public JSNonFinalObject { public: - ObjectPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure); + ObjectPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure); private: virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index 181f912..c102eeb 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -24,9 +24,8 @@ #include "ExceptionHelpers.h" #include "Interpreter.h" -#include "JSImmediate.h" -#include "JSNumberCell.h" #include "JSString.h" +#include "JSValueInlineMethods.h" namespace JSC { @@ -431,7 +430,7 @@ namespace JSC { if (cell->structure()->isDictionary()) { asObject(cell)->flattenDictionaryObject(callFrame->globalData()); if (slotBase == cell) - slotOffset = cell->structure()->get(propertyName); + slotOffset = cell->structure()->get(callFrame->globalData(), propertyName); } ++count; diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h index c000dc8..fc195cd 100644 --- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -22,6 +22,7 @@ #define PropertyMapHashTable_h #include "UString.h" +#include "WriteBarrier.h" #include <wtf/HashTable.h> #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> @@ -73,13 +74,13 @@ struct PropertyMapEntry { StringImpl* key; unsigned offset; unsigned attributes; - JSCell* specificValue; + WriteBarrier<JSCell> specificValue; - PropertyMapEntry(StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue) + PropertyMapEntry(JSGlobalData& globalData, JSCell* owner, StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue) : key(key) , offset(offset) , attributes(attributes) - , specificValue(specificValue) + , specificValue(globalData, owner, specificValue) { } }; @@ -141,9 +142,9 @@ public: typedef std::pair<ValueType*, unsigned> find_iterator; // Constructor is passed an initial capacity, a PropertyTable to copy, or both. - PropertyTable(unsigned initialCapacity); - PropertyTable(const PropertyTable&); - PropertyTable(unsigned initialCapacity, const PropertyTable&); + explicit PropertyTable(unsigned initialCapacity); + PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&); + PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&); ~PropertyTable(); // Ordered iteration methods. @@ -176,7 +177,7 @@ public: void addDeletedOffset(unsigned offset); // Copy this PropertyTable, ensuring the copy has at least the capacity provided. - PassOwnPtr<PropertyTable> copy(unsigned newCapacity); + PassOwnPtr<PropertyTable> copy(JSGlobalData&, JSCell* owner, unsigned newCapacity); #ifndef NDEBUG size_t sizeInMemory(); @@ -184,6 +185,7 @@ public: #endif private: + PropertyTable(const PropertyTable&); // Used to insert a value known not to be in the table, and where we know capacity to be available. void reinsert(const ValueType& entry); @@ -243,7 +245,7 @@ inline PropertyTable::PropertyTable(unsigned initialCapacity) ASSERT(isPowerOf2(m_indexSize)); } -inline PropertyTable::PropertyTable(const PropertyTable& other) +inline PropertyTable::PropertyTable(JSGlobalData& globalData, JSCell* owner, const PropertyTable& other) : m_indexSize(other.m_indexSize) , m_indexMask(other.m_indexMask) , m_index(static_cast<unsigned*>(fastMalloc(dataSize()))) @@ -255,8 +257,10 @@ inline PropertyTable::PropertyTable(const PropertyTable& other) memcpy(m_index, other.m_index, dataSize()); iterator end = this->end(); - for (iterator iter = begin(); iter != end; ++iter) + for (iterator iter = begin(); iter != end; ++iter) { iter->key->ref(); + writeBarrier(globalData, owner, iter->specificValue.get()); + } // Copy the m_deletedOffsets vector. Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get(); @@ -264,7 +268,7 @@ inline PropertyTable::PropertyTable(const PropertyTable& other) m_deletedOffsets.set(new Vector<unsigned>(*otherDeletedOffsets)); } -inline PropertyTable::PropertyTable(unsigned initialCapacity, const PropertyTable& other) +inline PropertyTable::PropertyTable(JSGlobalData& globalData, JSCell* owner, unsigned initialCapacity, const PropertyTable& other) : m_indexSize(sizeForCapacity(initialCapacity)) , m_indexMask(m_indexSize - 1) , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize()))) @@ -279,6 +283,7 @@ inline PropertyTable::PropertyTable(unsigned initialCapacity, const PropertyTabl ASSERT(canInsert()); reinsert(*iter); iter->key->ref(); + writeBarrier(globalData, owner, iter->specificValue.get()); } // Copy the m_deletedOffsets vector. @@ -443,15 +448,15 @@ inline void PropertyTable::addDeletedOffset(unsigned offset) m_deletedOffsets->append(offset); } -inline PassOwnPtr<PropertyTable> PropertyTable::copy(unsigned newCapacity) +inline PassOwnPtr<PropertyTable> PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity) { ASSERT(newCapacity >= m_keyCount); // Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it, // save rehashing all keys. if (sizeForCapacity(newCapacity) == m_indexSize) - return new PropertyTable(*this); - return new PropertyTable(newCapacity, *this); + return new PropertyTable(globalData, owner, *this); + return new PropertyTable(globalData, owner, newCapacity, *this); } #ifndef NDEBUG diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 19b4b36..3da0198 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -95,7 +95,7 @@ const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_i @end */ -RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype) +RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "RegExp")) , d(adoptPtr(new RegExpConstructorPrivate)) { @@ -109,7 +109,7 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje } RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) - : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized) + : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized) { RegExpConstructorPrivate* d = new RegExpConstructorPrivate; d->input = data->lastInput; diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h index 5e0b2b8..548664e 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.h +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h @@ -57,9 +57,9 @@ namespace JSC { class RegExpConstructor : public InternalFunction { public: - RegExpConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, RegExpPrototype*); + RegExpConstructor(ExecState*, JSGlobalObject*, Structure*, RegExpPrototype*); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 4b5028b..d824ecd 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -61,7 +61,7 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_ @end */ -RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp) +RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, NonNullPassRefPtr<RegExp> regExp) : JSObjectWithGlobalObject(globalObject, structure) , d(adoptPtr(new RegExpObjectData(regExp))) { diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index fa2024d..4274fff 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -30,7 +30,7 @@ namespace JSC { public: typedef JSObjectWithGlobalObject Base; - RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>); + RegExpObject(JSGlobalObject*, Structure*, NonNullPassRefPtr<RegExp>); virtual ~RegExpObject(); void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; } @@ -58,7 +58,7 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 61747b1..5bb8ad8 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -47,7 +47,7 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*); // ECMA 15.10.5 -RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) +RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure) : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", NoFlags)) { putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.h b/Source/JavaScriptCore/runtime/RegExpPrototype.h index 70d77d9..2cc5405 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.h +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.h @@ -28,7 +28,7 @@ namespace JSC { class RegExpPrototype : public RegExpObject { public: - RegExpPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure); + RegExpPrototype(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp index 4615f9a..026d729 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.cpp +++ b/Source/JavaScriptCore/runtime/ScopeChain.cpp @@ -51,6 +51,8 @@ void ScopeChainNode::print() #endif +const ClassInfo ScopeChainNode::s_info = { "ScopeChainNode", 0, 0, 0 }; + int ScopeChainNode::localDepth() { int scopeDepth = 0; diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h index cb70a34..d0a2672 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.h +++ b/Source/JavaScriptCore/runtime/ScopeChain.h @@ -22,6 +22,7 @@ #define ScopeChain_h #include "JSCell.h" +#include "Structure.h" #include <wtf/FastAllocBase.h> namespace JSC { @@ -35,7 +36,7 @@ namespace JSC { class ScopeChainNode : public JSCell { public: ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) - : JSCell(globalData->scopeChainNodeStructure.get()) + : JSCell(*globalData, globalData->scopeChainNodeStructure.get()) , globalData(globalData) , next(*globalData, this, next) , object(*globalData, this, object) @@ -64,10 +65,11 @@ namespace JSC { void print(); #endif - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); } virtual void markChildren(MarkStack&); private: static const unsigned StructureFlags = OverridesMarkChildren; + static const ClassInfo s_info; }; inline ScopeChainNode* ScopeChainNode::push(JSObject* o) diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp index 24c501e..e666dee 100644 --- a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp +++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp @@ -29,7 +29,7 @@ namespace JSC { StrictEvalActivation::StrictEvalActivation(ExecState* exec) - : JSNonFinalObject(exec->globalData().strictEvalActivationStructure) + : JSNonFinalObject(exec->globalData(), exec->globalData().strictEvalActivationStructure.get()) { } diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp index ed088e4..560202a 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.cpp +++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp @@ -48,7 +48,7 @@ static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec) ASSERT_CLASS_FITS_IN_CELL(StringConstructor); -StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure, StringPrototype* stringPrototype) +StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* functionStructure, StringPrototype* stringPrototype) : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, stringPrototype->classInfo()->className)) { // ECMA 15.5.3.1 String.prototype diff --git a/Source/JavaScriptCore/runtime/StringConstructor.h b/Source/JavaScriptCore/runtime/StringConstructor.h index 3a42c7e..117cce8 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.h +++ b/Source/JavaScriptCore/runtime/StringConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class StringConstructor : public InternalFunction { public: - StringConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* functionStructure, StringPrototype*); + StringConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* functionStructure, StringPrototype*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index 47e5860..67dc291 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -29,22 +29,22 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 }; -StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(structure) +StringObject::StringObject(ExecState* exec, Structure* structure) + : JSWrapperObject(exec->globalData(), structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsEmptyString(exec)); } -StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string) - : JSWrapperObject(structure) +StringObject::StringObject(JSGlobalData& globalData, Structure* structure, JSString* string) + : JSWrapperObject(globalData, structure) { ASSERT(inherits(&s_info)); setInternalValue(globalData, string); } -StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) - : JSWrapperObject(structure) +StringObject::StringObject(ExecState* exec, Structure* structure, const UString& string) + : JSWrapperObject(exec->globalData(), structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsString(exec, string)); diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index ae3376d..4c16044 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -28,8 +28,8 @@ namespace JSC { class StringObject : public JSWrapperObject { public: - StringObject(ExecState*, NonNullPassRefPtr<Structure>); - StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&); + StringObject(ExecState*, Structure*); + StringObject(ExecState*, Structure*, const UString&); static StringObject* create(ExecState*, JSGlobalObject*, JSString*); @@ -45,14 +45,14 @@ namespace JSC { JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; - StringObject(JSGlobalData&, NonNullPassRefPtr<Structure>, JSString*); + StringObject(JSGlobalData&, Structure*, JSString*); }; StringObject* asStringObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index e4c7061..3133944 100644 --- a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -37,12 +37,12 @@ namespace JSC { } private: - StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) + StringObjectThatMasqueradesAsUndefined(ExecState* exec, Structure* structure, const UString& string) : StringObject(exec, structure, string) { } - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) + static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index a6bf4e6..91112a5 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -131,7 +131,7 @@ const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, */ // ECMA 15.5.4 -StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure) +StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) : StringObject(exec, structure) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h index 57def22..6c4b475 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.h +++ b/Source/JavaScriptCore/runtime/StringPrototype.h @@ -29,12 +29,12 @@ namespace JSC { class StringPrototype : public StringObject { public: - StringPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); + StringPrototype(ExecState*, JSGlobalObject*, Structure*); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index 829e3db..dcc8e7c 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -61,21 +61,6 @@ int numRemoves; namespace JSC { -#ifndef NDEBUG -static WTF::RefCountedLeakCounter structureCounter("Structure"); - -#if ENABLE(JSC_MULTIPLE_THREADS) -static Mutex& ignoreSetMutex() -{ - DEFINE_STATIC_LOCAL(Mutex, mutex, ()); - return mutex; -} -#endif - -static bool shouldIgnoreLeaks; -static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>); -#endif - #if DUMP_STRUCTURE_ID_STATISTICS static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>); #endif @@ -106,41 +91,41 @@ inline void StructureTransitionTable::remove(Structure* structure) // map mode). // As such, the passed structure *must* be the existing transition. ASSERT(singleTransition() == structure); - setSingleTransition(0); + clearSingleTransition(); } else { // Check whether a mapping exists for structure's key, and whether the // entry is structure (the latter check may fail if we initially had a // transition with a specific value, and this has been despecified). TransitionMap::iterator entry = map()->find(make_pair(structure->m_nameInPrevious, structure->m_attributesInPrevious)); - if (entry != map()->end() && structure == entry->second) + if (entry != map()->end() && structure == entry.get().second) map()->remove(entry); } } -inline void StructureTransitionTable::add(Structure* structure) +inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure) { if (isUsingSingleSlot()) { Structure* existingTransition = singleTransition(); // This handles the first transition being added. if (!existingTransition) { - setSingleTransition(structure); + setSingleTransition(globalData, structure); return; } // This handles the second transition being added // (or the first transition being despecified!) setMap(new TransitionMap()); - add(existingTransition); + add(globalData, existingTransition); } // Add the structure to the map. - std::pair<TransitionMap::iterator, bool> result = map()->add(make_pair(structure->m_nameInPrevious, structure->m_attributesInPrevious), structure); + std::pair<TransitionMap::iterator, bool> result = map()->add(globalData, make_pair(structure->m_nameInPrevious, structure->m_attributesInPrevious), structure); if (!result.second) { // There already is an entry! - we should only hit this when despecifying. - ASSERT(result.first->second->m_specificValueInPrevious); + ASSERT(result.first.get().second->m_specificValueInPrevious); ASSERT(!structure->m_specificValueInPrevious); - result.first->second = structure; + map()->set(result.first, structure); } } @@ -189,10 +174,10 @@ void Structure::dumpStatistics() #endif } -Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) - : m_typeInfo(typeInfo) - , m_prototype(prototype) - , m_specificValueInPrevious(0) +Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) + : JSCell(globalData, globalData.structureStructure.get()) + , m_typeInfo(typeInfo) + , m_prototype(globalData, this, prototype) , m_classInfo(classInfo) , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity) , m_offset(noOffset) @@ -206,27 +191,36 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anony , m_preventExtensions(false) { ASSERT(m_prototype); - ASSERT(m_prototype->isObject() || m_prototype->isNull()); + ASSERT(m_prototype.isObject() || m_prototype.isNull()); +} -#ifndef NDEBUG -#if ENABLE(JSC_MULTIPLE_THREADS) - MutexLocker protect(ignoreSetMutex()); -#endif - if (shouldIgnoreLeaks) - ignoreSet.add(this); - else - structureCounter.increment(); -#endif +const ClassInfo Structure::s_info = { "Structure", 0, 0, 0 }; -#if DUMP_STRUCTURE_ID_STATISTICS - liveStructureSet.add(this); -#endif +Structure::Structure(JSGlobalData& globalData) + : JSCell(globalData, this) + , m_typeInfo(CompoundType, OverridesMarkChildren) + , m_prototype(globalData, this, jsNull()) + , m_classInfo(&s_info) + , m_propertyStorageCapacity(0) + , m_offset(noOffset) + , m_dictionaryKind(NoneDictionaryKind) + , m_isPinnedPropertyTable(false) + , m_hasGetterSetterProperties(false) + , m_hasNonEnumerableProperties(false) + , m_attributesInPrevious(0) + , m_specificFunctionThrashCount(0) + , m_anonymousSlotCount(0) + , m_preventExtensions(false) +{ + ASSERT(m_prototype); + ASSERT(m_prototype.isNull()); + ASSERT(!globalData.structureStructure); } -Structure::Structure(const Structure* previous) - : m_typeInfo(previous->typeInfo()) - , m_prototype(previous->storedPrototype()) - , m_specificValueInPrevious(0) +Structure::Structure(JSGlobalData& globalData, const Structure* previous) + : JSCell(globalData, globalData.structureStructure.get()) + , m_typeInfo(previous->typeInfo()) + , m_prototype(globalData, this, previous->storedPrototype()) , m_classInfo(previous->m_classInfo) , m_propertyStorageCapacity(previous->m_propertyStorageCapacity) , m_offset(noOffset) @@ -240,61 +234,14 @@ Structure::Structure(const Structure* previous) , m_preventExtensions(previous->m_preventExtensions) { ASSERT(m_prototype); - ASSERT(m_prototype->isObject() || m_prototype->isNull()); - -#ifndef NDEBUG -#if ENABLE(JSC_MULTIPLE_THREADS) - MutexLocker protect(ignoreSetMutex()); -#endif - if (shouldIgnoreLeaks) - ignoreSet.add(this); - else - structureCounter.increment(); -#endif - -#if DUMP_STRUCTURE_ID_STATISTICS - liveStructureSet.add(this); -#endif + ASSERT(m_prototype.isObject() || m_prototype.isNull()); } Structure::~Structure() { - if (m_previous) { - ASSERT(m_nameInPrevious); - m_previous->m_transitionTable.remove(this); - } - -#ifndef NDEBUG -#if ENABLE(JSC_MULTIPLE_THREADS) - MutexLocker protect(ignoreSetMutex()); -#endif - HashSet<Structure*>::iterator it = ignoreSet.find(this); - if (it != ignoreSet.end()) - ignoreSet.remove(it); - else - structureCounter.decrement(); -#endif - -#if DUMP_STRUCTURE_ID_STATISTICS - liveStructureSet.remove(this); -#endif -} - -void Structure::startIgnoringLeaks() -{ -#ifndef NDEBUG - shouldIgnoreLeaks = true; -#endif } -void Structure::stopIgnoringLeaks() -{ -#ifndef NDEBUG - shouldIgnoreLeaks = false; -#endif -} - -void Structure::materializePropertyMap() +void Structure::materializePropertyMap(JSGlobalData& globalData) { ASSERT(!m_propertyTable); @@ -309,7 +256,7 @@ void Structure::materializePropertyMap() ASSERT(structure->m_propertyTable); ASSERT(!structure->m_previous); - m_propertyTable = structure->m_propertyTable->copy(m_offset + 1); + m_propertyTable = structure->m_propertyTable->copy(globalData, 0, m_offset + 1); break; } @@ -321,7 +268,7 @@ void Structure::materializePropertyMap() for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { structure = structures[i]; - PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious); + PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get()); m_propertyTable->add(entry); } } @@ -334,27 +281,27 @@ void Structure::growPropertyStorageCapacity() m_propertyStorageCapacity *= 2; } -void Structure::despecifyDictionaryFunction(const Identifier& propertyName) +void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName) { StringImpl* rep = propertyName.impl(); - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); ASSERT(isDictionary()); ASSERT(m_propertyTable); PropertyMapEntry* entry = m_propertyTable->find(rep).first; ASSERT(entry); - entry->specificValue = 0; + entry->specificValue.clear(); } -PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) +Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.impl(), attributes)) { - JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious; + JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get(); if (specificValueInPrevious && specificValueInPrevious != specificValue) return 0; ASSERT(existingTransition->m_offset != noOffset); @@ -367,7 +314,7 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct return 0; } -PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) +Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { // If we have a specific function, we may have got to this point if there is // already a transition with the correct property name and attributes, but @@ -387,37 +334,37 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con specificValue = 0; if (structure->transitionCount() > s_maxTransitionLength) { - RefPtr<Structure> transition = toCacheableDictionaryTransition(structure); + Structure* transition = toCacheableDictionaryTransition(globalData, structure); ASSERT(structure != transition); - offset = transition->put(propertyName, attributes, specificValue); + offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue); ASSERT(offset >= structure->m_anonymousSlotCount); ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) transition->growPropertyStorageCapacity(); - return transition.release(); + return transition; } - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); - transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; - transition->m_previous = structure; + transition->m_cachedPrototypeChain.set(globalData, transition, structure->m_cachedPrototypeChain.get()); + transition->m_previous.set(globalData, transition, structure); transition->m_nameInPrevious = propertyName.impl(); transition->m_attributesInPrevious = attributes; - transition->m_specificValueInPrevious = specificValue; + transition->m_specificValueInPrevious.set(globalData, transition, specificValue); if (structure->m_propertyTable) { if (structure->m_isPinnedPropertyTable) - transition->m_propertyTable = structure->m_propertyTable->copy(structure->m_propertyTable->size() + 1); + transition->m_propertyTable = structure->m_propertyTable->copy(globalData, 0, structure->m_propertyTable->size() + 1); else transition->m_propertyTable = structure->m_propertyTable.release(); } else { if (structure->m_previous) - transition->materializePropertyMap(); + transition->materializePropertyMap(globalData); else transition->createPropertyMap(); } - offset = transition->put(propertyName, attributes, specificValue); + offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue); ASSERT(offset >= structure->m_anonymousSlotCount); ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) @@ -425,106 +372,106 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_offset = offset - structure->m_anonymousSlotCount; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - structure->m_transitionTable.add(transition.get()); - return transition.release(); + structure->m_transitionTable.add(globalData, transition); + return transition; } -PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset) +Structure* Structure::removePropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, size_t& offset) { ASSERT(!structure->isUncacheableDictionary()); - RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure); + Structure* transition = toUncacheableDictionaryTransition(globalData, structure); offset = transition->remove(propertyName); ASSERT(offset >= structure->m_anonymousSlotCount); ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount); - return transition.release(); + return transition; } -PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype) +Structure* Structure::changePrototypeTransition(JSGlobalData& globalData, Structure* structure, JSValue prototype) { - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); - transition->m_prototype = prototype; + transition->m_prototype.set(globalData, transition, prototype); // Don't set m_offset, as one can not transition to this. - structure->materializePropertyMapIfNecessary(); - transition->m_propertyTable = structure->copyPropertyTable(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTable(globalData, transition); transition->m_isPinnedPropertyTable = true; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - return transition.release(); + return transition; } -PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction) +Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Structure* structure, const Identifier& replaceFunction) { ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount); - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); ++transition->m_specificFunctionThrashCount; // Don't set m_offset, as one can not transition to this. - structure->materializePropertyMapIfNecessary(); - transition->m_propertyTable = structure->copyPropertyTable(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTable(globalData, transition); transition->m_isPinnedPropertyTable = true; if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) - transition->despecifyAllFunctions(); + transition->despecifyAllFunctions(globalData); else { - bool removed = transition->despecifyFunction(replaceFunction); + bool removed = transition->despecifyFunction(globalData, replaceFunction); ASSERT_UNUSED(removed, removed); } ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - return transition.release(); + return transition; } -PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) +Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure) { - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); // Don't set m_offset, as one can not transition to this. - structure->materializePropertyMapIfNecessary(); - transition->m_propertyTable = structure->copyPropertyTable(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTable(globalData, transition); transition->m_isPinnedPropertyTable = true; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - return transition.release(); + return transition; } -PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind) +Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind) { ASSERT(!structure->isUncacheableDictionary()); - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); - structure->materializePropertyMapIfNecessary(); - transition->m_propertyTable = structure->copyPropertyTable(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTable(globalData, transition); transition->m_isPinnedPropertyTable = true; transition->m_dictionaryKind = kind; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - return transition.release(); + return transition; } -PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure) +Structure* Structure::toCacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure) { - return toDictionaryTransition(structure, CachedDictionaryKind); + return toDictionaryTransition(globalData, structure, CachedDictionaryKind); } -PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure) +Structure* Structure::toUncacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure) { - return toDictionaryTransition(structure, UncachedDictionaryKind); + return toDictionaryTransition(globalData, structure, UncachedDictionaryKind); } // In future we may want to cache this transition. -PassRefPtr<Structure> Structure::sealTransition(Structure* structure) +Structure* Structure::sealTransition(JSGlobalData& globalData, Structure* structure) { - RefPtr<Structure> transition = preventExtensionsTransition(structure); + Structure* transition = preventExtensionsTransition(globalData, structure); if (transition->m_propertyTable) { PropertyTable::iterator end = transition->m_propertyTable->end(); @@ -532,13 +479,13 @@ PassRefPtr<Structure> Structure::sealTransition(Structure* structure) iter->attributes |= DontDelete; } - return transition.release(); + return transition; } // In future we may want to cache this transition. -PassRefPtr<Structure> Structure::freezeTransition(Structure* structure) +Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* structure) { - RefPtr<Structure> transition = preventExtensionsTransition(structure); + Structure* transition = preventExtensionsTransition(globalData, structure); if (transition->m_propertyTable) { PropertyTable::iterator end = transition->m_propertyTable->end(); @@ -546,32 +493,32 @@ PassRefPtr<Structure> Structure::freezeTransition(Structure* structure) iter->attributes |= (DontDelete | ReadOnly); } - return transition.release(); + return transition; } // In future we may want to cache this transition. -PassRefPtr<Structure> Structure::preventExtensionsTransition(Structure* structure) +Structure* Structure::preventExtensionsTransition(JSGlobalData& globalData, Structure* structure) { - RefPtr<Structure> transition = create(structure); + Structure* transition = create(globalData, structure); // Don't set m_offset, as one can not transition to this. - structure->materializePropertyMapIfNecessary(); - transition->m_propertyTable = structure->copyPropertyTable(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTable(globalData, transition); transition->m_isPinnedPropertyTable = true; transition->m_preventExtensions = true; ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount()); - return transition.release(); + return transition; } // In future we may want to cache this property. -bool Structure::isSealed() +bool Structure::isSealed(JSGlobalData& globalData) { if (isExtensible()) return false; - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return true; @@ -584,12 +531,12 @@ bool Structure::isSealed() } // In future we may want to cache this property. -bool Structure::isFrozen() +bool Structure::isFrozen(JSGlobalData& globalData) { if (isExtensible()) return false; - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return true; @@ -601,7 +548,7 @@ bool Structure::isFrozen() return true; } -PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object) +Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object) { ASSERT(isDictionary()); if (isUncacheableDictionary()) { @@ -630,30 +577,30 @@ PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSGlobalData& global return this; } -size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) +size_t Structure::addPropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { ASSERT(!m_enumerationCache); if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) specificValue = 0; - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); m_isPinnedPropertyTable = true; - size_t offset = put(propertyName, attributes, specificValue); + size_t offset = putSpecificValue(globalData, propertyName, attributes, specificValue); ASSERT(offset >= m_anonymousSlotCount); if (propertyStorageSize() > propertyStorageCapacity()) growPropertyStorageCapacity(); return offset; } -size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName) +size_t Structure::removePropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName) { ASSERT(isUncacheableDictionary()); ASSERT(!m_enumerationCache); - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); m_isPinnedPropertyTable = true; size_t offset = remove(propertyName); @@ -688,14 +635,14 @@ inline void Structure::checkConsistency() #endif -PropertyTable* Structure::copyPropertyTable() +PropertyTable* Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner) { - return m_propertyTable ? new PropertyTable(*m_propertyTable) : 0; + return m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0; } -size_t Structure::get(StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue) +size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue) { - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return WTF::notFound; @@ -704,14 +651,14 @@ size_t Structure::get(StringImpl* propertyName, unsigned& attributes, JSCell*& s return WTF::notFound; attributes = entry->attributes; - specificValue = entry->specificValue; + specificValue = entry->specificValue.get(); ASSERT(entry->offset >= m_anonymousSlotCount); return entry->offset; } -bool Structure::despecifyFunction(const Identifier& propertyName) +bool Structure::despecifyFunction(JSGlobalData& globalData, const Identifier& propertyName) { - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return false; @@ -721,25 +668,25 @@ bool Structure::despecifyFunction(const Identifier& propertyName) return false; ASSERT(entry->specificValue); - entry->specificValue = 0; + entry->specificValue.clear(); return true; } -void Structure::despecifyAllFunctions() +void Structure::despecifyAllFunctions(JSGlobalData& globalData) { - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return; PropertyTable::iterator end = m_propertyTable->end(); for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) - iter->specificValue = 0; + iter->specificValue.clear(); } -size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) +size_t Structure::putSpecificValue(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { ASSERT(!propertyName.isNull()); - ASSERT(get(propertyName) == notFound); + ASSERT(get(globalData, propertyName) == notFound); checkConsistency(); if (attributes & DontEnum) @@ -758,7 +705,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel newOffset = m_propertyTable->size() + m_anonymousSlotCount; ASSERT(newOffset >= m_anonymousSlotCount); - m_propertyTable->add(PropertyMapEntry(rep, newOffset, attributes, specificValue)); + m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue)); checkConsistency(); return newOffset; @@ -798,9 +745,9 @@ void Structure::createPropertyMap(unsigned capacity) checkConsistency(); } -void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode) +void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode) { - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return; @@ -818,11 +765,26 @@ void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMo } } -void Structure::initializeThreading() -{ -#if !defined(NDEBUG) && ENABLE(JSC_MULTIPLE_THREADS) - ignoreSetMutex(); -#endif +void Structure::markChildren(MarkStack& markStack) +{ + JSCell::markChildren(markStack); + if (m_prototype) + markStack.append(&m_prototype); + if (m_cachedPrototypeChain) + markStack.append(&m_cachedPrototypeChain); + if (m_previous) + markStack.append(&m_previous); + if (m_specificValueInPrevious) + markStack.append(&m_specificValueInPrevious); + if (m_enumerationCache) + markStack.append(&m_enumerationCache); + if (m_propertyTable) { + PropertyTable::iterator end = m_propertyTable->end(); + for (PropertyTable::iterator ptr = m_propertyTable->begin(); ptr != end; ++ptr) { + if (ptr->specificValue) + markStack.append(&ptr->specificValue); + } + } } #if DO_PROPERTYMAP_CONSTENCY_CHECK diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index c9f900a..fe9ce6b 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -27,6 +27,7 @@ #define Structure_h #include "Identifier.h" +#include "JSCell.h" #include "JSType.h" #include "JSValue.h" #include "PropertyMapHashTable.h" @@ -35,7 +36,7 @@ #include "StructureTransitionTable.h" #include "JSTypeInfo.h" #include "UString.h" -#include "WeakGCPtr.h" +#include "Weak.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -54,49 +55,41 @@ namespace JSC { IncludeDontEnumProperties }; - class Structure : public RefCounted<Structure> { + class Structure : public JSCell { public: friend class StructureTransitionTable; - static PassRefPtr<Structure> create(JSGlobalData&, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) + static Structure* create(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) { - return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount, classInfo)); + ASSERT(globalData.structureStructure); + return new (&globalData) Structure(globalData, prototype, typeInfo, anonymousSlotCount, classInfo); } - enum VPtrStealingHackType { VPtrStealingHack }; - static PassRefPtr<Structure> create(VPtrStealingHackType, const ClassInfo* classInfo) - { - return adoptRef(new Structure(jsNull(), TypeInfo(UnspecifiedType), 0, classInfo)); - } - - static void startIgnoringLeaks(); - static void stopIgnoringLeaks(); - static void dumpStatistics(); - static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); - static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); - static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset); - static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype); - static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&); - static PassRefPtr<Structure> getterSetterTransition(Structure*); - static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*); - static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*); - static PassRefPtr<Structure> sealTransition(Structure*); - static PassRefPtr<Structure> freezeTransition(Structure*); - static PassRefPtr<Structure> preventExtensionsTransition(Structure*); - - bool isSealed(); - bool isFrozen(); + static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset); + static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype); + static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&); + static Structure* getterSetterTransition(JSGlobalData&, Structure*); + static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*); + static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*); + static Structure* sealTransition(JSGlobalData&, Structure*); + static Structure* freezeTransition(JSGlobalData&, Structure*); + static Structure* preventExtensionsTransition(JSGlobalData&, Structure*); + + bool isSealed(JSGlobalData&); + bool isFrozen(JSGlobalData&); bool isExtensible() const { return !m_preventExtensions; } - PassRefPtr<Structure> flattenDictionaryStructure(JSGlobalData&, JSObject*); + Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*); ~Structure(); // These should be used with caution. - size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); - size_t removePropertyWithoutTransition(const Identifier& propertyName); - void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; } + size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); + size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName); + void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); } bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; } bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; } @@ -104,10 +97,9 @@ namespace JSC { const TypeInfo& typeInfo() const { return m_typeInfo; } JSValue storedPrototype() const { return m_prototype.get(); } - DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; } JSValue prototypeForLookup(ExecState*) const; StructureChain* prototypeChain(ExecState*) const; - DeprecatedPtr<StructureChain>* cachedPrototypeChainSlot() { return &m_cachedPrototypeChain; } + void markChildren(MarkStack&); Structure* previousID() const { return m_previous.get(); } @@ -116,12 +108,12 @@ namespace JSC { unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); } bool isUsingInlineStorage() const; - size_t get(const Identifier& propertyName); - size_t get(StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue); - size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) + size_t get(JSGlobalData&, const Identifier& propertyName); + size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue); + size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) { ASSERT(!propertyName.isNull()); - return get(propertyName.impl(), attributes, specificValue); + return get(globalData, propertyName.impl(), attributes, specificValue); } bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } @@ -134,18 +126,15 @@ namespace JSC { bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; } - void despecifyDictionaryFunction(const Identifier& propertyName); + void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName); void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; } void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. - void clearEnumerationCache(); // Defined in JSPropertyNameIterator.h. JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h. - void getPropertyNames(PropertyNameArray&, EnumerationMode mode); + void getPropertyNames(JSGlobalData&, PropertyNameArray&, EnumerationMode mode); const ClassInfo* classInfo() const { return m_classInfo; } - static void initializeThreading(); - static ptrdiff_t prototypeOffset() { return OBJECT_OFFSETOF(Structure, m_prototype); @@ -161,37 +150,47 @@ namespace JSC { return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset(); } + static Structure* createStructure(JSGlobalData& globalData) + { + ASSERT(!globalData.structureStructure); + return new (&globalData) Structure(globalData); + } + private: - Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*); - Structure(const Structure*); + Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*); + Structure(JSGlobalData&); + Structure(JSGlobalData&, const Structure*); - static PassRefPtr<Structure> create(const Structure* structure) + static Structure* create(JSGlobalData& globalData, const Structure* structure) { - return adoptRef(new Structure(structure)); + ASSERT(globalData.structureStructure); + return new (&globalData) Structure(globalData, structure); } - + + static const ClassInfo s_info; + typedef enum { NoneDictionaryKind = 0, CachedDictionaryKind = 1, UncachedDictionaryKind = 2 } DictionaryKind; - static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind); + static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind); - size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); + size_t putSpecificValue(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t remove(const Identifier& propertyName); void createPropertyMap(unsigned keyCount = 0); void checkConsistency(); - bool despecifyFunction(const Identifier&); - void despecifyAllFunctions(); + bool despecifyFunction(JSGlobalData&, const Identifier&); + void despecifyAllFunctions(JSGlobalData&); - PropertyTable* copyPropertyTable(); - void materializePropertyMap(); - void materializePropertyMapIfNecessary() + PropertyTable* copyPropertyTable(JSGlobalData&, Structure* owner); + void materializePropertyMap(JSGlobalData&); + void materializePropertyMapIfNecessary(JSGlobalData& globalData) { if (!m_propertyTable && m_previous) - materializePropertyMap(); + materializePropertyMap(globalData); } signed char transitionCount() const @@ -210,18 +209,18 @@ namespace JSC { TypeInfo m_typeInfo; - DeprecatedPtr<Unknown> m_prototype; - mutable DeprecatedPtr<StructureChain> m_cachedPrototypeChain; + WriteBarrier<Unknown> m_prototype; + mutable WriteBarrier<StructureChain> m_cachedPrototypeChain; - RefPtr<Structure> m_previous; + WriteBarrier<Structure> m_previous; RefPtr<StringImpl> m_nameInPrevious; - JSCell* m_specificValueInPrevious; + WriteBarrier<JSCell> m_specificValueInPrevious; const ClassInfo* m_classInfo; StructureTransitionTable m_transitionTable; - WeakGCPtr<JSPropertyNameIterator> m_enumerationCache; + WriteBarrier<JSPropertyNameIterator> m_enumerationCache; OwnPtr<PropertyTable> m_propertyTable; @@ -248,9 +247,9 @@ namespace JSC { // 4 free bits }; - inline size_t Structure::get(const Identifier& propertyName) + inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName) { - materializePropertyMapIfNecessary(); + materializePropertyMapIfNecessary(globalData); if (!m_propertyTable) return notFound; @@ -259,6 +258,48 @@ namespace JSC { return entry ? entry->offset : notFound; } + inline bool JSCell::isObject() const + { + return m_structure->typeInfo().type() == ObjectType; + } + + inline bool JSCell::isString() const + { + return m_structure->typeInfo().type() == StringType; + } + + inline const ClassInfo* JSCell::classInfo() const + { + return m_structure->classInfo(); + } + + inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData) + { + return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); + } + + inline bool JSValue::needsThisConversion() const + { + if (UNLIKELY(!isCell())) + return true; + return asCell()->structure()->typeInfo().needsThisConversion(); + } + + ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) + { + ASSERT(!m_isCheckingForDefaultMarkViolation); + ASSERT(cell); + if (Heap::testAndSetMarked(cell)) + return; + if (cell->structure()->typeInfo().type() >= CompoundType) + m_values.append(cell); + } + + inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure) + { + return Hash::Key(structure->m_nameInPrevious.get(), structure->m_attributesInPrevious); + } + } // namespace JSC #endif // Structure_h diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp index 4fa4a4b..ad6abff 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.cpp +++ b/Source/JavaScriptCore/runtime/StructureChain.cpp @@ -31,20 +31,33 @@ #include <wtf/RefPtr.h> namespace JSC { + +ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0 }; -StructureChain::StructureChain(NonNullPassRefPtr<Structure> structure, Structure* head) - : JSCell(structure.releaseRef()) +StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure, Structure* head) + : JSCell(globalData, structure) { size_t size = 0; for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) ++size; - m_vector = adoptArrayPtr(new RefPtr<Structure>[size + 1]); + m_vector = adoptArrayPtr(new WriteBarrier<Structure>[size + 1]); size_t i = 0; for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) - m_vector[i++] = current; - m_vector[i] = 0; + m_vector[i++].set(globalData, this, current); + m_vector[i].clear(); +} + +StructureChain::~StructureChain() +{ +} + +void StructureChain::markChildren(MarkStack& markStack) +{ + size_t i = 0; + while (m_vector[i]) + markStack.append(&m_vector[i++]); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h index 88592dc..b984be6 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.h +++ b/Source/JavaScriptCore/runtime/StructureChain.h @@ -27,6 +27,7 @@ #define StructureChain_h #include "JSCell.h" +#include "Structure.h" #include <wtf/OwnArrayPtr.h> #include <wtf/PassRefPtr.h> @@ -41,14 +42,17 @@ namespace JSC { friend class JIT; public: - static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData.structureChainStructure, head); } - RefPtr<Structure>* head() { return m_vector.get(); } + static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData, globalData.structureChainStructure.get(), head); } + WriteBarrier<Structure>* head() { return m_vector.get(); } + void markChildren(MarkStack&); - static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), 0, 0); } - private: - StructureChain(NonNullPassRefPtr<Structure>, Structure* head); + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), 0, &s_info); } - OwnArrayPtr<RefPtr<Structure> > m_vector; + private: + StructureChain(JSGlobalData&, Structure*, Structure* head); + ~StructureChain(); + OwnArrayPtr<WriteBarrier<Structure> > m_vector; + static ClassInfo s_info; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h index da78e1b..adebad2 100644 --- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h @@ -27,8 +27,8 @@ #define StructureTransitionTable_h #include "UString.h" +#include "WeakGCMap.h" #include <wtf/HashFunctions.h> -#include <wtf/HashMap.h> #include <wtf/HashTraits.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> @@ -69,7 +69,21 @@ class StructureTransitionTable { static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } }; - typedef HashMap<Hash::Key, Structure*, Hash, HashTraits> TransitionMap; + struct WeakGCMapFinalizerCallback { + static void* finalizerContextFor(Hash::Key) + { + return 0; + } + + static inline Hash::Key keyForFinalizer(void* context, Structure* structure) + { + return keyForWeakGCMapFinalizer(context, structure); + } + }; + + typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap; + + static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*); public: StructureTransitionTable() @@ -81,9 +95,11 @@ public: { if (!isUsingSingleSlot()) delete map(); + else + clearSingleTransition(); } - inline void add(Structure*); + inline void add(JSGlobalData&, Structure*); inline void remove(Structure*); inline bool contains(StringImpl* rep, unsigned attributes) const; inline Structure* get(StringImpl* rep, unsigned attributes) const; @@ -100,9 +116,18 @@ private: return reinterpret_cast<TransitionMap*>(m_data); } + HandleSlot slot() const + { + ASSERT(isUsingSingleSlot()); + return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag); + } + void setMap(TransitionMap* map) { ASSERT(isUsingSingleSlot()); + + if (HandleSlot slot = this->slot()) + HandleHeap::heapFor(slot)->deallocate(slot); // This implicitly clears the flag that indicates we're using a single transition m_data = reinterpret_cast<intptr_t>(map); @@ -113,13 +138,31 @@ private: Structure* singleTransition() const { ASSERT(isUsingSingleSlot()); - return reinterpret_cast<Structure*>(m_data & ~UsingSingleSlotFlag); + if (HandleSlot slot = this->slot()) { + if (*slot) + return reinterpret_cast<Structure*>(slot->asCell()); + } + return 0; } - - void setSingleTransition(Structure* structure) + + void clearSingleTransition() { ASSERT(isUsingSingleSlot()); - m_data = reinterpret_cast<intptr_t>(structure) | UsingSingleSlotFlag; + if (HandleSlot slot = this->slot()) + HandleHeap::heapFor(slot)->deallocate(slot); + } + + void setSingleTransition(JSGlobalData& globalData, Structure* structure) + { + ASSERT(isUsingSingleSlot()); + HandleSlot slot = this->slot(); + if (!slot) { + slot = globalData.allocateGlobalHandle(); + HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0); + m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag; + } + HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure)); + *slot = reinterpret_cast<JSCell*>(structure); } intptr_t m_data; diff --git a/Source/JavaScriptCore/runtime/UString.h b/Source/JavaScriptCore/runtime/UString.h index 8f6c083..b98e7b4 100644 --- a/Source/JavaScriptCore/runtime/UString.h +++ b/Source/JavaScriptCore/runtime/UString.h @@ -252,10 +252,7 @@ template<> struct DefaultHash<JSC::UString> { typedef JSC::UStringHash Hash; }; -template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits -{ - static const bool canInitializeWithMemset = true; -}; +template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits { }; } // namespace WTF diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h index a40e684..5ad1c62 100644 --- a/Source/JavaScriptCore/runtime/WeakGCMap.h +++ b/Source/JavaScriptCore/runtime/WeakGCMap.h @@ -34,17 +34,31 @@ namespace JSC { // A HashMap for GC'd values that removes entries when the associated value // dies. -template<typename KeyType, typename MappedType> class WeakGCMap : private Finalizer { +template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback { + static void* finalizerContextFor(KeyType key) + { + return reinterpret_cast<void*>(key); + } + + static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType) + { + return reinterpret_cast<KeyType>(context); + } +}; + +template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> > +class WeakGCMap : private WeakHandleOwner { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(WeakGCMap); - typedef HashMap<KeyType, HandleSlot> MapType; + typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType; typedef typename HandleTypes<MappedType>::ExternalType ExternalType; typedef typename MapType::iterator map_iterator; public: struct iterator { + friend class WeakGCMap; iterator(map_iterator iter) : m_iterator(iter) { @@ -62,7 +76,7 @@ public: bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } private: - map_iterator m_iterator; + map_iterator m_iterator; }; WeakGCMap() @@ -78,6 +92,25 @@ public: m_map.clear(); } + bool contains(const KeyType& key) const + { + return m_map.contains(key); + } + + iterator find(const KeyType& key) + { + return m_map.find(key); + } + + void remove(iterator iter) + { + ASSERT(iter.m_iterator != m_map.end()); + HandleSlot slot = iter.m_iterator->second; + ASSERT(slot); + HandleHeap::heapFor(slot)->deallocate(slot); + m_map.remove(iter.m_iterator); + } + ExternalType get(const KeyType& key) const { return HandleTypes<MappedType>::getFromSlot(m_map.get(key)); @@ -88,14 +121,35 @@ public: return m_map.get(key); } + pair<iterator, bool> add(JSGlobalData& globalData, const KeyType& key, ExternalType value) + { + pair<typename MapType::iterator, bool> iter = m_map.add(key, 0); + if (iter.second) { + HandleSlot slot = globalData.allocateGlobalHandle(); + iter.first->second = slot; + HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key)); + HandleHeap::heapFor(slot)->writeBarrier(slot, value); + *slot = value; + } + return iter; + } + + void set(iterator iter, ExternalType value) + { + HandleSlot slot = iter.m_iterator->second; + ASSERT(slot); + HandleHeap::heapFor(slot)->writeBarrier(slot, value); + *slot = value; + } + void set(JSGlobalData& globalData, const KeyType& key, ExternalType value) { pair<typename MapType::iterator, bool> iter = m_map.add(key, 0); HandleSlot slot = iter.first->second; if (iter.second) { slot = globalData.allocateGlobalHandle(); - iter.first->second = slot; HandleHeap::heapFor(slot)->makeWeak(slot, this, key); + iter.first->second = slot; } HandleHeap::heapFor(slot)->writeBarrier(slot, value); *slot = value; @@ -113,22 +167,6 @@ public: size_t size() { return m_map.size(); } - bool deprecatedRemove(const KeyType& key, ExternalType value) - { - // This only exists in order to allow some semblance of correctness to - // the JSWeakObjectMapClear API - typename MapType::iterator iter = m_map.find(key); - if (iter == m_map.end()) - return false; - HandleSlot slot = iter->second; - ExternalType inmap = HandleTypes<MappedType>::getFromSlot(slot); - if (inmap && inmap != value) - return false; - m_map.remove(iter); - HandleHeap::heapFor(slot)->deallocate(slot); - return true; - } - iterator begin() { return iterator(m_map.begin()); } iterator end() { return iterator(m_map.end()); } @@ -138,9 +176,9 @@ public: } private: - virtual void finalize(Handle<Unknown>, void* key) + virtual void finalize(Handle<Unknown> handle, void* context) { - HandleSlot slot = m_map.take(static_cast<KeyType>(key)); + HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot()))); ASSERT(slot); HandleHeap::heapFor(slot)->deallocate(slot); } diff --git a/Source/JavaScriptCore/runtime/WeakGCPtr.h b/Source/JavaScriptCore/runtime/WeakGCPtr.h deleted file mode 100644 index 3f87b83..0000000 --- a/Source/JavaScriptCore/runtime/WeakGCPtr.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. 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 WeakGCPtr_h -#define WeakGCPtr_h - -#include "Global.h" -#include "Heap.h" - -namespace JSC { -// A smart pointer whose get() function returns 0 for cells that have died - -template <typename T> class WeakGCPtr : public HandleConverter<WeakGCPtr<T>, T> { - WTF_MAKE_NONCOPYABLE(WeakGCPtr); - -public: - typedef typename HandleTypes<T>::ExternalType ExternalType; - - WeakGCPtr() - : m_slot(0) - { - } - - WeakGCPtr(JSGlobalData& globalData, Finalizer* finalizer = 0, void* context = 0) - : m_slot(globalData.allocateGlobalHandle()) - { - HandleHeap::heapFor(m_slot)->makeWeak(m_slot, finalizer, context); - } - - WeakGCPtr(JSGlobalData& globalData, ExternalType value, Finalizer* finalizer = 0, void* context = 0) - : m_slot(globalData.allocateGlobalHandle()) - { - HandleHeap::heapFor(m_slot)->makeWeak(m_slot, finalizer, context); - internalSet(value); - } - - ExternalType get() const { return HandleTypes<T>::getFromSlot(m_slot); } - - void clear() - { - if (m_slot) - internalSet(ExternalType()); - } - - bool operator!() const { return !m_slot || !*m_slot; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef ExternalType (WeakGCPtr::*UnspecifiedBoolType); - operator UnspecifiedBoolType*() const { return !*this ? 0 : reinterpret_cast<UnspecifiedBoolType*>(1); } - - ~WeakGCPtr() - { - if (!m_slot) - return; - HandleHeap::heapFor(m_slot)->deallocate(m_slot); - } - - void set(JSGlobalData& globalData, ExternalType value, Finalizer* finalizer) - { - if (!this->m_slot) { - this->m_slot = globalData.allocateGlobalHandle(); - HandleHeap::heapFor(this->m_slot)->makeWeak(this->m_slot, finalizer, 0); - } else - ASSERT(HandleHeap::heapFor(this->m_slot)->getFinalizer(this->m_slot) == finalizer); - this->internalSet(value); - } - -private: - void internalSet(ExternalType value) - { - ASSERT(m_slot); - JSValue newValue(HandleTypes<T>::toJSValue(value)); - HandleHeap::heapFor(m_slot)->writeBarrier(m_slot, newValue); - *m_slot = newValue; - } - - HandleSlot m_slot; -}; - -} // namespace JSC - -#endif // WeakGCPtr_h diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h index af018a8..32cb968 100644 --- a/Source/JavaScriptCore/runtime/WriteBarrier.h +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -32,54 +32,17 @@ namespace JSC { class JSCell; class JSGlobalData; -typedef enum { } Unknown; -typedef JSValue* HandleSlot; - -// FIXME: Remove all uses of this class. -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; -}; - -// FIXME: Remove all uses of this class. -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; -}; +inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue) +{ +} -template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) +inline void writeBarrier(JSGlobalData&, const JSCell*, JSCell*) { - return lhs.get() == rhs.get(); } +typedef enum { } Unknown; +typedef JSValue* HandleSlot; + template <typename T> struct JSValueChecker { static const bool IsJSValue = false; }; @@ -92,11 +55,36 @@ template <> struct JSValueChecker<JSValue> { template <typename T> class WriteBarrierBase { public: COMPILE_ASSERT(!JSValueChecker<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); - void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } + void set(JSGlobalData& globalData, const JSCell* owner, T* value) + { + this->m_cell = reinterpret_cast<JSCell*>(value); + writeBarrier(globalData, owner, this->m_cell); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie(owner)); + ASSERT(!isZombie(m_cell)); +#endif + } - 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); } + T* get() const + { + return reinterpret_cast<T*>(m_cell); + } + + T* operator*() const + { + ASSERT(m_cell); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie(m_cell)); +#endif + return static_cast<T*>(m_cell); + } + + T* operator->() const + { + ASSERT(m_cell); + return static_cast<T*>(m_cell); + } + void clear() { m_cell = 0; } JSCell** slot() { return &m_cell; } @@ -106,7 +94,13 @@ public: bool operator!() const { return !m_cell; } - void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } + void setWithoutWriteBarrier(T* value) + { + this->m_cell = reinterpret_cast<JSCell*>(value); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!m_cell || !isZombie(m_cell)); +#endif + } private: JSCell* m_cell; @@ -114,12 +108,32 @@ private: 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 set(JSGlobalData& globalData, const JSCell* owner, JSValue value) + { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie(owner)); + ASSERT(!value.isZombie()); +#endif + m_value = JSValue::encode(value); + writeBarrier(globalData, owner, value); + } + void setWithoutWriteBarrier(JSValue value) + { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!value.isZombie()); +#endif + 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 isObject() const { return get().isObject(); } + bool isNull() const { return get().isNull(); } bool isGetterSetter() const { return get().isGetterSetter(); } JSValue* slot() |