diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime')
114 files changed, 1638 insertions, 1286 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp index 25a8916..f46d108 100644 --- a/Source/JavaScriptCore/runtime/ArgList.cpp +++ b/Source/JavaScriptCore/runtime/ArgList.cpp @@ -23,6 +23,7 @@ #include "JSValue.h" #include "JSCell.h" +#include "JSObject.h" #include "ScopeChain.h" using std::min; @@ -38,12 +39,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const result = ArgList(m_args + startIndex, m_argCount - startIndex); } -void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet) +void MarkedArgumentBuffer::markLists(HeapRootMarker& heapRootMarker, ListSet& markSet) { ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { MarkedArgumentBuffer* list = *it; - markStack.deprecatedAppendValues(list->m_buffer, list->m_size); + heapRootMarker.mark(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size); } } @@ -55,8 +56,8 @@ void MarkedArgumentBuffer::slowAppend(JSValue v) // our Vector's inline capacity, though, our values move to the // heap, where they do need explicit marking. if (!m_markSet) { - // We can only register for explicit marking once we know which heap - // is the current one, i.e., when a non-immediate value is appended. + // FIXME: Even if v is not a JSCell*, if previous values in the buffer + // are, then they won't be marked! if (Heap* heap = Heap::heap(v)) { ListSet& markSet = heap->markListSet(); markSet.add(this); diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h index 5564d5b..a794a04 100644 --- a/Source/JavaScriptCore/runtime/ArgList.h +++ b/Source/JavaScriptCore/runtime/ArgList.h @@ -141,7 +141,7 @@ namespace JSC { const_iterator begin() const { return m_buffer; } const_iterator end() const { return m_buffer + m_size; } - static void markLists(MarkStack&, ListSet&); + static void markLists(HeapRootMarker&, ListSet&); private: void slowAppend(JSValue); diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 007e0f1..950bb4e 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -92,9 +92,9 @@ namespace JSC { d->registers = &activation->registerAt(0); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -237,19 +237,17 @@ namespace JSC { // This JSActivation function is defined here so it can get at Arguments::setRegisters. inline void JSActivation::copyRegisters(JSGlobalData& globalData) { - ASSERT(!d()->registerArray); + ASSERT(!m_registerArray); - size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); - size_t numVars = d()->functionExecutable->capturedVariableCount(); - size_t numLocals = numVars + numParametersMinusThis; + size_t numLocals = m_numCapturedVars + m_numParametersMinusThis; if (!numLocals) return; - int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize; + int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize; size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; - OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, d()->registers - registerOffset, registerArraySize); + OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize); 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 af2afc6..e0f4b23 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -52,16 +52,18 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) { + JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); + // a single numeric argument denotes the array size (!) if (args.size() == 1 && args.at(0).isNumber()) { 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(exec->lexicalGlobalObject()->arrayStructure(), n, CreateInitialized); + return new (exec) JSArray(globalObject->arrayStructure(), n, CreateInitialized); } // otherwise the array is constructed with the arguments in it - return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), args); + return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), args); } static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 488effd..fdbcd95 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -165,16 +165,20 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + bool isRealArray = isJSArray(&exec->globalData(), thisValue); if (!isRealArray && !thisValue.inherits(&JSArray::s_info)) return throwVMTypeError(exec); JSArray* thisObj = asArray(thisValue); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) return earlyReturnValue; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned totalSize = length ? length - 1 : 0; #if OS(SYMBIAN) // Symbian has very limited stack size available. @@ -225,16 +229,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (!thisValue.inherits(&JSArray::s_info)) return throwVMTypeError(exec); JSObject* thisObj = asArray(thisValue); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) return earlyReturnValue; JSStringBuilder strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -260,6 +268,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) @@ -271,7 +282,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) if (!exec->argument(0).isUndefined()) separator = exec->argument(0).toString(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (isJSArray(&exec->globalData(), thisObj)) { JSArray* array = asArray(thisObj); @@ -355,12 +365,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (isJSArray(&exec->globalData(), thisValue)) return JSValue::encode(asArray(thisValue)->pop()); JSObject* thisObj = thisValue.toThisObject(exec); - JSValue result; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + JSValue result; if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); result = jsUndefined(); @@ -375,6 +389,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) { JSArray* array = asArray(thisValue); array->push(exec, exec->argument(0)); @@ -383,6 +398,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) JSObject* thisObj = thisValue.toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + for (unsigned n = 0; n < exec->argumentCount(); n++) thisObj->put(exec, length + n, exec->argument(n)); length += exec->argumentCount(); @@ -394,8 +412,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - unsigned middle = length / 2; + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned middle = length / 2; for (unsigned k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; JSValue obj2 = getProperty(exec, thisObj, lk1); @@ -420,6 +440,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec) JSValue result; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); result = jsUndefined(); @@ -451,6 +474,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) JSValue result = resObj; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length); @@ -466,6 +492,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (!length || exec->hadException()) + return JSValue::encode(thisObj); JSValue function = exec->argument(0); CallData callData; @@ -481,11 +510,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) return JSValue::encode(thisObj); } - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - - if (!length) - return JSValue::encode(thisObj); - // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { @@ -523,14 +547,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - // 15.4.4.12 + JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (!exec->argumentCount()) return JSValue::encode(constructEmptyArray(exec)); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned deleteCount = length - begin; @@ -589,10 +615,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - // 15.4.4.13 + + JSObject* thisObj = exec->hostThisValue().toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned nrArgs = exec->argumentCount(); if ((nrArgs) && (length)) { if (isJSArray(&exec->globalData(), thisObj)) @@ -616,6 +645,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -627,7 +659,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) JSArray* resultArray = constructEmptyArray(exec); unsigned filterIndex = 0; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -674,6 +705,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -683,8 +717,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - JSArray* resultArray = constructEmptyArray(exec, length); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { @@ -731,6 +763,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -742,7 +777,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) JSValue result = jsBoolean(true); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -787,6 +821,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -796,7 +833,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -832,6 +868,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -843,7 +882,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) JSValue result = jsBoolean(false); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -885,7 +923,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + JSValue function = exec->argument(0); CallData callData; CallType callType = getCallData(function, callData); @@ -894,9 +935,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) unsigned i = 0; JSValue rv; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length && exec->argumentCount() == 1) return throwVMTypeError(exec); + JSArray* array = 0; if (isJSArray(&exec->globalData(), thisObj)) array = asArray(thisObj); @@ -955,7 +996,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + JSValue function = exec->argument(0); CallData callData; CallType callType = getCallData(function, callData); @@ -964,9 +1008,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) unsigned i = 0; JSValue rv; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length && exec->argumentCount() == 1) return throwVMTypeError(exec); + JSArray* array = 0; if (isJSArray(&exec->globalData(), thisObj)) array = asArray(thisObj); @@ -1023,13 +1067,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) { - // JavaScript 1.5 Extension by Mozilla - // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf + // 15.4.4.14 JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length); JSValue searchElement = exec->argument(0); for (; index < length; ++index) { JSValue e = getProperty(exec, thisObj, index); @@ -1044,10 +1088,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) { - // JavaScript 1.6 Extension by Mozilla - // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf + // 15.4.4.15 JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length) return JSValue::encode(jsNumber(-1)); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index e41d8ca..96641bd 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -35,9 +35,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 21ef5bb..e5b0f3d 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -40,7 +40,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalOb // ECMA 15.6.2 JSObject* constructBoolean(ExecState* exec, const ArgList& args) { - BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -69,9 +69,9 @@ CallType BooleanConstructor::getCallData(CallData& callData) return CallTypeHost; } -JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue) +JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue) { - BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), globalObject->booleanObjectStructure()); obj->setInternalValue(exec->globalData(), immediateBooleanValue); return obj; } diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h index 0f3efa7..2550b3b 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.h +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h @@ -36,7 +36,7 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue); + JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue); JSObject* constructBoolean(ExecState*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index 16c4669..2945c0e 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& globalData, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(globalData, structure) +BooleanObject::BooleanObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index e2af0c2..ef2d403 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -31,9 +31,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } }; diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp index 83d8bd8..ac19705 100644 --- a/Source/JavaScriptCore/runtime/Completion.cpp +++ b/Source/JavaScriptCore/runtime/Completion.cpp @@ -39,7 +39,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); - RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); + ProgramExecutable* program = ProgramExecutable::create(exec, source); JSObject* error = program->checkSyntax(exec); if (error) return Completion(Throw, error); @@ -52,14 +52,16 @@ Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCod JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); - RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); - JSObject* error = program->compile(exec, scopeChain); - if (error) - return Completion(Throw, error); + ProgramExecutable* program = ProgramExecutable::create(exec, source); + if (!program) { + JSValue exception = exec->globalData().exception; + exec->globalData().exception = JSValue(); + return Completion(Throw, exception); + } JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); - JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain, thisObj); + JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj); if (exec->hadException()) { JSValue exception = exec->exception(); diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.cpp b/Source/JavaScriptCore/runtime/ConservativeSet.cpp index bc8bd6d..8872023 100644 --- a/Source/JavaScriptCore/runtime/ConservativeSet.cpp +++ b/Source/JavaScriptCore/runtime/ConservativeSet.cpp @@ -33,33 +33,26 @@ inline bool isPointerAligned(void* p) return !((intptr_t)(p) & (sizeof(char*) - 1)); } -void ConservativeSet::grow() +void ConservativeRoots::grow() { size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; - DeprecatedPtr<JSCell>* newSet = static_cast<DeprecatedPtr<JSCell>*>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); - memcpy(newSet, m_set, m_size * sizeof(JSCell*)); - if (m_set != m_inlineSet) - OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(JSCell*)); + 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_set = newSet; + m_roots = newRoots; } -void ConservativeSet::add(void* begin, void* end) +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) { - if (!m_heap->contains(*it)) - continue; - - if (m_size == m_capacity) - grow(); - - m_set[m_size++] = reinterpret_cast<JSCell*>(*it); - } + 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 index e7c2c4a..d078606 100644 --- a/Source/JavaScriptCore/runtime/ConservativeSet.h +++ b/Source/JavaScriptCore/runtime/ConservativeSet.h @@ -23,24 +23,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ConservativeSet_h -#define ConservativeSet_h +#ifndef ConservativeRoots_h +#define ConservativeRoots_h #include "Heap.h" -#include "MarkStack.h" +#include <wtf/OSAllocator.h> #include <wtf/Vector.h> namespace JSC { class JSCell; +class Heap; -class ConservativeSet { +// May contain duplicates. + +class ConservativeRoots { public: - ConservativeSet(Heap*); - ~ConservativeSet(); + ConservativeRoots(Heap*); + ~ConservativeRoots(); + void add(void*); void add(void* begin, void* end); - void mark(MarkStack&); + + size_t size(); + JSCell** roots(); private: static const size_t inlineCapacity = 128; @@ -49,32 +55,47 @@ private: void grow(); Heap* m_heap; - DeprecatedPtr<JSCell>* m_set; + JSCell** m_roots; size_t m_size; size_t m_capacity; - DeprecatedPtr<JSCell> m_inlineSet[inlineCapacity]; + JSCell* m_inlineRoots[inlineCapacity]; }; -inline ConservativeSet::ConservativeSet(Heap* heap) +inline ConservativeRoots::ConservativeRoots(Heap* heap) : m_heap(heap) - , m_set(m_inlineSet) + , m_roots(m_inlineRoots) , m_size(0) , m_capacity(inlineCapacity) { } -inline ConservativeSet::~ConservativeSet() +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() { - if (m_set != m_inlineSet) - OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(DeprecatedPtr<JSCell>*)); + return m_size; } -inline void ConservativeSet::mark(MarkStack& markStack) +inline JSCell** ConservativeRoots::roots() { - for (size_t i = 0; i < m_size; ++i) - markStack.append(&m_set[i]); + return m_roots; } } // namespace JSC -#endif // ConservativeSet_h +#endif // ConservativeRoots_h diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index efaeb0f..0a06148 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -70,7 +70,7 @@ DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, } // ECMA 15.9.3 -JSObject* constructDate(ExecState* exec, const ArgList& args) +JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { int numArgs = args.size(); @@ -121,13 +121,13 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) } } - return new (exec) DateInstance(exec, value); + return new (exec) DateInstance(exec, globalObject->dateStructure(), value); } static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructDate(exec, args)); + return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType DateConstructor::getConstructData(ConstructData& constructData) diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h index 2adcd08..bd529f1 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.h +++ b/Source/JavaScriptCore/runtime/DateConstructor.h @@ -36,7 +36,7 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructDate(ExecState*, const ArgList&); + JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp index 597f1e9..1418876 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.cpp +++ b/Source/JavaScriptCore/runtime/DateConversion.cpp @@ -44,6 +44,7 @@ #include "DateConversion.h" #include "CallFrame.h" +#include "JSObject.h" #include "ScopeChain.h" #include "UString.h" #include <wtf/DateMath.h> diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp index 95d5dc2..74adda4 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.cpp +++ b/Source/JavaScriptCore/runtime/DateInstance.cpp @@ -35,21 +35,14 @@ namespace JSC { const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0}; DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsNaN()); } DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time) - : JSWrapperObject(exec->globalData(), structure) -{ - ASSERT(inherits(&s_info)); - setInternalValue(exec->globalData(), jsNumber(timeClip(time))); -} - -DateInstance::DateInstance(ExecState* exec, double time) - : JSWrapperObject(exec->globalData(), exec->lexicalGlobalObject()->dateStructure()) + : JSWrapperObject(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 627b9e7..d0dcf0b 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.h +++ b/Source/JavaScriptCore/runtime/DateInstance.h @@ -31,7 +31,6 @@ namespace JSC { class DateInstance : public JSWrapperObject { public: - DateInstance(ExecState*, double); DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double); explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>); @@ -53,14 +52,11 @@ namespace JSC { return calculateGregorianDateTimeUTC(exec); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - protected: - static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; - private: const GregorianDateTime* calculateGregorianDateTime(ExecState*) const; const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/DatePrototype.h b/Source/JavaScriptCore/runtime/DatePrototype.h index dca90e3..0ebbedc 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.h +++ b/Source/JavaScriptCore/runtime/DatePrototype.h @@ -36,14 +36,16 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags; + COMPILE_ASSERT(!DateInstance::AnonymousSlotCount, DatePrototype_stomps_on_your_anonymous_slot); + static const unsigned AnonymousSlotCount = 1; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp index 2e53b95..7f4f82c 100644 --- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -42,7 +42,7 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState* exec) { JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined(); - Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); + Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure(); return JSValue::encode(ErrorInstance::create(exec, errorStructure, message)); } @@ -55,7 +55,7 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec) { JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined(); - Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); + Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure(); return JSValue::encode(ErrorInstance::create(exec, errorStructure, message)); } diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h index c1beef7..82dbf0f 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.h +++ b/Source/JavaScriptCore/runtime/ErrorInstance.h @@ -29,9 +29,9 @@ namespace JSC { public: static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static ErrorInstance* create(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&); diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 607a2c2..a059ed2 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -33,6 +33,11 @@ #include "UStringBuilder.h" #include "Vector.h" +#if ENABLE(DFG_JIT) +#include "DFGByteCodeParser.h" +#include "DFGJITCompiler.h" +#endif + namespace JSC { NativeExecutable::~NativeExecutable() @@ -44,7 +49,7 @@ VPtrHackExecutable::~VPtrHackExecutable() } EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) - : ScriptExecutable(exec, source, inStrictContext) + : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext) { } @@ -53,7 +58,7 @@ EvalExecutable::~EvalExecutable() } ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source, false) + : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false) { } @@ -62,7 +67,7 @@ ProgramExecutable::~ProgramExecutable() } FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) - : ScriptExecutable(globalData, source, inStrictContext) + : ScriptExecutable(globalData->functionExecutableStructure.get(), globalData, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -74,7 +79,7 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie } FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) - : ScriptExecutable(exec, source, inStrictContext) + : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -85,9 +90,6 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, m_lastLine = lastLine; } -FunctionExecutable::~FunctionExecutable() -{ -} JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { @@ -127,6 +129,13 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope return 0; } +void EvalExecutable::markChildren(MarkStack& markStack) +{ + ScriptExecutable::markChildren(markStack); + if (m_evalCodeBlock) + m_evalCodeBlock->markAggregate(markStack); +} + JSObject* ProgramExecutable::checkSyntax(ExecState* exec) { JSObject* exception = 0; @@ -178,6 +187,41 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc return 0; } +#if ENABLE(JIT) +static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck) +{ +#if ENABLE(DFG_JIT) +#if ENABLE(DFG_JIT_RESTRICTIONS) + // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets. + // FIXME: temporarily disable property accesses until we fix regressions. + if (codeBlock->numberOfJumpTargets() || codeBlock->numberOfStructureStubInfos()) + return false; +#endif + + DFG::Graph dfg; + if (!parse(dfg, globalData, codeBlock)) + return false; + + DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock); + dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck); + return true; +#else + UNUSED_PARAM(globalData); + UNUSED_PARAM(codeBlock); + UNUSED_PARAM(jitCode); + UNUSED_PARAM(jitCodeWithArityCheck); + return false; +#endif +} +#endif + +void ProgramExecutable::markChildren(MarkStack& markStack) +{ + ScriptExecutable::markChildren(markStack); + if (m_programCodeBlock) + m_programCodeBlock->markAggregate(markStack); +} + JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { JSObject* exception = 0; @@ -212,7 +256,10 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain #if ENABLE(JIT) if (exec->globalData().canUseJIT()) { - m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); + bool dfgCompiled = tryDFGCompile(&exec->globalData(), m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck); + if (!dfgCompiled) + m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); + #if !ENABLE(OPCODE_SAMPLING) if (!BytecodeGenerator::dumpsGeneratedCode()) m_codeBlockForCall->discardBytecode(); @@ -268,8 +315,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope return 0; } -void FunctionExecutable::markAggregate(MarkStack& markStack) +void FunctionExecutable::markChildren(MarkStack& markStack) { + ScriptExecutable::markChildren(markStack); if (m_codeBlockForCall) m_codeBlockForCall->markAggregate(markStack); if (m_codeBlockForConstruct) @@ -288,7 +336,7 @@ void FunctionExecutable::discardCode() #endif } -PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) +FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception); diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index b2565a0..f15df07 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -44,7 +44,7 @@ namespace JSC { struct ExceptionInfo; - class ExecutableBase : public RefCounted<ExecutableBase> { + class ExecutableBase : public JSCell { friend class JIT; protected: @@ -52,21 +52,23 @@ namespace JSC { static const int NUM_PARAMETERS_NOT_COMPILED = -1; public: - ExecutableBase(int numParameters) - : m_numParametersForCall(numParameters) + ExecutableBase(Structure* structure, int numParameters) + : JSCell(structure) + , m_numParametersForCall(numParameters) , m_numParametersForConstruct(numParameters) { } - virtual ~ExecutableBase() {} - bool isHostFunction() const { ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST)); 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); } + protected: + static const unsigned StructureFlags = 0; int m_numParametersForCall; int m_numParametersForConstruct; @@ -96,16 +98,16 @@ namespace JSC { friend class JIT; public: #if ENABLE(JIT) - static PassRefPtr<NativeExecutable> create(MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor) + static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor) { if (!callThunk) - return adoptRef(new NativeExecutable(JITCode(), function, JITCode(), constructor)); - return adoptRef(new NativeExecutable(JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor)); + return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor); + return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor); } #else - static PassRefPtr<NativeExecutable> create(NativeFunction function, NativeFunction constructor) + static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) { - return adoptRef(new NativeExecutable(function, constructor)); + return new (&globalData) NativeExecutable(globalData, function, constructor); } #endif @@ -115,8 +117,8 @@ namespace JSC { private: #if ENABLE(JIT) - NativeExecutable(JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor) - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor) + : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -126,8 +128,8 @@ namespace JSC { m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall(); } #else - NativeExecutable(NativeFunction function, NativeFunction constructor) - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) + : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -142,8 +144,8 @@ namespace JSC { class VPtrHackExecutable : public ExecutableBase { public: - VPtrHackExecutable() - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + VPtrHackExecutable(Structure* structure) + : ExecutableBase(structure, NUM_PARAMETERS_IS_HOST) { } @@ -152,8 +154,8 @@ namespace JSC { class ScriptExecutable : public ExecutableBase { public: - ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) + ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -166,8 +168,8 @@ namespace JSC { #endif } - ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) + ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -214,6 +216,7 @@ namespace JSC { JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_evalCodeBlock) error = compileInternal(exec, scopeChainNode); @@ -227,7 +230,7 @@ namespace JSC { return *m_evalCodeBlock; } - static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); } + static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); } #if ENABLE(JIT) JITCode& generatedJITCode() @@ -235,26 +238,30 @@ namespace JSC { return generatedJITCodeForCall(); } #endif + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; EvalExecutable(ExecState*, const SourceCode&, bool); JSObject* compileInternal(ExecState*, ScopeChainNode*); + virtual void markChildren(MarkStack&); OwnPtr<EvalCodeBlock> m_evalCodeBlock; }; class ProgramExecutable : public ScriptExecutable { public: - static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source) + static ProgramExecutable* create(ExecState* exec, const SourceCode& source) { - return adoptRef(new ProgramExecutable(exec, source)); + return new (exec) ProgramExecutable(exec, source); } ~ProgramExecutable(); JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_programCodeBlock) error = compileInternal(exec, scopeChainNode); @@ -276,11 +283,15 @@ namespace JSC { return generatedJITCodeForCall(); } #endif + + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; ProgramExecutable(ExecState*, const SourceCode&); JSObject* compileInternal(ExecState*, ScopeChainNode*); + virtual void markChildren(MarkStack&); OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; @@ -288,18 +299,16 @@ namespace JSC { class FunctionExecutable : public ScriptExecutable { friend class JIT; public: - static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); + return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine); } - static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); + return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine); } - ~FunctionExecutable(); - JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain) { return new (exec) JSFunction(exec, this, scopeChain); @@ -318,6 +327,7 @@ namespace JSC { JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_codeBlockForCall) error = compileForCallInternal(exec, scopeChainNode); @@ -338,6 +348,7 @@ namespace JSC { JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_codeBlockForConstruct) error = compileForConstructInternal(exec, scopeChainNode); @@ -363,8 +374,9 @@ namespace JSC { SharedSymbolTable* symbolTable() const { return m_symbolTable; } void discardCode(); - void markAggregate(MarkStack&); - static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + 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); } private: FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); @@ -372,7 +384,8 @@ namespace JSC { JSObject* compileForCallInternal(ExecState*, ScopeChainNode*); JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); - + + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; unsigned m_numCapturedVariables : 31; bool m_forceUsesArguments : 1; diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index e642594..a9f0a06 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -49,7 +49,7 @@ FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* global static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructFunction(exec, args)); + return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType FunctionConstructor::getConstructData(ConstructData& constructData) @@ -61,7 +61,7 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructFunction(exec, args)); + return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); } // ECMA 15.3.1 The Function Constructor Called as a Function @@ -72,7 +72,7 @@ CallType FunctionConstructor::getCallData(CallData& callData) } // ECMA 15.3.2 The Function Constructor -JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) +JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { // Functions need to have a space following the opening { due to for web compatibility // see https://bugs.webkit.org/show_bug.cgi?id=24350 @@ -96,11 +96,10 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi program = builder.toUString(); } - JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSGlobalData& globalData = globalObject->globalData(); SourceCode source = makeSource(program, sourceURL, lineNumber); JSObject* exception = 0; - RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); + FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); if (!function) { ASSERT(exception); return throwError(exec, exception); @@ -111,9 +110,9 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi } // ECMA 15.3.2 The Function Constructor -JSObject* constructFunction(ExecState* exec, const ArgList& args) +JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { - return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1); + return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h index 6af4861..7f21b20 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.h +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h @@ -36,8 +36,8 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); - JSObject* constructFunction(ExecState*, const ArgList&); + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.h b/Source/JavaScriptCore/runtime/FunctionPrototype.h index fb0bb48..447f00b 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.h +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.h @@ -30,9 +30,9 @@ namespace JSC { FunctionPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction); - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index a941cfa..2e878bf 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -33,6 +33,7 @@ #include "Heap.h" #include "JSGlobalData.h" #include "JSLock.h" +#include "JSObject.h" #include "ScopeChain.h" #include <wtf/RetainPtr.h> #include <wtf/WTFThreadData.h> diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h index 68a8c70..8241275 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.h +++ b/Source/JavaScriptCore/runtime/GetterSetter.h @@ -47,9 +47,9 @@ 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(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0); } private: virtual bool isGetterSetter() const; diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp index c52bcfe..e3ef8bb 100644 --- a/Source/JavaScriptCore/runtime/Heap.cpp +++ b/Source/JavaScriptCore/runtime/Heap.cpp @@ -46,7 +46,7 @@ Heap::Heap(JSGlobalData* globalData) , m_markListSet(0) , m_activityCallback(DefaultGCActivityCallback::create(this)) , m_globalData(globalData) - , m_machineStackMarker(this) + , m_machineThreads(this) , m_markStack(globalData->jsArrayVPtr) , m_handleHeap(globalData) , m_extraCost(0) @@ -75,6 +75,10 @@ void Heap::destroy() // (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(); @@ -97,7 +101,7 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost) // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. - if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.capacity() / 2) + if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.highWaterMark() / 2) collectAllGarbage(); m_extraCost += cost; } @@ -147,11 +151,11 @@ bool Heap::unprotect(JSValue k) return m_protectedValues.remove(k.asCell()); } -void Heap::markProtectedObjects(MarkStack& markStack) +void Heap::markProtectedObjects(HeapRootMarker& heapRootMarker) { ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - markStack.deprecatedAppend(&it->first); + heapRootMarker.mark(&it->first); } void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) @@ -165,7 +169,7 @@ void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) m_tempSortingVectors.removeLast(); } -void Heap::markTempSortVectors(MarkStack& markStack) +void Heap::markTempSortVectors(HeapRootMarker& heapRootMarker) { typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; @@ -176,7 +180,7 @@ void Heap::markTempSortVectors(MarkStack& markStack) Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) { if (vectorIt->first) - markStack.deprecatedAppend(&vectorIt->first); + heapRootMarker.mark(&vectorIt->first); } } } @@ -195,52 +199,52 @@ void Heap::markRoots() } #endif + void* dummy; + ASSERT(m_operationInProgress == NoOperation); if (m_operationInProgress != NoOperation) CRASH(); m_operationInProgress = Collection; - // We gather the conservative set before clearing mark bits, because + 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. - ConservativeSet conservativeSet(this); - m_machineStackMarker.markMachineStackConservatively(conservativeSet); - conservativeSet.add(registerFile().start(), registerFile().end()); + ConservativeRoots machineThreadRoots(this); + m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy); + + ConservativeRoots registerFileRoots(this); + registerFile().gatherConservativeRoots(registerFileRoots); m_markedSpace.clearMarks(); - MarkStack& markStack = m_markStack; - conservativeSet.mark(markStack); + markStack.append(machineThreadRoots); markStack.drain(); - // Mark explicitly registered roots. - markProtectedObjects(markStack); + markStack.append(registerFileRoots); markStack.drain(); - - // Mark temporary vector for Array sorting - markTempSortVectors(markStack); + + markProtectedObjects(heapRootMarker); markStack.drain(); - HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end(); - for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it) - (*it)->markAggregate(markStack); + markTempSortVectors(heapRootMarker); markStack.drain(); - // Mark misc. other roots. if (m_markListSet && m_markListSet->size()) - MarkedArgumentBuffer::markLists(markStack, *m_markListSet); + MarkedArgumentBuffer::markLists(heapRootMarker, *m_markListSet); if (m_globalData->exception) - markStack.append(&m_globalData->exception); - if (m_globalData->firstStringifierToMark) - JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); + heapRootMarker.mark(&m_globalData->exception); markStack.drain(); - m_handleHeap.markStrongHandles(markStack); + 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(markStack); + m_globalData->smallStrings.markChildren(heapRootMarker); markStack.drain(); markStack.compact(); @@ -371,7 +375,7 @@ void Heap::reset(SweepToggle sweepToggle) m_extraCost = 0; #if ENABLE(JSC_ZOMBIES) - sweep(); + sweepToggle = DoSweep; #endif if (sweepToggle == DoSweep) { @@ -379,7 +383,11 @@ void Heap::reset(SweepToggle sweepToggle) m_markedSpace.shrink(); } - size_t proportionalBytes = static_cast<size_t>(1.5 * m_markedSpace.size()); + // 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(); diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h index eb8af70..c2d3bac 100644 --- a/Source/JavaScriptCore/runtime/Heap.h +++ b/Source/JavaScriptCore/runtime/Heap.h @@ -23,6 +23,7 @@ #define Heap_h #include "HandleHeap.h" +#include "HandleStack.h" #include "MarkStack.h" #include "MarkedSpace.h" #include <wtf/Forward.h> @@ -33,6 +34,7 @@ namespace JSC { class GCActivityCallback; class GlobalCodeBlock; + class HeapRootMarker; class JSCell; class JSGlobalData; class JSValue; @@ -65,7 +67,7 @@ namespace JSC { JSGlobalData* globalData() const { return m_globalData; } MarkedSpace& markedSpace() { return m_markedSpace; } - MachineStackMarker& machineStackMarker() { return m_machineStackMarker; } + MachineThreads& machineThreads() { return m_machineThreads; } GCActivityCallback* activityCallback(); void setActivityCallback(PassOwnPtr<GCActivityCallback>); @@ -92,14 +94,15 @@ namespace JSC { void pushTempSortVector(Vector<ValueStringPair>*); void popTempSortVector(Vector<ValueStringPair>*); - - HashSet<GlobalCodeBlock*>& codeBlocks() { return m_codeBlocks; } - + HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } 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; @@ -111,8 +114,8 @@ namespace JSC { void reportExtraMemoryCostSlowCase(size_t); void markRoots(); - void markProtectedObjects(MarkStack&); - void markTempSortVectors(MarkStack&); + void markProtectedObjects(HeapRootMarker&); + void markTempSortVectors(HeapRootMarker&); enum SweepToggle { DoNotSweep, DoSweep }; void reset(SweepToggle); @@ -124,7 +127,6 @@ namespace JSC { ProtectCountSet m_protectedValues; Vector<Vector<ValueStringPair>* > m_tempSortingVectors; - HashSet<GlobalCodeBlock*> m_codeBlocks; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -132,10 +134,11 @@ namespace JSC { JSGlobalData* m_globalData; - MachineStackMarker m_machineStackMarker; + MachineThreads m_machineThreads; MarkStack m_markStack; HandleHeap m_handleHeap; - + HandleStack m_handleStack; + size_t m_extraCost; }; diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp index 3992418..4a99b19 100644 --- a/Source/JavaScriptCore/runtime/Identifier.cpp +++ b/Source/JavaScriptCore/runtime/Identifier.cpp @@ -22,6 +22,7 @@ #include "Identifier.h" #include "CallFrame.h" +#include "JSObject.h" #include "NumericStrings.h" #include "ScopeChain.h" #include <new> // for placement new @@ -90,7 +91,7 @@ bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length) struct IdentifierCStringTranslator { static unsigned hash(const char* c) { - return WTF::StringHasher::createHash<char>(c); + return StringHasher::computeHash<char>(c); } static bool equal(StringImpl* r, const char* s) @@ -150,7 +151,7 @@ struct UCharBuffer { struct IdentifierUCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { - return WTF::StringHasher::createHash<UChar>(buf.s, buf.length); + return StringHasher::computeHash<UChar>(buf.s, buf.length); } static bool equal(StringImpl* str, const UCharBuffer& buf) @@ -216,7 +217,7 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s, { if (length == 1) { UChar c = s[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } if (!length) @@ -243,7 +244,7 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI if (r->length() == 1) { UChar c = r->characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) r = globalData->smallStrings.singleCharacterStringRep(c); if (r->isIdentifier()) return r; diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h index 8427b8c..08c98a5 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.h +++ b/Source/JavaScriptCore/runtime/InternalFunction.h @@ -39,9 +39,9 @@ namespace JSC { const UString displayName(ExecState*); const UString calculatedDisplayName(ExecState*); - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h index 43dd0d3..54fe909 100644 --- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -35,9 +35,9 @@ namespace JSC { virtual bool isAPIValueWrapper() const { return true; } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0); } diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index eb9c7c1..d0c50dd 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -39,15 +39,23 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 }; -JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable) - : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers())) +JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable) + : Base(callFrame->globalData().activationStructure, functionExecutable->symbolTable(), callFrame->registers()) + , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount())) + , m_numCapturedVars(functionExecutable->capturedVariableCount()) + , m_requiresDynamicChecks(functionExecutable->usesEval()) + , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister()) { ASSERT(inherits(&s_info)); + + // We have to manually ref and deref the symbol table as JSVariableObject + // doesn't know about SharedSymbolTable + static_cast<SharedSymbolTable*>(m_symbolTable)->ref(); } JSActivation::~JSActivation() { - delete d(); + static_cast<SharedSymbolTable*>(m_symbolTable)->deref(); } void JSActivation::markChildren(MarkStack& markStack) @@ -55,30 +63,26 @@ void JSActivation::markChildren(MarkStack& markStack) Base::markChildren(markStack); // No need to mark our registers if they're still in the RegisterFile. - WriteBarrier<Unknown>* registerArray = d()->registerArray.get(); + WriteBarrier<Unknown>* registerArray = m_registerArray.get(); if (!registerArray) return; - size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); - - size_t count = numParametersMinusThis; - markStack.appendValues(registerArray, count); - - size_t numVars = d()->functionExecutable->capturedVariableCount(); + markStack.appendValues(registerArray, m_numParametersMinusThis); // Skip the call frame, which sits between the parameters and vars. - markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); + markStack.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues); } inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) { SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); - if (!entry.isNull()) { - ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); - slot.setValue(registerAt(entry.getIndex()).get()); - return true; - } - return false; + if (entry.isNull()) + return false; + if (entry.getIndex() >= m_numCapturedVars) + return false; + + slot.setValue(registerAt(entry.getIndex()).get()); + return true; } inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value) @@ -90,7 +94,9 @@ inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identif return false; if (entry.isReadOnly()) return true; - ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); + if (entry.getIndex() >= m_numCapturedVars) + return false; + registerAt(entry.getIndex()).set(globalData, this, value); return true; } @@ -99,9 +105,11 @@ void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope { SymbolTable::const_iterator end = symbolTable().end(); for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) { - ASSERT(it->second.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); - if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties)) - propertyNames.add(Identifier(exec, it->first.get())); + if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties) + continue; + if (it->second.getIndex() >= m_numCapturedVars) + continue; + propertyNames.add(Identifier(exec, it->first.get())); } // Skip the JSVariableObject implementation of getOwnPropertyNames JSObject::getOwnPropertyNames(exec, propertyNames, mode); @@ -116,8 +124,9 @@ inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, return false; SymbolTableEntry& entry = iter->second; ASSERT(!entry.isNull()); - if (entry.getIndex() >= static_cast<int>(d()->functionExecutable->capturedVariableCount())) + if (entry.getIndex() >= m_numCapturedVars) return false; + entry.setAttributes(attributes); registerAt(entry.getIndex()).set(globalData, this, value); return true; @@ -195,15 +204,15 @@ JSValue JSActivation::toStrictThisObject(ExecState*) const bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const { - requiresDynamicChecks = d()->functionExecutable->usesEval(); + requiresDynamicChecks = m_requiresDynamicChecks; return false; } JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&) { JSActivation* activation = asActivation(slotBase); - CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->d()->registers)); - int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister(); + CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers)); + int argumentsRegister = activation->m_argumentsRegister; if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue()) return arguments; int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister); diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 6e04041..7463f47 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -42,7 +42,7 @@ namespace JSC { class JSActivation : public JSVariableObject { typedef JSVariableObject Base; public: - JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>); + JSActivation(CallFrame*, FunctionExecutable*); virtual ~JSActivation(); virtual void markChildren(MarkStack&); @@ -66,29 +66,12 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static PassRefPtr<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; private: - struct JSActivationData : public JSVariableObjectData { - JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers) - : JSVariableObjectData(_functionExecutable->symbolTable(), registers) - , functionExecutable(_functionExecutable) - { - // We have to manually ref and deref the symbol table as JSVariableObjectData - // doesn't know about SharedSymbolTable - functionExecutable->symbolTable()->ref(); - } - ~JSActivationData() - { - static_cast<SharedSymbolTable*>(symbolTable)->deref(); - } - - RefPtr<FunctionExecutable> functionExecutable; - }; - bool symbolTableGet(const Identifier&, PropertySlot&); bool symbolTableGet(const Identifier&, PropertyDescriptor&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); @@ -98,7 +81,10 @@ namespace JSC { static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); - JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); } + int m_numParametersMinusThis; + int m_numCapturedVars : 31; + bool m_requiresDynamicChecks : 1; + int m_argumentsRegister; }; JSActivation* asActivation(JSValue); @@ -108,6 +94,11 @@ namespace JSC { ASSERT(asObject(value)->inherits(&JSActivation::s_info)); return static_cast<JSActivation*>(asObject(value)); } + + ALWAYS_INLINE JSActivation* Register::activation() const + { + return asActivation(jsValue()); + } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 822b84c..1d621fe 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -127,7 +127,7 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif JSArray::JSArray(VPtrStealingHackType) - : JSNonFinalObject(createStructure(jsNull())) + : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index ede3c61..1a6eba8 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -58,7 +58,6 @@ namespace JSC { enum ArrayCreationMode { CreateCompact, CreateInitialized }; class JSArray : public JSNonFinalObject { - friend class JIT; friend class Walker; public: @@ -125,13 +124,23 @@ namespace JSC { void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToRegisters(ExecState*, Register*, uint32_t); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } inline void markChildrenDirect(MarkStack& markStack); + static ptrdiff_t storageOffset() + { + return OBJECT_OFFSETOF(JSArray, m_storage); + } + + static ptrdiff_t vectorLengthOffset() + { + return OBJECT_OFFSETOF(JSArray, m_vectorLength); + } + protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -142,7 +151,7 @@ namespace JSC { void* subclassData() const; void setSubclassData(void*); - + private: bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); void putSlowCase(ExecState*, unsigned propertyName, JSValue); @@ -174,11 +183,8 @@ namespace JSC { return asArray(value.asCell()); } - inline bool isJSArray(JSGlobalData* globalData, JSValue v) - { - return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; - } inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; } + inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); } inline void JSArray::markChildrenDirect(MarkStack& markStack) { @@ -196,77 +202,6 @@ namespace JSC { } } - 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); - } - - inline 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 - } - // Rule from ECMA 15.2 about what an array index is. // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. inline unsigned Identifier::toArrayIndex(bool& ok) const diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp index ae735dc..fbaea1d 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp @@ -50,9 +50,9 @@ JSByteArray::~JSByteArray() #endif -PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype, const JSC::ClassInfo* classInfo) +PassRefPtr<Structure> JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo); } bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h index 6e91594..e674958 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ b/Source/JavaScriptCore/runtime/JSByteArray.h @@ -76,7 +76,7 @@ namespace JSC { } JSByteArray(ExecState*, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage); - static PassRefPtr<Structure> createStructure(JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo); + static PassRefPtr<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&); @@ -102,7 +102,7 @@ namespace JSC { private: enum VPtrStealingHackType { VPtrStealingHack }; JSByteArray(VPtrStealingHackType) - : JSNonFinalObject(createStructure(jsNull())) + : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) { } diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index 9acb777..ce7fe22 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -119,7 +119,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, P // This is not a general purpose implementation of getOwnPropertySlot. // It should only be called by JSValue::get. // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec); + JSObject* object = toObject(exec, exec->lexicalGlobalObject()); slot.setBase(object); if (!object->getPropertySlot(exec, identifier, slot)) slot.setUndefined(); @@ -131,7 +131,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl // This is not a general purpose implementation of getOwnPropertySlot. // It should only be called by JSValue::get. // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec); + JSObject* object = toObject(exec, exec->lexicalGlobalObject()); slot.setBase(object); if (!object->getPropertySlot(exec, identifier, slot)) slot.setUndefined(); @@ -140,27 +140,27 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) { - toObject(exec)->put(exec, identifier, value, slot); + toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot); } void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) { - toObject(exec)->put(exec, identifier, value); + toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value); } bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); } bool JSCell::deleteProperty(ExecState* exec, unsigned identifier) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); } JSObject* JSCell::toThisObject(ExecState* exec) const { - return toObject(exec); + return toObject(exec, exec->lexicalGlobalObject()); } JSValue JSCell::getJSNumber() @@ -203,7 +203,7 @@ UString JSCell::toString(ExecState*) const return UString(); } -JSObject* JSCell::toObject(ExecState*) const +JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const { ASSERT_NOT_REACHED(); return 0; diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 7313d52..ab0e237 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -35,6 +35,8 @@ namespace JSC { + class JSGlobalObject; + #if COMPILER(MSVC) // If WTF_MAKE_NONCOPYABLE is applied to JSCell we end up with a bunch of // undefined references to the JSCell copy constructor and assignment operator @@ -53,10 +55,9 @@ namespace JSC { WTF_MAKE_NONCOPYABLE(JSCell); #endif + friend class ExecutableBase; friend class GetterSetter; friend class Heap; - friend class JIT; - friend class JSNumberCell; friend class JSObject; friend class JSPropertyNameIterator; friend class JSString; @@ -67,15 +68,16 @@ namespace JSC { friend class MarkedSpace; friend class MarkedBlock; friend class ScopeChainNode; + friend class StructureChain; private: explicit JSCell(Structure*); virtual ~JSCell(); public: - static PassRefPtr<Structure> createDummyStructure() + static PassRefPtr<Structure> createDummyStructure(JSGlobalData& globalData) { - return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); + return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); } // Querying the type. @@ -107,7 +109,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; // Garbage collection. void* operator new(size_t, ExecState*); @@ -137,6 +139,16 @@ namespace JSC { // property names, we want a similar interface with appropriate optimizations.) bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + static ptrdiff_t structureOffset() + { + return OBJECT_OFFSETOF(JSCell, m_structure); + } + + Structure* const * addressOfStructure() const + { + return &m_structure; + } + protected: static const unsigned AnonymousSlotCount = 0; @@ -203,6 +215,11 @@ namespace JSC { return isCell() ? asCell()->getString(exec) : UString(); } + template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const + { + return jsValue().getString(exec); + } + inline JSObject* JSValue::getObject() const { return isCell() ? asCell()->getObject() : 0; @@ -322,24 +339,19 @@ namespace JSC { inline JSObject* JSValue::toObject(ExecState* exec) const { - return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec); + return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject()); } - inline JSObject* JSValue::toThisObject(ExecState* exec) const + inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const { - return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); + return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject); } - - template <typename T> void MarkStack::append(DeprecatedPtr<T>* slot) + + inline JSObject* JSValue::toThisObject(ExecState* exec) const { - internalAppend(slot->get()); + return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); } - template <typename T> void MarkStack::append(WriteBarrierBase<T>* slot) - { - internalAppend(slot->get()); - } - ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) { ASSERT(!m_isCheckingForDefaultMarkViolation); @@ -350,31 +362,6 @@ namespace JSC { m_values.append(cell); } - ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value) - { - ASSERT(value); - internalAppend(*value); - } - - ALWAYS_INLINE void MarkStack::deprecatedAppend(JSValue* value) - { - ASSERT(value); - internalAppend(*value); - } - - ALWAYS_INLINE void MarkStack::deprecatedAppend(Register* value) - { - ASSERT(value); - internalAppend(value->jsValue()); - } - - ALWAYS_INLINE void MarkStack::internalAppend(JSValue value) - { - ASSERT(value); - if (value.isCell()) - internalAppend(value.asCell()); - } - inline Heap* Heap::heap(JSValue v) { if (!v.isCell()) @@ -411,8 +398,10 @@ namespace JSC { inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes) { - ASSERT(bytes && bytes <= preciseCutoff); - return m_preciseSizeClasses[(bytes - 1) / preciseStep]; + ASSERT(bytes && bytes < maxCellSize); + if (bytes < preciseCutoff) + return m_preciseSizeClasses[(bytes - 1) / preciseStep]; + return m_impreciseSizeClasses[(bytes - 1) / impreciseStep]; } inline void* MarkedSpace::allocate(size_t bytes) diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 2ade441..dbfc606 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -56,16 +56,16 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) +JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure, VPtrHackExecutable* executable) : Base(structure) - , m_executable(adoptRef(new VPtrHackExecutable())) { ASSERT(inherits(&s_info)); + m_executable.setWithoutWriteBarrier(executable); } -JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk) +JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk) : Base(globalObject, structure) - , m_executable(thunk) + , m_executable(exec->globalData(), this, thunk) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); @@ -75,17 +75,20 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(globalObject, structure) - , m_executable(exec->globalData().getHostFunction(func)) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); + // We separate out intialisation from setting the executable + // as getHostFunction may perform a GC allocation, so we have to be able to + // mark ourselves safely + m_executable.set(exec->globalData(), this, exec->globalData().getHostFunction(func)); putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } -JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) +JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode) : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure()) - , m_executable(executable) + , m_executable(exec->globalData(), this, executable) , m_scopeChain(exec->globalData(), this, scopeChainNode) { ASSERT(inherits(&s_info)); @@ -96,19 +99,6 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex JSFunction::~JSFunction() { ASSERT(vptr() == JSGlobalData::jsFunctionVPtr); - - // JIT code for other functions may have had calls linked directly to the code for this function; these links - // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once - // this memory is freed and may be reused (potentially for another, different JSFunction). - if (!isHostFunction()) { -#if ENABLE(JIT_OPTIMIZE_CALL) - ASSERT(m_executable); - if (jsExecutable()->isGeneratedForCall()) - jsExecutable()->generatedBytecodeForCall().unlinkCallers(); - if (jsExecutable()->isGeneratedForConstruct()) - jsExecutable()->generatedBytecodeForConstruct().unlinkCallers(); -#endif - } } static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function"; @@ -148,9 +138,13 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec) void JSFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (!isHostFunction()) { - jsExecutable()->markAggregate(markStack); - markStack.append(&m_scopeChain); + + markStack.append(&m_scopeChain); + if (m_executable) { + // Delightful race condition: m_executable may not have been initialised + // if this is a host function, as the executable isn't necessarily created + // until after the function has been allocated. + markStack.append(&m_executable); } } diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 089f42e..505b9de 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -34,6 +34,7 @@ namespace JSC { class JSActivation; class JSGlobalObject; class NativeExecutable; + class VPtrHackExecutable; EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); @@ -45,8 +46,8 @@ namespace JSC { public: JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); - JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, PassRefPtr<NativeExecutable>); - JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*); + JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*); + JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); virtual ~JSFunction(); const UString& name(ExecState*); @@ -72,9 +73,9 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } NativeFunction nativeFunction(); @@ -86,7 +87,7 @@ namespace JSC { const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; private: - JSFunction(NonNullPassRefPtr<Structure>); + JSFunction(NonNullPassRefPtr<Structure>, VPtrHackExecutable*); bool isHostFunctionNonInline() const; @@ -102,7 +103,7 @@ namespace JSC { static JSValue callerGetter(ExecState*, JSValue, const Identifier&); static JSValue lengthGetter(ExecState*, JSValue, const Identifier&); - RefPtr<ExecutableBase> m_executable; + WriteBarrier<ExecutableBase> m_executable; WriteBarrier<ScopeChainNode> m_scopeChain; }; diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index e25040c..ee1829b 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -68,6 +68,27 @@ using namespace WTF; +namespace { + +using namespace JSC; + +class Recompiler { +public: + void operator()(JSCell*); +}; + +inline void Recompiler::operator()(JSCell* cell) +{ + if (!cell->inherits(&JSFunction::s_info)) + return; + JSFunction* function = asFunction(cell); + if (function->executable()->isHostFunction()) + return; + function->jsExecutable()->discardCode(); +} + +} // namespace + namespace JSC { extern JSC_CONST_HASHTABLE HashTable arrayTable; @@ -107,8 +128,12 @@ void JSGlobalData::storeVPtrs() jsString->~JSCell(); COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage); - JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); + 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)); JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); + executable->~JSCell(); jsFunction->~JSCell(); } @@ -124,18 +149,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) - , activationStructure(JSActivation::createStructure(jsNull())) - , interruptedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull())) - , terminatedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull())) - , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) - , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull())) - , stringStructure(JSString::createStructure(jsNull())) - , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) - , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull())) - , getterSetterStructure(GetterSetter::createStructure(jsNull())) - , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) - , scopeChainNodeStructure(ScopeChainNode::createStructure(jsNull())) - , dummyMarkableCellStructure(JSCell::createDummyStructure()) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) @@ -145,7 +158,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , heap(this) , globalObjectCount(0) , dynamicGlobalObject(0) - , firstStringifierToMark(0) , cachedUTCOffset(NaN) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_regExpCache(new RegExpCache(this)) @@ -156,6 +168,24 @@ 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(); @@ -282,18 +312,18 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal() } #if ENABLE(JIT) -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function) { return jitStubs->hostFunctionStub(this, function); } -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) { return jitStubs->hostFunctionStub(this, function, generator); } #else -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function) { - return NativeExecutable::create(function, callHostFunctionAsConstructor); + return NativeExecutable::create(*this, function, callHostFunctionAsConstructor); } #endif @@ -325,22 +355,6 @@ void JSGlobalData::dumpSampleData(ExecState* exec) interpreter->dumpSampleData(exec); } -class Recompiler { -public: - void operator()(JSCell*); -}; - -inline void Recompiler::operator()(JSCell* cell) -{ - if (!cell->inherits(&JSFunction::s_info)) - return; - JSFunction* function = asFunction(cell); - if (function->executable()->isHostFunction()) - return; - function->jsExecutable()->discardCode(); -} - - void JSGlobalData::recompileAllJSFunctions() { // If JavaScript is running, it's not safe to recompile, since we'll end diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index ee3e067..34ea75d 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -57,6 +57,7 @@ namespace JSC { class CodeBlock; class CommonIdentifiers; + class HandleStack; class IdentifierTable; class Interpreter; class JSGlobalObject; @@ -128,7 +129,7 @@ namespace JSC { #if ENABLE(JSC_MULTIPLE_THREADS) // Will start tracking threads that use the heap, which is resource-heavy. - void makeUsableFromMultipleThreads() { heap.machineStackMarker().makeUsableFromMultipleThreads(); } + void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } #endif GlobalDataType globalDataType; @@ -155,7 +156,12 @@ namespace JSC { 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; static void storeVPtrs(); static JS_EXPORTDATA void* jsArrayVPtr; @@ -199,15 +205,15 @@ namespace JSC { { return jitStubs->ctiStub(this, generator); } - PassRefPtr<NativeExecutable> getHostFunction(NativeFunction, ThunkGenerator); + NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator); #endif - PassRefPtr<NativeExecutable> getHostFunction(NativeFunction); + NativeExecutable* getHostFunction(NativeFunction); TimeoutChecker timeoutChecker; Terminator terminator; Heap heap; - DeprecatedPtr<Unknown> exception; + JSValue exception; #if ENABLE(JIT) ReturnAddressPtr exceptionLocation; #endif @@ -219,8 +225,6 @@ namespace JSC { HashSet<JSObject*> stringRecursionCheckVisitedObjects; - Stringifier* firstStringifierToMark; - double cachedUTCOffset; DSTOffsetCache dstOffsetCache; @@ -255,6 +259,7 @@ namespace JSC { #endif void dumpRegExpTrace(); HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); } + HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); } private: JSGlobalData(GlobalDataType, ThreadStackType); diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 28fc07d..a2bbfbd 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -88,21 +88,21 @@ 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()); - if (d()->debugger) - d()->debugger->detach(this); + if (m_debugger) + m_debugger->detach(this); Profiler** profiler = Profiler::enabledProfilerReference(); if (UNLIKELY(*profiler != 0)) { - (*profiler)->stopProfiling(globalExec(), UString()); + (*profiler)->stopProfiling(this); } - - d()->destructor(d()); } void JSGlobalObject::init(JSObject* thisValue) @@ -111,14 +111,14 @@ void JSGlobalObject::init(JSObject* thisValue) structure()->disableSpecificFunctionTracking(); - d()->globalData = Heap::heap(this)->globalData(); - d()->globalScopeChain.set(*d()->globalData, this, new (d()->globalData.get()) ScopeChainNode(0, this, d()->globalData.get(), this, thisValue)); + m_globalData = Heap::heap(this)->globalData(); + m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue)); - JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.get(), CallFrame::noCaller(), 0, 0); + JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); - d()->debugger = 0; + m_debugger = 0; - d()->profileGroup = 0; + m_profileGroup = 0; reset(prototype()); } @@ -177,80 +177,80 @@ void JSGlobalObject::reset(JSValue prototype) // Prototypes - d()->functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull()))); // The real prototype will be set once ObjectPrototype is created. - d()->functionStructure = JSFunction::createStructure(d()->functionPrototype.get()); - d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype.get()); + 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()); JSFunction* callFunction = 0; JSFunction* applyFunction = 0; - d()->functionPrototype->addFunctionProperties(exec, this, d()->functionStructure.get(), &callFunction, &applyFunction); - d()->callFunction.set(exec->globalData(), this, callFunction); - d()->applyFunction.set(exec->globalData(), this, applyFunction); - d()->objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->functionStructure.get())); - d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype.get()); + 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()); - d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); + m_emptyObjectStructure = m_objectPrototype->inheritorID(exec->globalData()); - d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype.get()); - d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype.get()); - d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype.get()); - d()->callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(d()->objectPrototype.get()); + 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()); - d()->arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(d()->objectPrototype.get()))); - d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype.get()); - d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype.get()); + 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()); - d()->stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype.get()))); - d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype.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()); - d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype.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()); - d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype.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()); - d()->datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(d()->objectPrototype.get()))); - d()->dateStructure = DateInstance::createStructure(d()->datePrototype.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()); - d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype.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()); - d()->methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); + m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); - ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get()); - d()->errorStructure = ErrorInstance::createStructure(errorPrototype); + ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()); + m_errorStructure = ErrorInstance::createStructure(exec->globalData(), errorPrototype); // Constructors - JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.get()); - JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(d()->functionPrototype.get()), d()->functionPrototype.get()); - JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype.get()), d()->arrayPrototype.get(), d()->functionStructure.get()); - JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.get(), d()->stringPrototype.get()); - JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(d()->functionPrototype.get()), d()->booleanPrototype.get()); - JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(d()->functionPrototype.get()), d()->numberPrototype.get()); - JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.get(), d()->datePrototype.get()); - - d()->regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype.get()), d()->regExpPrototype.get())); - - d()->errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(d()->functionPrototype.get()), errorPrototype)); - - RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype); - RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype.get()); - d()->evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); - d()->rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); - d()->referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); - d()->syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); - d()->typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); - d()->URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); - - d()->objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); - d()->functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); - d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); - d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); - d()->stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); - d()->numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); - d()->datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); - d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->regExpConstructor.get(), DontEnum); - errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->errorConstructor.get(), DontEnum); + JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_objectPrototype.get()); + JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionPrototype.get()); + JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_arrayPrototype.get(), m_functionStructure.get()); + JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_stringPrototype.get()); + JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_booleanPrototype.get()); + JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_numberPrototype.get()); + JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_datePrototype.get()); + + m_regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_regExpPrototype.get())); + + 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()); + 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")); + m_syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); + m_typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); + m_URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); + + m_objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); + m_functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); + m_arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); + m_booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); + m_stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); + m_numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); + m_datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); + m_regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum); + errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); // Set global constructors @@ -263,42 +263,42 @@ void JSGlobalObject::reset(JSValue prototype) putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum); putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum); putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), d()->regExpConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), d()->errorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), d()->evalErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), d()->rangeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), d()->typeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), d()->URIErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum); // Set global values. GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete) + GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); // Set global functions. - d()->evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval)); - putDirectFunctionWithoutTransition(exec, d()->evalFunction.get(), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); + m_evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval)); + putDirectFunctionWithoutTransition(exec, m_evalFunction.get(), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); #ifndef NDEBUG - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif resetPrototype(prototype); @@ -310,7 +310,7 @@ void JSGlobalObject::resetPrototype(JSValue prototype) setPrototype(prototype); JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); - JSObject* objectPrototype = d()->objectPrototype.get(); + JSObject* objectPrototype = m_objectPrototype.get(); if (oldLastInPrototypeChain != objectPrototype) oldLastInPrototypeChain->setPrototype(objectPrototype); } @@ -318,67 +318,63 @@ void JSGlobalObject::resetPrototype(JSValue prototype) void JSGlobalObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - - markIfNeeded(markStack, &d()->globalScopeChain); - - markIfNeeded(markStack, &d()->regExpConstructor); - markIfNeeded(markStack, &d()->errorConstructor); - markIfNeeded(markStack, &d()->evalErrorConstructor); - markIfNeeded(markStack, &d()->rangeErrorConstructor); - markIfNeeded(markStack, &d()->referenceErrorConstructor); - markIfNeeded(markStack, &d()->syntaxErrorConstructor); - markIfNeeded(markStack, &d()->typeErrorConstructor); - markIfNeeded(markStack, &d()->URIErrorConstructor); - - markIfNeeded(markStack, &d()->evalFunction); - markIfNeeded(markStack, &d()->callFunction); - markIfNeeded(markStack, &d()->applyFunction); - - markIfNeeded(markStack, &d()->objectPrototype); - markIfNeeded(markStack, &d()->functionPrototype); - markIfNeeded(markStack, &d()->arrayPrototype); - markIfNeeded(markStack, &d()->booleanPrototype); - markIfNeeded(markStack, &d()->stringPrototype); - markIfNeeded(markStack, &d()->numberPrototype); - markIfNeeded(markStack, &d()->datePrototype); - markIfNeeded(markStack, &d()->regExpPrototype); - - markIfNeeded(markStack, &d()->methodCallDummy); - - markIfNeeded(markStack, d()->errorStructure); - markIfNeeded(markStack, d()->argumentsStructure); - markIfNeeded(markStack, d()->arrayStructure); - markIfNeeded(markStack, d()->booleanObjectStructure); - markIfNeeded(markStack, d()->callbackConstructorStructure); - markIfNeeded(markStack, d()->callbackFunctionStructure); - markIfNeeded(markStack, d()->callbackObjectStructure); - markIfNeeded(markStack, d()->dateStructure); - markIfNeeded(markStack, d()->emptyObjectStructure); - markIfNeeded(markStack, d()->errorStructure); - markIfNeeded(markStack, d()->functionStructure); - markIfNeeded(markStack, d()->numberObjectStructure); - markIfNeeded(markStack, d()->regExpMatchesArrayStructure); - markIfNeeded(markStack, d()->regExpStructure); - markIfNeeded(markStack, d()->stringObjectStructure); - - // No need to mark the other structures, because their prototypes are all - // guaranteed to be referenced elsewhere. - - if (d()->registerArray) { + + markIfNeeded(markStack, &m_globalScopeChain); + markIfNeeded(markStack, &m_methodCallDummy); + + markIfNeeded(markStack, &m_regExpConstructor); + markIfNeeded(markStack, &m_errorConstructor); + markIfNeeded(markStack, &m_evalErrorConstructor); + markIfNeeded(markStack, &m_rangeErrorConstructor); + markIfNeeded(markStack, &m_referenceErrorConstructor); + markIfNeeded(markStack, &m_syntaxErrorConstructor); + markIfNeeded(markStack, &m_typeErrorConstructor); + markIfNeeded(markStack, &m_URIErrorConstructor); + + markIfNeeded(markStack, &m_evalFunction); + markIfNeeded(markStack, &m_callFunction); + markIfNeeded(markStack, &m_applyFunction); + + markIfNeeded(markStack, &m_objectPrototype); + markIfNeeded(markStack, &m_functionPrototype); + markIfNeeded(markStack, &m_arrayPrototype); + markIfNeeded(markStack, &m_booleanPrototype); + markIfNeeded(markStack, &m_stringPrototype); + markIfNeeded(markStack, &m_numberPrototype); + 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); + + if (m_registerArray) { // Outside the execution of global code, when our variables are torn off, // we can mark the torn-off array. - markStack.appendValues(d()->registerArray.get(), d()->registerArraySize); - } else if (d()->registers) { + markStack.appendValues(m_registerArray.get(), m_registerArraySize); + } else if (m_registers) { // During execution of global code, when our variables are in the register file, // the symbol table tells us how many variables there are, and registers // points to where they end, and the registers used for execution begin. - markStack.appendValues(d()->registers - symbolTable().size(), symbolTable().size()); + markStack.appendValues(m_registers - symbolTable().size(), symbolTable().size()); } } ExecState* JSGlobalObject::globalExec() { - return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize); + return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize); } bool JSGlobalObject::isDynamicScope(bool&) const @@ -388,12 +384,12 @@ bool JSGlobalObject::isDynamicScope(bool&) const void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) { - ASSERT(!d()->registerArray); - ASSERT(!d()->registerArraySize); + ASSERT(!m_registerArray); + ASSERT(!m_registerArraySize); int numGlobals = registerFile.numGlobals(); if (!numGlobals) { - d()->registers = 0; + m_registers = 0; return; } @@ -411,24 +407,24 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) registerFile.setGlobalObject(this); registerFile.setNumGlobals(symbolTable().size()); - if (d()->registerArray) { + if (m_registerArray) { // The register file is always a gc root so no barrier is needed here - memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(WriteBarrier<Unknown>)); + memcpy(registerFile.start() - m_registerArraySize, m_registerArray.get(), m_registerArraySize * sizeof(WriteBarrier<Unknown>)); setRegisters(reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.start()), nullptr, 0); } } void JSGlobalObject::resizeRegisters(int oldSize, int newSize) { - ASSERT(symbolTable().size() == newSize); + ASSERT(oldSize <= newSize); if (newSize == oldSize) return; ASSERT(newSize && newSize > oldSize); - if (d()->registerArray || !d()->registers) { - ASSERT(static_cast<size_t>(oldSize) == d()->registerArraySize); + if (m_registerArray || !m_registers) { + ASSERT(static_cast<size_t>(oldSize) == m_registerArraySize); OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]); for (int i = 0; i < oldSize; i++) - registerArray[newSize - oldSize + i].set(globalData(), this, d()->registerArray[i].get()); + registerArray[newSize - oldSize + i].set(globalData(), this, m_registerArray[i].get()); WriteBarrier<Unknown>* registers = registerArray.get() + newSize; setRegisters(registers, registerArray.release(), newSize); } else { @@ -437,7 +433,7 @@ void JSGlobalObject::resizeRegisters(int oldSize, int newSize) } for (int i = -newSize; i < -oldSize; ++i) - d()->registers[i].setUndefined(); + m_registers[i].setUndefined(); } void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) @@ -445,26 +441,21 @@ void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) return globalData->heap.allocate(size); } -void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData) -{ - delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData); -} - -DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) - : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) +DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject) + : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject) , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) { if (!m_dynamicGlobalObjectSlot) { #if ENABLE(ASSEMBLER) if (ExecutableAllocator::underMemoryPressure()) - callFrame->globalData().recompileAllJSFunctions(); + globalData.recompileAllJSFunctions(); #endif m_dynamicGlobalObjectSlot = dynamicGlobalObject; // Reset the date cache between JS invocations to force the VM // to observe time zone changes. - callFrame->globalData().resetDateCache(); + globalData.resetDateCache(); } } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 03b39fc..04f63eb 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -28,6 +28,7 @@ #include "JSWeakObjectMapRefInternal.h" #include "NumberPrototype.h" #include "StringPrototype.h" +#include "StructureChain.h" #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/RandomNumber.h> @@ -54,92 +55,70 @@ namespace JSC { class JSGlobalObject : public JSVariableObject { protected: - using JSVariableObject::JSVariableObjectData; typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet; - struct JSGlobalObjectData : public JSVariableObjectData { - // We use an explicit destructor function pointer instead of a - // virtual destructor because we want to avoid adding a vtable - // pointer to this struct. Adding a vtable pointer would force the - // compiler to emit costly pointer fixup code when casting from - // JSVariableObjectData* to JSGlobalObjectData*. - typedef void (*Destructor)(void*); - - JSGlobalObjectData(Destructor destructor) - : JSVariableObjectData(&symbolTable, 0) - , destructor(destructor) - , registerArraySize(0) - , globalScopeChain() - , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) - { - } - - Destructor destructor; - - size_t registerArraySize; - - JSGlobalObject* next; - JSGlobalObject* prev; - - Debugger* debugger; - - WriteBarrier<ScopeChainNode> globalScopeChain; - Register globalCallFrame[RegisterFile::CallFrameHeaderSize]; - - WriteBarrier<RegExpConstructor> regExpConstructor; - WriteBarrier<ErrorConstructor> errorConstructor; - WriteBarrier<NativeErrorConstructor> evalErrorConstructor; - WriteBarrier<NativeErrorConstructor> rangeErrorConstructor; - WriteBarrier<NativeErrorConstructor> referenceErrorConstructor; - WriteBarrier<NativeErrorConstructor> syntaxErrorConstructor; - WriteBarrier<NativeErrorConstructor> typeErrorConstructor; - WriteBarrier<NativeErrorConstructor> URIErrorConstructor; - - WriteBarrier<JSFunction> evalFunction; - WriteBarrier<JSFunction> callFunction; - WriteBarrier<JSFunction> applyFunction; - - WriteBarrier<ObjectPrototype> objectPrototype; - WriteBarrier<FunctionPrototype> functionPrototype; - WriteBarrier<ArrayPrototype> arrayPrototype; - WriteBarrier<BooleanPrototype> booleanPrototype; - WriteBarrier<StringPrototype> stringPrototype; - WriteBarrier<NumberPrototype> numberPrototype; - WriteBarrier<DatePrototype> datePrototype; - WriteBarrier<RegExpPrototype> regExpPrototype; - - WriteBarrier<JSObject> methodCallDummy; - - RefPtr<Structure> argumentsStructure; - RefPtr<Structure> arrayStructure; - RefPtr<Structure> booleanObjectStructure; - RefPtr<Structure> callbackConstructorStructure; - RefPtr<Structure> callbackFunctionStructure; - RefPtr<Structure> callbackObjectStructure; - RefPtr<Structure> dateStructure; - RefPtr<Structure> emptyObjectStructure; - RefPtr<Structure> errorStructure; - RefPtr<Structure> functionStructure; - RefPtr<Structure> numberObjectStructure; - RefPtr<Structure> regExpMatchesArrayStructure; - RefPtr<Structure> regExpStructure; - RefPtr<Structure> stringObjectStructure; - RefPtr<Structure> internalFunctionStructure; - - SymbolTable symbolTable; - unsigned profileGroup; - - RefPtr<JSGlobalData> globalData; - - WeakMapSet weakMaps; - WeakRandom weakRandom; - }; + RefPtr<JSGlobalData> m_globalData; + + size_t m_registerArraySize; + Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize]; + + WriteBarrier<ScopeChainNode> m_globalScopeChain; + WriteBarrier<JSObject> m_methodCallDummy; + + WriteBarrier<RegExpConstructor> m_regExpConstructor; + WriteBarrier<ErrorConstructor> m_errorConstructor; + WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor; + + WriteBarrier<JSFunction> m_evalFunction; + WriteBarrier<JSFunction> m_callFunction; + WriteBarrier<JSFunction> m_applyFunction; + + WriteBarrier<ObjectPrototype> m_objectPrototype; + WriteBarrier<FunctionPrototype> m_functionPrototype; + WriteBarrier<ArrayPrototype> m_arrayPrototype; + WriteBarrier<BooleanPrototype> m_booleanPrototype; + WriteBarrier<StringPrototype> m_stringPrototype; + WriteBarrier<NumberPrototype> m_numberPrototype; + 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; + + unsigned m_profileGroup; + Debugger* m_debugger; + + WeakMapSet m_weakMaps; + WeakRandom m_weakRandom; + + SymbolTable m_symbolTable; public: void* operator new(size_t, JSGlobalData*); - explicit JSGlobalObject() - : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData)) + explicit JSGlobalObject(JSGlobalData& globalData) + : JSVariableObject(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))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -147,7 +126,10 @@ namespace JSC { } explicit JSGlobalObject(NonNullPassRefPtr<Structure> structure) - : JSVariableObject(structure, new JSGlobalObjectData(destroyJSGlobalObjectData)) + : JSVariableObject(structure, &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -155,8 +137,11 @@ namespace JSC { } protected: - JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) - : JSVariableObject(structure, data) + JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSObject* thisValue) + : JSVariableObject(structure, &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -184,55 +169,57 @@ namespace JSC { // The following accessors return pristine values, even if a script // replaces the global object's associated property. - RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor.get(); } - - ErrorConstructor* errorConstructor() const { return d()->errorConstructor.get(); } - NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor.get(); } - NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor.get(); } - NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor.get(); } - NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor.get(); } - NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor.get(); } - NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor.get(); } - - JSFunction* evalFunction() const { return d()->evalFunction.get(); } - - ObjectPrototype* objectPrototype() const { return d()->objectPrototype.get(); } - FunctionPrototype* functionPrototype() const { return d()->functionPrototype.get(); } - ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype.get(); } - BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype.get(); } - StringPrototype* stringPrototype() const { return d()->stringPrototype.get(); } - NumberPrototype* numberPrototype() const { return d()->numberPrototype.get(); } - DatePrototype* datePrototype() const { return d()->datePrototype.get(); } - RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype.get(); } - - JSObject* methodCallDummy() const { return d()->methodCallDummy.get(); } - - Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } - Structure* arrayStructure() const { return d()->arrayStructure.get(); } - Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } - Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); } - Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); } - Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); } - Structure* dateStructure() const { return d()->dateStructure.get(); } - Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); } - Structure* errorStructure() const { return d()->errorStructure.get(); } - Structure* functionStructure() const { return d()->functionStructure.get(); } - Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } - Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); } - Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } - Structure* regExpStructure() const { return d()->regExpStructure.get(); } - Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } - - void setProfileGroup(unsigned value) { d()->profileGroup = value; } - unsigned profileGroup() const { return d()->profileGroup; } - - Debugger* debugger() const { return d()->debugger; } - void setDebugger(Debugger* debugger) { d()->debugger = debugger; } + RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); } + + ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); } + NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); } + NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); } + NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); } + NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); } + NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); } + NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); } + + JSFunction* evalFunction() const { return m_evalFunction.get(); } + JSFunction* callFunction() const { return m_callFunction.get(); } + JSFunction* applyFunction() const { return m_applyFunction.get(); } + + ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); } + FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); } + ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); } + BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); } + StringPrototype* stringPrototype() const { return m_stringPrototype.get(); } + NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); } + DatePrototype* datePrototype() const { return m_datePrototype.get(); } + RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); } + + JSObject* methodCallDummy() const { return m_methodCallDummy.get(); } + + Structure* argumentsStructure() const { return m_argumentsStructure.get(); } + Structure* arrayStructure() const { return m_arrayStructure.get(); } + Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } + Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } + Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } + Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); } + Structure* dateStructure() const { return m_dateStructure.get(); } + Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); } + Structure* errorStructure() const { return m_errorStructure.get(); } + Structure* functionStructure() const { return m_functionStructure.get(); } + Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); } + Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); } + Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } + Structure* regExpStructure() const { return m_regExpStructure.get(); } + Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } + + void setProfileGroup(unsigned value) { m_profileGroup = value; } + unsigned profileGroup() const { return m_profileGroup; } + + Debugger* debugger() const { return m_debugger; } + void setDebugger(Debugger* debugger) { m_debugger = debugger; } virtual bool supportsProfiling() const { return false; } virtual bool supportsRichSourceInfo() const { return true; } - ScopeChainNode* globalScopeChain() { return d()->globalScopeChain.get(); } + ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); } virtual bool isGlobalObject() const { return true; } @@ -250,25 +237,24 @@ namespace JSC { void resetPrototype(JSValue prototype); - JSGlobalData& globalData() const { return *d()->globalData.get(); } - JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); } + JSGlobalData& globalData() const { return *m_globalData.get(); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } void registerWeakMap(OpaqueJSWeakObjectMap* map) { - d()->weakMaps.add(map); + m_weakMaps.add(map); } void deregisterWeakMap(OpaqueJSWeakObjectMap* map) { - d()->weakMaps.remove(map); + m_weakMaps.remove(map); } - double weakRandomNumber() { return d()->weakRandom.get(); } + double weakRandomNumber() { return m_weakRandom.get(); } protected: static const unsigned AnonymousSlotCount = JSVariableObject::AnonymousSlotCount + 1; @@ -289,8 +275,6 @@ namespace JSC { void addStaticGlobals(GlobalPropertyInfo*, int count); private: - static void destroyJSGlobalObjectData(void*); - // FIXME: Fold reset into init. void init(JSObject* thisValue); void reset(JSValue prototype); @@ -311,17 +295,17 @@ namespace JSC { inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count) { JSVariableObject::setRegisters(registers, registerArray); - d()->registerArraySize = count; + m_registerArraySize = count; } inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) { - size_t oldSize = d()->registerArraySize; + size_t oldSize = m_registerArraySize; size_t newSize = oldSize + count; OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]); - if (d()->registerArray) { + if (m_registerArray) { // memcpy is safe here as we're copying barriers we already own from the existing array - memcpy(registerArray.get() + count, d()->registerArray.get(), oldSize * sizeof(Register)); + memcpy(registerArray.get() + count, m_registerArray.get(), oldSize * sizeof(Register)); } WriteBarrier<Unknown>* registers = registerArray.get() + newSize; @@ -379,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(prototype.isNull() ? 0 : asObject(prototype)->structure()); + m_cachedPrototypeChain = StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()); } return m_cachedPrototypeChain.get(); } @@ -451,7 +435,7 @@ namespace JSC { class DynamicGlobalObjectScope { WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope); public: - DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject); + DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); ~DynamicGlobalObjectScope() { diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index de1300a..f0da773 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -449,12 +449,12 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) if (JSValue parsedObject = preparser.tryLiteralParse()) return JSValue::encode(parsedObject); - RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false); + EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()); if (error) return throwVMError(exec, error); - return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); + return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); } EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp index 64dcb08..fc543f0 100644 --- a/Source/JavaScriptCore/runtime/JSLock.cpp +++ b/Source/JavaScriptCore/runtime/JSLock.cpp @@ -23,6 +23,7 @@ #include "Heap.h" #include "CallFrame.h" +#include "JSObject.h" #include "ScopeChain.h" #if USE(PTHREADS) diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp index e01b401..1115dc0 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -67,7 +67,7 @@ UString JSNotAnObject::toString(ExecState* exec) const return ""; } -JSObject* JSNotAnObject::toObject(ExecState* exec) const +JSObject* JSNotAnObject::toObject(ExecState* exec, JSGlobalObject*) const { ASSERT_UNUSED(exec, exec->hadException()); return const_cast<JSNotAnObject*>(this); diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h index 7e70a98..75bca18 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.h +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h @@ -43,9 +43,9 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: @@ -58,7 +58,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; // JSObject methods virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.cpp b/Source/JavaScriptCore/runtime/JSNumberCell.cpp index 3172cc9..79f2d2a 100644 --- a/Source/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/Source/JavaScriptCore/runtime/JSNumberCell.cpp @@ -22,6 +22,7 @@ #include "config.h" #include "JSNumberCell.h" +#include "JSObject.h" #include "ScopeChain.h" // Keep our exported symbols lists happy. diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 7d18e08..8fc7ac9 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -32,6 +32,8 @@ #include "JSArray.h" #include "JSGlobalObject.h" #include "LiteralParser.h" +#include "Local.h" +#include "LocalScope.h" #include "Lookup.h" #include "PropertyNameArray.h" #include "UStringBuilder.h" @@ -74,24 +76,22 @@ private: class Stringifier { WTF_MAKE_NONCOPYABLE(Stringifier); public: - Stringifier(ExecState*, JSValue replacer, JSValue space); - ~Stringifier(); - JSValue stringify(JSValue); + Stringifier(ExecState*, const Local<Unknown>& replacer, const Local<Unknown>& space); + Local<Unknown> stringify(Handle<Unknown>); void markAggregate(MarkStack&); private: class Holder { public: - Holder(JSObject*); + Holder(JSGlobalData&, JSObject*); JSObject* object() const { return m_object.get(); } - DeprecatedPtr<JSObject>* objectSlot() { return &m_object; } bool appendNextProperty(Stringifier&, UStringBuilder&); private: - DeprecatedPtr<JSObject> m_object; + Local<JSObject> m_object; const bool m_isArray; bool m_isJSArray; unsigned m_index; @@ -113,16 +113,14 @@ private: void unindent(); void startNewLine(UStringBuilder&) const; - Stringifier* const m_nextStringifierToMark; ExecState* const m_exec; - const JSValue m_replacer; + const Local<Unknown> m_replacer; bool m_usingArrayReplacer; PropertyNameArray m_arrayReplacerPropertyNames; CallType m_replacerCallType; CallData m_replacerCallData; const UString m_gap; - HashSet<JSObject*> m_holderCycleDetector; Vector<Holder, 16> m_holderStack; UString m_repeatedGap; UString m_indent; @@ -199,23 +197,20 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const // ------------------------------ Stringifier -------------------------------- -Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) - : m_nextStringifierToMark(exec->globalData().firstStringifierToMark) - , m_exec(exec) +Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const Local<Unknown>& space) + : m_exec(exec) , m_replacer(replacer) , m_usingArrayReplacer(false) , m_arrayReplacerPropertyNames(exec) , m_replacerCallType(CallTypeNone) - , m_gap(gap(exec, space)) + , m_gap(gap(exec, space.get())) { - exec->globalData().firstStringifierToMark = this; - if (!m_replacer.isObject()) return; - if (asObject(m_replacer)->inherits(&JSArray::s_info)) { + if (m_replacer.asObject()->inherits(&JSArray::s_info)) { m_usingArrayReplacer = true; - JSObject* array = asObject(m_replacer); + Handle<JSObject> array = m_replacer.asObject(); unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) { JSValue name = array->get(exec, i); @@ -246,40 +241,25 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) return; } - m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData); -} - -Stringifier::~Stringifier() -{ - ASSERT(m_exec->globalData().firstStringifierToMark == this); - m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark; -} - -void Stringifier::markAggregate(MarkStack& markStack) -{ - for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) { - size_t size = m_holderStack.size(); - for (size_t i = 0; i < size; ++i) - markStack.append(m_holderStack[i].objectSlot()); - } + m_replacerCallType = m_replacer.asObject()->getCallData(m_replacerCallData); } -JSValue Stringifier::stringify(JSValue value) +Local<Unknown> Stringifier::stringify(Handle<Unknown> value) { JSObject* object = constructEmptyObject(m_exec); if (m_exec->hadException()) - return jsNull(); + return Local<Unknown>(m_exec->globalData(), jsNull()); PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier); - object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value); + object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get()); UStringBuilder result; - if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded) - return jsUndefined(); + if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded) + return Local<Unknown>(m_exec->globalData(), jsUndefined()); if (m_exec->hadException()) - return jsNull(); + return Local<Unknown>(m_exec->globalData(), jsNull()); - return jsString(m_exec, result.toUString()); + return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString())); } void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value) @@ -372,7 +352,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& if (m_replacerCallType != CallTypeNone) { JSValue list[] = { propertyName.value(m_exec), value }; ArgList args(list, WTF_ARRAY_LENGTH(list)); - value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder, args); + value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args); if (m_exec->hadException()) return StringifyFailed; } @@ -425,12 +405,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& } // Handle cycle detection, and put the holder on the stack. - if (!m_holderCycleDetector.add(object).second) { - throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures.")); - return StringifyFailed; + for (unsigned i = 0; i < m_holderStack.size(); i++) { + if (m_holderStack[i].object() == object) { + throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures.")); + return StringifyFailed; + } } bool holderStackWasEmpty = m_holderStack.isEmpty(); - m_holderStack.append(object); + m_holderStack.append(Holder(m_exec->globalData(), object)); if (!holderStackWasEmpty) return StringifySucceeded; @@ -450,7 +432,6 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& tickCount = localTimeoutChecker.ticksUntilNextCheck(); } } - m_holderCycleDetector.remove(m_holderStack.last().object()); m_holderStack.removeLast(); } while (!m_holderStack.isEmpty()); return StringifySucceeded; @@ -485,8 +466,8 @@ inline void Stringifier::startNewLine(UStringBuilder& builder) const builder.append(m_indent); } -inline Stringifier::Holder::Holder(JSObject* object) - : m_object(object) +inline Stringifier::Holder::Holder(JSGlobalData& globalData, JSObject* object) + : m_object(globalData, object) , m_isArray(object->inherits(&JSArray::s_info)) , m_index(0) { @@ -623,16 +604,11 @@ bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor); } -void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier) -{ - stringifier->markAggregate(markStack); -} - class Walker { public: - Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData) + Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData) : m_exec(exec) - , m_function(function) + , m_function(exec->globalData(), function) , m_callType(callType) , m_callData(callData) { @@ -649,7 +625,7 @@ private: friend class Holder; ExecState* m_exec; - DeprecatedPtr<JSObject> m_function; + Local<JSObject> m_function; CallType m_callType; CallData m_callData; }; @@ -663,8 +639,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) { Vector<PropertyNameArray, 16> propertyStack; Vector<uint32_t, 16> indexStack; - Vector<JSObject*, 16> objectStack; - Vector<JSArray*, 16> arrayStack; + LocalStack<JSObject, 16> objectStack(m_exec->globalData()); + LocalStack<JSArray, 16> arrayStack(m_exec->globalData()); Vector<WalkerState, 16> stateStack; WalkerState state = StateUnknown; @@ -684,7 +660,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) return throwError(m_exec, createStackOverflowError(m_exec)); JSArray* array = asArray(inValue); - arrayStack.append(array); + arrayStack.push(array); indexStack.append(0); // fallthrough } @@ -696,11 +672,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) tickCount = localTimeoutChecker.ticksUntilNextCheck(); } - JSArray* array = arrayStack.last(); + JSArray* array = arrayStack.peek(); uint32_t index = indexStack.last(); if (index == array->length()) { outValue = array; - arrayStack.removeLast(); + arrayStack.pop(); indexStack.removeLast(); break; } @@ -722,7 +698,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) // fallthrough } case ArrayEndVisitMember: { - JSArray* array = arrayStack.last(); + JSArray* array = arrayStack.peek(); JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue); if (filteredValue.isUndefined()) array->deleteProperty(m_exec, indexStack.last()); @@ -745,7 +721,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) return throwError(m_exec, createStackOverflowError(m_exec)); JSObject* object = asObject(inValue); - objectStack.append(object); + objectStack.push(object); indexStack.append(0); propertyStack.append(PropertyNameArray(m_exec)); object->getOwnPropertyNames(m_exec, propertyStack.last()); @@ -759,12 +735,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) tickCount = localTimeoutChecker.ticksUntilNextCheck(); } - JSObject* object = objectStack.last(); + JSObject* object = objectStack.peek(); uint32_t index = indexStack.last(); PropertyNameArray& properties = propertyStack.last(); if (index == properties.size()) { outValue = object; - objectStack.removeLast(); + objectStack.pop(); indexStack.removeLast(); propertyStack.removeLast(); break; @@ -787,7 +763,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) // fallthrough } case ObjectEndVisitMember: { - JSObject* object = objectStack.last(); + JSObject* object = objectStack.peek(); Identifier prop = propertyStack.last()[indexStack.last()]; PutPropertySlot slot; JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue); @@ -838,7 +814,8 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) UString source = value.toString(exec); if (exec->hadException()) return JSValue::encode(jsNull()); - + + LocalScope scope(exec->globalData()); LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON); JSValue unfiltered = jsonParser.tryLiteralParse(); if (!unfiltered) @@ -852,7 +829,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) CallType callType = getCallData(function, callData); if (callType == CallTypeNone) return JSValue::encode(unfiltered); - return JSValue::encode(Walker(exec, asObject(function), callType, callData).walk(unfiltered)); + return JSValue::encode(Walker(exec, Local<JSObject>(exec->globalData(), asObject(function)), callType, callData).walk(unfiltered)); } // ECMA-262 v5 15.12.3 @@ -860,15 +837,17 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec) { if (!exec->argumentCount()) return throwVMError(exec, createError(exec, "No input to stringify")); - JSValue value = exec->argument(0); - JSValue replacer = exec->argument(1); - JSValue space = exec->argument(2); - return JSValue::encode(Stringifier(exec, replacer, space).stringify(value)); + LocalScope scope(exec->globalData()); + Local<Unknown> value(exec->globalData(), exec->argument(0)); + Local<Unknown> replacer(exec->globalData(), exec->argument(1)); + Local<Unknown> space(exec->globalData(), exec->argument(2)); + return JSValue::encode(Stringifier(exec, replacer, space).stringify(value).get()); } UString JSONStringify(ExecState* exec, JSValue value, unsigned indent) { - JSValue result = Stringifier(exec, jsNull(), jsNumber(indent)).stringify(value); + LocalScope scope(exec->globalData()); + Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->globalData(), jsNull()), Local<Unknown>(exec->globalData(), jsNumber(indent))).stringify(Local<Unknown>(exec->globalData(), value)); if (result.isUndefinedOrNull()) return UString(); return result.getString(exec); diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h index acffeca..a52c543 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.h +++ b/Source/JavaScriptCore/runtime/JSONObject.h @@ -36,13 +36,11 @@ namespace JSC { public: JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - static void markStringifiers(MarkStack&, Stringifier*); - protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 87fbb67..b307540 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -43,7 +43,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject); -ASSERT_CLASS_FILLS_CELL(JSFinalObject); +ASSERT_CLASS_FITS_IN_CELL(JSFinalObject); const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property."; @@ -489,7 +489,7 @@ UString JSObject::toString(ExecState* exec) const return primitive.toString(exec); } -JSObject* JSObject::toObject(ExecState*) const +JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const { return const_cast<JSObject*>(this); } @@ -572,9 +572,9 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr slot.setUndefined(); } -Structure* JSObject::createInheritorID() +Structure* JSObject::createInheritorID(JSGlobalData& globalData) { - m_inheritorID = createEmptyObjectStructure(this); + m_inheritorID = createEmptyObjectStructure(globalData, this); return m_inheritorID.get(); } @@ -743,12 +743,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName // Changing the accessor functions of an existing accessor property ASSERT(descriptor.isAccessorDescriptor()); if (!current.configurable()) { - if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { + if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { if (throwException) throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property.")); return false; } - if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { + if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { if (throwException) throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property.")); return false; diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 2b4db43..578b3cf 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -92,7 +92,7 @@ namespace JSC { bool setPrototypeWithCycleCheck(JSValue prototype); void setStructure(NonNullPassRefPtr<Structure>); - Structure* inheritorID(); + Structure* inheritorID(JSGlobalData&); virtual UString className() const; @@ -138,7 +138,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; virtual JSObject* toThisObject(ExecState*) const; virtual JSValue toStrictThisObject(ExecState*) const; @@ -250,9 +250,9 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; protected: - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const unsigned StructureFlags = 0; @@ -296,7 +296,7 @@ namespace JSC { bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; - Structure* createInheritorID(); + Structure* createInheritorID(JSGlobalData&); PropertyStorage m_propertyStorage; RefPtr<Structure> m_inheritorID; @@ -320,9 +320,9 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt friend class JSObject; public: - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -348,9 +348,9 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt return new (exec) JSFinalObject(structure); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: @@ -377,9 +377,9 @@ inline JSObject* constructEmptyObject(ExecState* exec, NonNullPassRefPtr<Structu return JSFinalObject::create(exec, structure); } -inline PassRefPtr<Structure> createEmptyObjectStructure(JSValue prototype) +inline PassRefPtr<Structure> createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype) { - return JSFinalObject::createStructure(prototype); + return JSFinalObject::createStructure(globalData, prototype); } inline JSObject* asObject(JSCell* cell) @@ -442,11 +442,11 @@ inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure) m_structure = structure.leakRef(); // ~JSObject balances this ref() } -inline Structure* JSObject::inheritorID() +inline Structure* JSObject::inheritorID(JSGlobalData& globalData) { if (m_inheritorID) return m_inheritorID.get(); - return createInheritorID(); + return createInheritorID(globalData); } inline bool Structure::isUsingInlineStorage() const @@ -814,8 +814,10 @@ 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); @@ -840,6 +842,20 @@ inline JSValue JSValue::toStrictThisObject(ExecState* exec) const return asObject(asCell())->toStrictThisObject(exec); } +ALWAYS_INLINE JSObject* Register::function() const +{ + if (!jsValue()) + return 0; + return asObject(jsValue()); +} + +ALWAYS_INLINE Register Register::withCallee(JSObject* callee) +{ + Register r; + r = JSValue(callee); + return r; +} + } // namespace JSC #endif // JSObject_h diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h index c5e3047..8380514 100644 --- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h @@ -34,9 +34,9 @@ class JSGlobalObject; class JSObjectWithGlobalObject : public JSNonFinalObject { public: - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSGlobalObject* globalObject() const; diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index 0d759cf..6f31f99 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -77,7 +77,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject return jsPropertyNameIterator; } - jsPropertyNameIterator->setCachedPrototypeChain(structureChain); + jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain); jsPropertyNameIterator->setCachedStructure(o->structure()); o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator); return jsPropertyNameIterator; @@ -86,7 +86,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 == base->structure()->prototypeChain(exec)) + if (m_cachedStructure == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec)) return identifier; if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec)))) @@ -97,6 +97,8 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) void JSPropertyNameIterator::markChildren(MarkStack& markStack) { markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues); + if (m_cachedPrototypeChain) + markStack.append(&m_cachedPrototypeChain); } #if !ASSERT_DISABLED diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h index d51cba8..499396c 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(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0); } virtual bool isPropertyNameIterator() const { return true; } @@ -73,7 +73,7 @@ namespace JSC { } Structure* cachedStructure() { return m_cachedStructure.get(); } - void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } + void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); } StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } private: @@ -84,7 +84,7 @@ namespace JSC { #endif RefPtr<Structure> m_cachedStructure; - RefPtr<StructureChain> m_cachedPrototypeChain; + WriteBarrier<StructureChain> m_cachedPrototypeChain; uint32_t m_numCacheableSlots; uint32_t m_jsStringsSize; OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings; @@ -106,6 +106,11 @@ namespace JSC { return m_enumerationCache.get(); } + ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const + { + return static_cast<JSPropertyNameIterator*>(jsValue().asCell()); + } + } // namespace JSC #endif // JSPropertyNameIterator_h diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 727ac28..3d4dc7c 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -28,13 +28,12 @@ #include "JSStaticScopeObject.h" namespace JSC { - ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject); void JSStaticScopeObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - markStack.deprecatedAppend(&d()->registerStore); + markStack.append(&m_registerStore); } JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const @@ -68,12 +67,6 @@ bool JSStaticScopeObject::isDynamicScope(bool&) const return false; } -JSStaticScopeObject::~JSStaticScopeObject() -{ - ASSERT(d()); - delete d(); -} - bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot) { return symbolTableGet(propertyName, slot); diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h index b3c0695..3e19bbc 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -31,25 +31,14 @@ namespace JSC{ class JSStaticScopeObject : public JSVariableObject { - protected: - using JSVariableObject::JSVariableObjectData; - struct JSStaticScopeObjectData : public JSVariableObjectData { - JSStaticScopeObjectData() - : JSVariableObjectData(&symbolTable, ®isterStore + 1) - { - } - SymbolTable symbolTable; - Register registerStore; - }; - public: JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes) - : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData()) + : JSVariableObject(exec->globalData().staticScopeStructure, &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1)) { - d()->registerStore = value; + m_registerStore.set(exec->globalData(), this, value); symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes)); } - virtual ~JSStaticScopeObject(); + virtual void markChildren(MarkStack&); bool isDynamicScope(bool& requiresDynamicChecks) const; virtual JSObject* toThisObject(ExecState*) const; @@ -58,13 +47,14 @@ namespace JSC{ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static PassRefPtr<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; private: - JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); } + SymbolTable m_symbolTable; + WriteBarrier<Unknown> m_registerStore; }; } diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index 848c431..d9c4d46 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -152,7 +152,7 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, if (substringLength == 1) { ASSERT(substringFiberCount == 1); UChar c = substringFibers[0].characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } if (substringFiberCount == 1) @@ -253,19 +253,19 @@ UString JSString::toString(ExecState* exec) const return value(exec); } -inline StringObject* StringObject::create(ExecState* exec, JSString* string) +inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { - return new (exec) StringObject(exec->globalData(), exec->lexicalGlobalObject()->stringObjectStructure(), string); + return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string); } -JSObject* JSString::toObject(ExecState* exec) const +JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const { - return StringObject::create(exec, const_cast<JSString*>(this)); + return StringObject::create(exec, globalObject, const_cast<JSString*>(this)); } JSObject* JSString::toThisObject(ExecState* exec) const { - return StringObject::create(exec, const_cast<JSString*>(this)); + return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this)); } bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 3672300..9113d4a 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -349,7 +349,7 @@ namespace JSC { JSValue replaceCharacter(ExecState*, UChar, const UString& replacement); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -402,7 +402,7 @@ namespace JSC { virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; virtual UString toString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; @@ -468,7 +468,7 @@ namespace JSC { inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) { - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1))); } @@ -478,7 +478,7 @@ namespace JSC { JSGlobalData* globalData = &exec->globalData(); ASSERT(offset < static_cast<unsigned>(s.length())); UChar c = s.characters()[offset]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1)))); } @@ -513,7 +513,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (size == 1) { UChar c = s.characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); @@ -521,7 +521,7 @@ namespace JSC { inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context) { - ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > 0xFF)); + ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > maxSingleCharacterString)); JSGlobalData* globalData = &exec->globalData(); return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context)); } @@ -548,7 +548,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (length == 1) { UChar c = s.characters()[offset]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner)); @@ -561,7 +561,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (size == 1) { UChar c = s.characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner)); diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h index fdcaf31..284d2b2 100644 --- a/Source/JavaScriptCore/runtime/JSTypeInfo.h +++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h @@ -46,7 +46,6 @@ namespace JSC { static const unsigned IsJSFinalObject = 1 << 8; class TypeInfo { - friend class JIT; public: TypeInfo(JSType type, unsigned flags = 0) : m_type(type) @@ -72,6 +71,16 @@ namespace JSC { unsigned flags() const { return m_flags; } unsigned isFinal() const { return m_flags2 && (IsJSFinalObject >> 8); } + static ptrdiff_t flagsOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_flags); + } + + static ptrdiff_t typeOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_type); + } + private: unsigned char m_type; unsigned char m_flags; diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index f4662db..d3ee89e 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -54,14 +54,14 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const return trunc(toNumber(exec)); } -JSObject* JSValue::toObjectSlowCase(ExecState* exec) const +JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const { ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, globalObject, asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, globalObject, asValue()); ASSERT(isUndefinedOrNull()); throwError(exec, createNotAnObjectError(exec, *this)); @@ -73,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); ASSERT(isUndefinedOrNull()); return exec->globalThisValue(); } @@ -84,9 +84,9 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const { ASSERT(!isCell()); if (isNumber()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isBoolean()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); ASSERT(isUndefinedOrNull()); throwError(exec, createNotAnObjectError(exec, *this)); diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index b2e7a51..098123e 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -37,6 +37,7 @@ namespace JSC { class Identifier; class JSCell; class JSGlobalData; + class JSGlobalObject; class JSImmediate; class JSObject; class JSString; @@ -52,11 +53,33 @@ namespace JSC { enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; + #if USE(JSVALUE32_64) typedef int64_t EncodedJSValue; #else typedef void* EncodedJSValue; #endif + + union EncodedValueDescriptor { + EncodedJSValue asEncodedJSValue; +#if USE(JSVALUE32_64) + double asDouble; +#elif USE(JSVALUE64) + JSCell* ptr; +#endif + +#if CPU(BIG_ENDIAN) + struct { + int32_t tag; + int32_t payload; + } asBits; +#else + struct { + int32_t payload; + int32_t tag; + } asBits; +#endif + }; double nonInlineNaN(); @@ -167,6 +190,7 @@ namespace JSC { UString toString(ExecState*) const; UString toPrimitiveString(ExecState*) const; JSObject* toObject(ExecState*) const; + JSObject* toObject(ExecState*, JSGlobalObject*) const; // Integer conversions. double toInteger(ExecState*) const; @@ -222,7 +246,7 @@ namespace JSC { JSValue(HashTableDeletedValueTag); inline const JSValue asValue() const { return *this; } - JSObject* toObjectSlowCase(ExecState*) const; + JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; JSObject* toThisObjectSlowCase(ExecState*) const; JSObject* synthesizePrototype(ExecState*) const; @@ -239,28 +263,14 @@ namespace JSC { enum { DeletedValueTag = 0xfffffff8 }; enum { LowestTag = DeletedValueTag }; - + uint32_t tag() const; int32_t payload() const; - union { - EncodedJSValue asEncodedJSValue; - double asDouble; -#if CPU(BIG_ENDIAN) - struct { - int32_t tag; - int32_t payload; - } asBits; -#else - struct { - int32_t payload; - int32_t tag; - } asBits; -#endif - } u; -#else // USE(JSVALUE32_64) + EncodedValueDescriptor u; +#elif USE(JSVALUE64) JSCell* m_ptr; -#endif // USE(JSVALUE32_64) +#endif }; #if USE(JSVALUE32_64) @@ -392,9 +402,6 @@ namespace JSC { { JSValue v; v.u.asEncodedJSValue = encodedJSValue; -#if ENABLE(JSC_ZOMBIES) - ASSERT(!v.isZombie()); -#endif return v; } diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index e94d277..891ada8 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -44,7 +44,7 @@ namespace JSC { friend class JIT; public: - SymbolTable& symbolTable() const { return *d->symbolTable; } + SymbolTable& symbolTable() const { return *m_symbolTable; } virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; @@ -54,39 +54,24 @@ namespace JSC { virtual bool isVariableObject() const; virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0; - WriteBarrier<Unknown>& registerAt(int index) const { return d->registers[index]; } + WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; } - static PassRefPtr<Structure> createStructure(JSValue prototype) + WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; } + + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags; - // Subclasses of JSVariableObject can subclass this struct to add data - // without increasing their own size (since there's a hard limit on the - // size of a JSCell). - struct JSVariableObjectData { - JSVariableObjectData(SymbolTable* symbolTable, Register* registers) - : symbolTable(symbolTable) - , registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) - { - ASSERT(symbolTable); - } - - SymbolTable* symbolTable; // Maps name -> offset from "r" in register file. - WriteBarrier<Unknown>* registers; // "r" in the register file. - OwnArrayPtr<WriteBarrier<Unknown> > registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. - - private: - JSVariableObjectData(const JSVariableObjectData&); - JSVariableObjectData& operator=(const JSVariableObjectData&); - }; - - JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data) + + JSVariableObject(NonNullPassRefPtr<Structure> structure, SymbolTable* symbolTable, Register* registers) : JSNonFinalObject(structure) - , d(data) // Subclass owns this pointer. + , m_symbolTable(symbolTable) + , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) { + ASSERT(m_symbolTable); COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier); } @@ -99,7 +84,9 @@ namespace JSC { bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue); bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes); - JSVariableObjectData* d; + SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file. + WriteBarrier<Unknown>* m_registers; // "r" in the register file. + OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. }; inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) @@ -161,9 +148,9 @@ namespace JSC { inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray) { - ASSERT(registerArray != d->registerArray); - d->registerArray = registerArray; - d->registers = registers; + ASSERT(registerArray != m_registerArray); + m_registerArray = registerArray; + m_registers = registers; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h index 6d586df..63833e9 100644 --- a/Source/JavaScriptCore/runtime/JSWrapperObject.h +++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h @@ -30,19 +30,19 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSNonFinalObject { protected: - explicit JSWrapperObject(JSGlobalData&, NonNullPassRefPtr<Structure>); + explicit JSWrapperObject(NonNullPassRefPtr<Structure>); public: - JSValue internalValue() const { return m_internalValue.get(); } + JSValue internalValue() const; void setInternalValue(JSGlobalData&, JSValue); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount; + static const unsigned StructureFlags = OverridesMarkChildren | JSNonFinalObject::StructureFlags; private: virtual void markChildren(MarkStack&); @@ -50,10 +50,14 @@ namespace JSC { WriteBarrier<Unknown> m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) + inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure) : JSNonFinalObject(structure) { - putAnonymousValue(globalData, 0, jsNull()); + } + + inline JSValue JSWrapperObject::internalValue() const + { + return m_internalValue.get(); } inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value) @@ -61,7 +65,6 @@ namespace JSC { ASSERT(value); ASSERT(!value.isObject()); m_internalValue.set(globalData, this, value); - putAnonymousValue(globalData, 0, value); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSZombie.cpp b/Source/JavaScriptCore/runtime/JSZombie.cpp index c0c5f11..23cf135 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.cpp +++ b/Source/JavaScriptCore/runtime/JSZombie.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSZombie.h" #include "ClassInfo.h" +#include "JSObject.h" #include "ScopeChain.h" #if ENABLE(JSC_ZOMBIES) @@ -38,7 +39,7 @@ Structure* JSZombie::leakedZombieStructure() { static Structure* structure = 0; if (!structure) { Structure::startIgnoringLeaks(); - structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &info).leakRef(); + structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &s_info).leakRef(); Structure::stopIgnoringLeaks(); } return structure; diff --git a/Source/JavaScriptCore/runtime/JSZombie.h b/Source/JavaScriptCore/runtime/JSZombie.h index 5fe6b6d..179ff53 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.h +++ b/Source/JavaScriptCore/runtime/JSZombie.h @@ -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(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, 0), AnonymousSlotCount, &s_info); } static const ClassInfo s_info; diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp index 4614a7c..3e205a1 100644 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp @@ -28,6 +28,11 @@ #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) @@ -74,12 +79,14 @@ #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) #include <signal.h> #ifndef SA_RESTART -#error MachineStackMarker requires SA_RESTART +#error MachineThreads requires SA_RESTART #endif #endif #endif +using namespace WTF; + namespace JSC { static inline void swapIfBackwards(void*& begin, void*& end) @@ -113,7 +120,7 @@ static void pthreadSignalHandlerSuspendResume(int signo) } #endif -class MachineStackMarker::Thread { +class MachineThreads::Thread { public: Thread(pthread_t pthread, const PlatformThread& platThread, void* base) : posixThread(pthread) @@ -142,20 +149,20 @@ public: #endif -MachineStackMarker::MachineStackMarker(Heap* heap) +MachineThreads::MachineThreads(Heap* heap) : m_heap(heap) #if ENABLE(JSC_MULTIPLE_THREADS) , m_registeredThreads(0) - , m_currentThreadRegistrar(0) + , m_threadSpecific(0) #endif { } -MachineStackMarker::~MachineStackMarker() +MachineThreads::~MachineThreads() { #if ENABLE(JSC_MULTIPLE_THREADS) - if (m_currentThreadRegistrar) { - int error = pthread_key_delete(m_currentThreadRegistrar); + if (m_threadSpecific) { + int error = pthread_key_delete(m_threadSpecific); ASSERT_UNUSED(error, !error); } @@ -181,24 +188,24 @@ static inline PlatformThread getCurrentPlatformThread() #endif } -void MachineStackMarker::makeUsableFromMultipleThreads() +void MachineThreads::makeUsableFromMultipleThreads() { - if (m_currentThreadRegistrar) + if (m_threadSpecific) return; - int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); + int error = pthread_key_create(&m_threadSpecific, removeThread); if (error) CRASH(); } -void MachineStackMarker::registerThread() +void MachineThreads::addCurrentThread() { ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) + if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) return; - pthread_setspecific(m_currentThreadRegistrar, this); + pthread_setspecific(m_threadSpecific, this); Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin()); MutexLocker lock(m_registeredThreadsMutex); @@ -207,13 +214,13 @@ void MachineStackMarker::registerThread() m_registeredThreads = thread; } -void MachineStackMarker::unregisterThread(void* p) +void MachineThreads::removeThread(void* p) { if (p) - static_cast<MachineStackMarker*>(p)->unregisterThread(); + static_cast<MachineThreads*>(p)->removeCurrentThread(); } -void MachineStackMarker::unregisterThread() +void MachineThreads::removeCurrentThread() { pthread_t currentPosixThread = pthread_self(); @@ -240,21 +247,13 @@ void MachineStackMarker::unregisterThread() #endif -void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(ConservativeSet& conservativeSet) -{ - void* begin = m_heap->globalData()->stack().current(); - void* end = m_heap->globalData()->stack().origin(); - swapIfBackwards(begin, end); - conservativeSet.add(begin, end); -} - #if COMPILER(GCC) #define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) #else #define REGISTER_BUFFER_ALIGNMENT #endif -void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conservativeSet) +void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, void* stackCurrent) { // setjmp forces volatile registers onto the stack jmp_buf registers REGISTER_BUFFER_ALIGNMENT; @@ -267,7 +266,15 @@ void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conser #pragma warning(pop) #endif - markCurrentThreadConservativelyInternal(conservativeSet); + 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) @@ -431,20 +438,19 @@ static void freePlatformThreadRegisters(PlatformThreadRegisters& regs) #endif } -void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conservativeSet, Thread* thread) +void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread) { suspendThread(thread->platformThread); PlatformThreadRegisters regs; size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); - // mark the thread's registers - conservativeSet.add(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + 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); - conservativeSet.add(stackPointer, stackBase); + conservativeRoots.add(stackPointer, stackBase); resumeThread(thread->platformThread); @@ -453,27 +459,27 @@ void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conserva #endif -void MachineStackMarker::markMachineStackConservatively(ConservativeSet& conservativeSet) +void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent) { - markCurrentThreadConservatively(conservativeSet); + gatherFromCurrentThread(conservativeRoots, stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) - if (m_currentThreadRegistrar) { + if (m_threadSpecific) { MutexLocker lock(m_registeredThreadsMutex); #ifndef NDEBUG - // Forbid malloc during the mark phase. Marking a thread suspends it, so - // a malloc inside markChildren() would risk a deadlock with a thread that had been - // suspended while holding the malloc lock. + // 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())) - markOtherThreadConservatively(conservativeSet, thread); + gatherFromOtherThread(conservativeRoots, thread); } #ifndef NDEBUG fastMallocAllow(); diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h index 8afdb46..c814ac5 100644 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.h +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.h @@ -19,8 +19,8 @@ * */ -#ifndef MachineStackMarker_h -#define MachineStackMarker_h +#ifndef MachineThreads_h +#define MachineThreads_h #include <wtf/Noncopyable.h> #include <wtf/ThreadingPrimitives.h> @@ -32,32 +32,31 @@ namespace JSC { class Heap; - class ConservativeSet; + class ConservativeRoots; - class MachineStackMarker { - WTF_MAKE_NONCOPYABLE(MachineStackMarker); + class MachineThreads { + WTF_MAKE_NONCOPYABLE(MachineThreads); public: - MachineStackMarker(Heap*); - ~MachineStackMarker(); + MachineThreads(Heap*); + ~MachineThreads(); - void markMachineStackConservatively(ConservativeSet&); + void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) void makeUsableFromMultipleThreads(); - void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. + void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads. #endif private: - void markCurrentThreadConservatively(ConservativeSet&); - void markCurrentThreadConservativelyInternal(ConservativeSet&); + void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) class Thread; - static void unregisterThread(void*); + static void removeThread(void*); + void removeCurrentThread(); - void unregisterThread(); - void markOtherThreadConservatively(ConservativeSet&, Thread*); + void gatherFromOtherThread(ConservativeRoots&, Thread*); #endif Heap* m_heap; @@ -65,10 +64,10 @@ namespace JSC { #if ENABLE(JSC_MULTIPLE_THREADS) Mutex m_registeredThreadsMutex; Thread* m_registeredThreads; - pthread_key_t m_currentThreadRegistrar; + pthread_key_t m_threadSpecific; #endif }; } // namespace JSC -#endif // MachineStackMarker_h +#endif // MachineThreads_h diff --git a/Source/JavaScriptCore/runtime/MarkStack.cpp b/Source/JavaScriptCore/runtime/MarkStack.cpp index a350c35..e9d1b13 100644 --- a/Source/JavaScriptCore/runtime/MarkStack.cpp +++ b/Source/JavaScriptCore/runtime/MarkStack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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 @@ -26,6 +26,14 @@ #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; @@ -37,4 +45,83 @@ void MarkStack::compact() 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 index 0b7941e..7131917 100644 --- a/Source/JavaScriptCore/runtime/MarkStack.h +++ b/Source/JavaScriptCore/runtime/MarkStack.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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 @@ -27,6 +27,7 @@ #define MarkStack_h #include "JSValue.h" +#include "Register.h" #include "WriteBarrier.h" #include <wtf/Vector.h> #include <wtf/Noncopyable.h> @@ -34,6 +35,7 @@ namespace JSC { + class ConservativeRoots; class JSGlobalData; class Register; @@ -50,7 +52,13 @@ namespace JSC { #endif { } - + + ~MarkStack() + { + ASSERT(m_markSets.isEmpty()); + ASSERT(m_values.isEmpty()); + } + void deprecatedAppend(JSValue*); void deprecatedAppend(JSCell**); void deprecatedAppend(Register*); @@ -70,17 +78,18 @@ namespace JSC { if (count) m_markSets.append(MarkSet(values, values + count, properties)); } + + void append(ConservativeRoots&); - inline void drain(); + void drain(); void compact(); - ~MarkStack() - { - ASSERT(m_markSets.isEmpty()); - ASSERT(m_values.isEmpty()); - } - 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*); @@ -196,7 +205,105 @@ namespace JSC { 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/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp index 48dda4c..cae701f 100644 --- a/Source/JavaScriptCore/runtime/MarkedBlock.cpp +++ b/Source/JavaScriptCore/runtime/MarkedBlock.cpp @@ -27,6 +27,8 @@ #include "MarkedBlock.h" #include "JSCell.h" +#include "JSObject.h" +#include "JSZombie.h" #include "ScopeChain.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.h b/Source/JavaScriptCore/runtime/MarkedBlock.h index e80fe82..0e2b59c 100644 --- a/Source/JavaScriptCore/runtime/MarkedBlock.h +++ b/Source/JavaScriptCore/runtime/MarkedBlock.h @@ -24,6 +24,7 @@ #include <wtf/Bitmap.h> #include <wtf/PageAllocationAligned.h> +#include <wtf/StdLibExtras.h> namespace JSC { @@ -35,15 +36,6 @@ namespace JSC { static const size_t KB = 1024; - // Efficient implementation that takes advantage of powers of two. - template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x) - { - COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two); - - size_t remainderMask = divisor - 1; - return (x + remainderMask) & ~remainderMask; - } - class MarkedBlock { public: static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types. @@ -109,7 +101,7 @@ namespace JSC { inline size_t MarkedBlock::firstAtom() { - return roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; + return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; } inline MarkedBlock::Atom* MarkedBlock::atoms() diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp index 15ab514..d9a1e42 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp +++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp @@ -24,6 +24,7 @@ #include "JSCell.h" #include "JSGlobalData.h" #include "JSLock.h" +#include "JSObject.h" #include "ScopeChain.h" namespace JSC { @@ -35,7 +36,10 @@ MarkedSpace::MarkedSpace(JSGlobalData* globalData) , m_highWaterMark(0) , m_globalData(globalData) { - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) + 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; } @@ -148,7 +152,10 @@ void MarkedSpace::reset() { m_waterMark = 0; - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) + 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(); diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h index 2e88887..29a8cd0 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.h +++ b/Source/JavaScriptCore/runtime/MarkedSpace.h @@ -32,8 +32,7 @@ #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) -#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::maxCellSize, class_fills_cell) +#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) < MarkedSpace::maxCellSize, class_fits_in_cell) namespace JSC { @@ -48,7 +47,7 @@ namespace JSC { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: // Currently public for use in assertions. - static const size_t maxCellSize = 64; + static const size_t maxCellSize = 1024; static Heap* heap(JSCell*); @@ -81,10 +80,15 @@ namespace JSC { template<typename Functor> void forEach(Functor&); private: - // [ 8, 16... 64 ] + // [ 8, 16... 128 ) static const size_t preciseStep = MarkedBlock::atomSize; - static const size_t preciseCutoff = maxCellSize; - static const size_t preciseCount = preciseCutoff / preciseStep; + 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; @@ -106,6 +110,7 @@ namespace JSC { void clearMarks(MarkedBlock*); SizeClass m_preciseSizeClasses[preciseCount]; + SizeClass m_impreciseSizeClasses[impreciseCount]; HashSet<MarkedBlock*> m_blocks; size_t m_waterMark; size_t m_highWaterMark; diff --git a/Source/JavaScriptCore/runtime/MathObject.h b/Source/JavaScriptCore/runtime/MathObject.h index 86e7951..26eaae0 100644 --- a/Source/JavaScriptCore/runtime/MathObject.h +++ b/Source/JavaScriptCore/runtime/MathObject.h @@ -34,9 +34,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp index 7949dd9..d8fda69 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -41,7 +41,7 @@ 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(prototype); + m_errorStructure = ErrorInstance::createStructure(exec->globalData(), prototype); } static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h index e4978cc..23f798e 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h @@ -35,9 +35,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } Structure* errorStructure() { return m_errorStructure.get(); } diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp index 3e4d6c7..aee143a 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp @@ -104,7 +104,7 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&) // ECMA 15.7.1 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec) { - NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); + NumberObject* object = new (exec) NumberObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure()); double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0; object->setInternalValue(exec->globalData(), jsNumber(n)); return JSValue::encode(object); diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h index aaf7c32..ab4507e 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.h +++ b/Source/JavaScriptCore/runtime/NumberConstructor.h @@ -37,9 +37,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp index 4408673..74b5e98 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& globalData, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(globalData, structure) +NumberObject::NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); } @@ -42,9 +42,9 @@ JSValue NumberObject::getJSNumber() return internalValue(); } -NumberObject* constructNumber(ExecState* exec, JSValue number) +NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number) { - NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); + NumberObject* object = new (exec) NumberObject(exec->globalData(), globalObject->numberObjectStructure()); object->setInternalValue(exec->globalData(), number); return object; } diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h index 8a80382..90d0b26 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.h +++ b/Source/JavaScriptCore/runtime/NumberObject.h @@ -31,19 +31,16 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - protected: - static const unsigned StructureFlags = JSWrapperObject::StructureFlags; - private: virtual JSValue getJSNumber(); }; - NumberObject* constructNumber(ExecState*, JSValue); + NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 5080ef8..c642a5b 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -95,18 +95,18 @@ bool ObjectConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifi } // ECMA 15.2.2 -static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) +static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { JSValue arg = args.at(0); if (arg.isUndefinedOrNull()) - return constructEmptyObject(exec); - return arg.toObject(exec); + return constructEmptyObject(exec, globalObject); + return arg.toObject(exec, globalObject); } static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructObject(exec, args)); + return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) @@ -118,7 +118,7 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructObject(exec, args)); + return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args)); } CallType ObjectConstructor::getCallData(CallData& callData) diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.h b/Source/JavaScriptCore/runtime/ObjectConstructor.h index 895f988..b7bfc1d 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.h +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.h @@ -36,9 +36,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h index 85a3818..c000dc8 100644 --- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -291,7 +291,7 @@ inline PropertyTable::~PropertyTable() { iterator end = this->end(); for (iterator iter = begin(); iter != end; ++iter) - iter->key->ref(); + iter->key->deref(); fastFree(m_index); } diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp index 351ecc3..8efb406 100644 --- a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "PropertyNameArray.h" +#include "JSObject.h" #include "ScopeChain.h" #include "Structure.h" #include "StructureChain.h" diff --git a/Source/JavaScriptCore/runtime/PutPropertySlot.h b/Source/JavaScriptCore/runtime/PutPropertySlot.h index 4c9e0e6..69d1f8b 100644 --- a/Source/JavaScriptCore/runtime/PutPropertySlot.h +++ b/Source/JavaScriptCore/runtime/PutPropertySlot.h @@ -45,14 +45,14 @@ namespace JSC { { } - void setExistingProperty(DeprecatedPtr<JSObject> base, size_t offset) + void setExistingProperty(JSObject* base, size_t offset) { m_type = ExistingProperty; m_base = base; m_offset = offset; } - void setNewProperty(DeprecatedPtr<JSObject> base, size_t offset) + void setNewProperty(JSObject* base, size_t offset) { m_type = NewProperty; m_base = base; @@ -60,7 +60,7 @@ namespace JSC { } Type type() const { return m_type; } - JSObject* base() const { return m_base.get(); } + JSObject* base() const { return m_base; } bool isStrictMode() const { return m_isStrictMode; } bool isCacheable() const { return m_type != Uncachable; } @@ -68,9 +68,10 @@ namespace JSC { ASSERT(isCacheable()); return m_offset; } + private: Type m_type; - DeprecatedPtr<JSObject> m_base; + JSObject* m_base; size_t m_offset; bool m_isStrictMode; }; diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 95ce5e9..25cb2d5 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -34,6 +34,38 @@ namespace JSC { +RegExpFlags regExpFlags(const UString& string) +{ + RegExpFlags flags = NoFlags; + + for (unsigned i = 0; i < string.length(); ++i) { + switch (string.characters()[i]) { + case 'g': + if (flags & FlagGlobal) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagGlobal); + break; + + case 'i': + if (flags & FlagIgnoreCase) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase); + break; + + case 'm': + if (flags & FlagMultiline) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagMultiline); + break; + + default: + return InvalidFlags; + } + } + + return flags; +} + struct RegExpRepresentation { #if ENABLE(YARR_JIT) Yarr::YarrCodeBlock m_regExpJITCode; @@ -41,9 +73,9 @@ struct RegExpRepresentation { OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; }; -inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, const UString& flags) +inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags) : m_patternString(patternString) - , m_flagBits(0) + , m_flags(flags) , m_constructionError(0) , m_numSubpatterns(0) #if ENABLE(REGEXP_TRACING) @@ -52,17 +84,6 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, co #endif , m_representation(adoptPtr(new RegExpRepresentation)) { - // NOTE: The global flag is handled on a case-by-case basis by functions like - // String::match and RegExpObject::match. - if (!flags.isNull()) { - if (flags.find('g') != notFound) - m_flagBits |= Global; - if (flags.find('i') != notFound) - m_flagBits |= IgnoreCase; - if (flags.find('m') != notFound) - m_flagBits |= Multiline; - } - m_state = compile(globalData); } @@ -70,7 +91,7 @@ RegExp::~RegExp() { } -PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, const UString& flags) +PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags) { RefPtr<RegExp> res = adoptRef(new RegExp(globalData, patternString, flags)); #if ENABLE(REGEXP_TRACING) diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h index d99befb..000c33a 100644 --- a/Source/JavaScriptCore/runtime/RegExp.h +++ b/Source/JavaScriptCore/runtime/RegExp.h @@ -24,6 +24,7 @@ #include "UString.h" #include "ExecutableAllocator.h" +#include "RegExpKey.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> @@ -32,18 +33,20 @@ namespace JSC { struct RegExpRepresentation; class JSGlobalData; + RegExpFlags regExpFlags(const UString&); + class RegExp : public RefCounted<RegExp> { public: - static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags); + static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, RegExpFlags); ~RegExp(); - bool global() const { return m_flagBits & Global; } - bool ignoreCase() const { return m_flagBits & IgnoreCase; } - bool multiline() const { return m_flagBits & Multiline; } + bool global() const { return m_flags & FlagGlobal; } + bool ignoreCase() const { return m_flags & FlagIgnoreCase; } + bool multiline() const { return m_flags & FlagMultiline; } const UString& pattern() const { return m_patternString; } - bool isValid() const { return !m_constructionError; } + bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; } const char* errorMessage() const { return m_constructionError; } int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0); @@ -54,7 +57,7 @@ namespace JSC { #endif private: - RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags); + RegExp(JSGlobalData* globalData, const UString& pattern, RegExpFlags); enum RegExpState { ParseError, @@ -68,9 +71,8 @@ namespace JSC { void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult); #endif - enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 }; UString m_patternString; - int m_flagBits; + RegExpFlags m_flags; const char* m_constructionError; unsigned m_numSubpatterns; #if ENABLE(REGEXP_TRACING) diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp index d101758..c96b047 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.cpp +++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp @@ -31,7 +31,7 @@ namespace JSC { -PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags) +PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags flags) { if (patternString.length() < maxCacheablePatternLength) { pair<RegExpCacheMap::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0); @@ -43,7 +43,7 @@ PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, con return create(patternString, flags, m_cacheMap.end()); } -PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator) +PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, RegExpFlags flags, RegExpCacheMap::iterator iterator) { RefPtr<RegExp> regExp = RegExp::create(m_globalData, patternString, flags); diff --git a/Source/JavaScriptCore/runtime/RegExpCache.h b/Source/JavaScriptCore/runtime/RegExpCache.h index b5b637f..b4a6ae5 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.h +++ b/Source/JavaScriptCore/runtime/RegExpCache.h @@ -41,8 +41,8 @@ class RegExpCache { typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap; public: - PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags); - PassRefPtr<RegExp> create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator); + PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, RegExpFlags); + PassRefPtr<RegExp> create(const UString& patternString, RegExpFlags, RegExpCacheMap::iterator); RegExpCache(JSGlobalData* globalData); private: diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index c06fdc4..19b4b36 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -291,9 +291,9 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu { asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); } - + // ECMA 15.10.4 -JSObject* constructRegExp(ExecState* exec, const ArgList& args) +JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { JSValue arg0 = args.at(0); JSValue arg1 = args.at(1); @@ -305,18 +305,28 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) } UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); - UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); + if (exec->hadException()) + return 0; + + RegExpFlags flags = NoFlags; + if (!arg1.isUndefined()) { + flags = regExpFlags(arg1.toString(exec)); + if (exec->hadException()) + return 0; + if (flags == InvalidFlags) + return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); + } RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) return throwError(exec, createSyntaxError(exec, regExp->errorMessage())); - return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); + return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp.release()); } static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructRegExp(exec, args)); + return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) @@ -329,7 +339,7 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructRegExp(exec, args)); + return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args)); } CallType RegExpConstructor::getCallData(CallData& callData) diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h index 8a8a54a..5e0b2b8 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.h +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h @@ -59,9 +59,9 @@ namespace JSC { public: RegExpConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, RegExpPrototype*); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -96,7 +96,7 @@ namespace JSC { RegExpConstructor* asRegExpConstructor(JSValue); - JSObject* constructRegExp(ExecState*, const ArgList&); + JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&); inline RegExpConstructor* asRegExpConstructor(JSValue value) { diff --git a/Source/JavaScriptCore/runtime/RegExpKey.h b/Source/JavaScriptCore/runtime/RegExpKey.h index cd1368d..b4847f9 100644 --- a/Source/JavaScriptCore/runtime/RegExpKey.h +++ b/Source/JavaScriptCore/runtime/RegExpKey.h @@ -25,63 +25,54 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "UString.h" -#include <wtf/text/StringHash.h> - #ifndef RegExpKey_h #define RegExpKey_h +#include "UString.h" +#include <wtf/text/StringHash.h> + namespace JSC { +enum RegExpFlags { + NoFlags = 0, + FlagGlobal = 1, + FlagIgnoreCase = 2, + FlagMultiline = 4, + InvalidFlags = 8, + DeletedValueFlags = -1 +}; + struct RegExpKey { - int flagsValue; + RegExpFlags flagsValue; RefPtr<StringImpl> pattern; RegExpKey() - : flagsValue(0) + : flagsValue(NoFlags) { } - RegExpKey(int flags) + RegExpKey(RegExpFlags flags) : flagsValue(flags) { } - RegExpKey(int flags, const UString& pattern) + RegExpKey(RegExpFlags flags, const UString& pattern) : flagsValue(flags) , pattern(pattern.impl()) { } - RegExpKey(int flags, const PassRefPtr<StringImpl> pattern) + RegExpKey(RegExpFlags flags, const PassRefPtr<StringImpl> pattern) : flagsValue(flags) , pattern(pattern) { } - RegExpKey(int flags, const RefPtr<StringImpl>& pattern) + RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern) : flagsValue(flags) , pattern(pattern) { } - - RegExpKey(const UString& flags, const UString& pattern) - : pattern(pattern.impl()) - { - flagsValue = getFlagsValue(flags); - } - - int getFlagsValue(const UString flags) - { - flagsValue = 0; - if (flags.find('g') != notFound) - flagsValue += 4; - if (flags.find('i') != notFound) - flagsValue += 2; - if (flags.find('m') != notFound) - flagsValue += 1; - return flagsValue; - } }; inline bool operator==(const RegExpKey& a, const RegExpKey& b) @@ -112,8 +103,8 @@ template<> struct DefaultHash<JSC::RegExpKey> { }; template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> { - static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; } - static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; } + static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; } + static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; } }; } // namespace WTF diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 5baf884..4b5028b 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -63,7 +63,7 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_ RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp) : JSObjectWithGlobalObject(globalObject, structure) - , d(adoptPtr(new RegExpObjectData(regExp, 0))) + , d(adoptPtr(new RegExpObjectData(regExp))) { ASSERT(inherits(&s_info)); } @@ -72,6 +72,13 @@ RegExpObject::~RegExpObject() { } +void RegExpObject::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + if (UNLIKELY(!d->lastIndex.get().isInt32())) + markStack.append(&d->lastIndex); +} + bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); @@ -104,7 +111,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&) { - return jsNumber(asRegExpObject(slotBase)->lastIndex()); + return asRegExpObject(slotBase)->getLastIndex(); } void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) @@ -114,7 +121,7 @@ void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec)); + asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value); } JSValue RegExpObject::test(ExecState* exec) @@ -133,12 +140,7 @@ JSValue RegExpObject::exec(ExecState* exec) bool RegExpObject::match(ExecState* exec) { RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - - UString input = !exec->argumentCount() ? regExpConstructor->input() : exec->argument(0).toString(exec); - if (input.isNull()) { - throwError(exec, createError(exec, makeUString("No input to ", toString(exec), "."))); - return false; - } + UString input = exec->argument(0).toString(exec); if (!regExp()->global()) { int position; @@ -147,20 +149,32 @@ bool RegExpObject::match(ExecState* exec) return position >= 0; } - if (d->lastIndex < 0 || d->lastIndex > input.length()) { - d->lastIndex = 0; - return false; + JSValue jsLastIndex = getLastIndex(); + unsigned lastIndex; + if (LIKELY(jsLastIndex.isUInt32())) { + lastIndex = jsLastIndex.asUInt32(); + if (lastIndex > input.length()) { + setLastIndex(0); + return false; + } + } else { + double doubleLastIndex = jsLastIndex.toInteger(exec); + if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { + setLastIndex(0); + return false; + } + lastIndex = static_cast<unsigned>(doubleLastIndex); } int position; int length = 0; - regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length); + regExpConstructor->performMatch(d->regExp.get(), input, lastIndex, position, length); if (position < 0) { - d->lastIndex = 0; + setLastIndex(0); return false; } - d->lastIndex = position + length; + setLastIndex(position + length); return true; } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index 1f89b84..fa2024d 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -28,14 +28,26 @@ namespace JSC { class RegExpObject : public JSObjectWithGlobalObject { public: + typedef JSObjectWithGlobalObject Base; + RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>); virtual ~RegExpObject(); void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; } RegExp* regExp() const { return d->regExp.get(); } - void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; } - double lastIndex() const { return d->lastIndex; } + void setLastIndex(size_t lastIndex) + { + d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + } + void setLastIndex(JSGlobalData& globalData, JSValue lastIndex) + { + d->lastIndex.set(globalData, this, lastIndex); + } + JSValue getLastIndex() const + { + return d->lastIndex.get(); + } JSValue test(ExecState*); JSValue exec(ExecState*); @@ -46,28 +58,30 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags; - + static const unsigned StructureFlags = OverridesMarkChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags; + private: + virtual void markChildren(MarkStack&); + bool match(ExecState*); struct RegExpObjectData { WTF_MAKE_FAST_ALLOCATED; public: - RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex) + RegExpObjectData(NonNullPassRefPtr<RegExp> regExp) : regExp(regExp) - , lastIndex(lastIndex) { + lastIndex.setWithoutWriteBarrier(jsNumber(0)); } RefPtr<RegExp> regExp; - double lastIndex; + WriteBarrier<Unknown> lastIndex; }; #if COMPILER(MSVC) friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*); diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 106006c..61747b1 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -48,11 +48,11 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*); // ECMA 15.10.5 RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) - : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", "")) + : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", NoFlags)) { - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum); } @@ -90,7 +90,17 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) regExp = asRegExpObject(arg0)->regExp(); } else { UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec); - UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + RegExpFlags flags = NoFlags; + if (!arg1.isUndefined()) { + flags = regExpFlags(arg1.toString(exec)); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (flags == InvalidFlags) + return throwVMError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); + } regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); } diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h index fbecd11..cb70a34 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.h +++ b/Source/JavaScriptCore/runtime/ScopeChain.h @@ -64,7 +64,7 @@ namespace JSC { void print(); #endif - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } virtual void markChildren(MarkStack&); private: static const unsigned StructureFlags = OverridesMarkChildren; @@ -100,7 +100,7 @@ namespace JSC { bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } private: - DeprecatedPtr<ScopeChainNode> m_node; + ScopeChainNode* m_node; }; inline ScopeChainIterator ScopeChainNode::begin() @@ -128,6 +128,17 @@ namespace JSC { { return scopeChain()->globalThis.get(); } + + ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const + { + return static_cast<ScopeChainNode*>(jsValue().asCell()); + } + + ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) + { + *this = JSValue(scopeChain); + return *this; + } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp index 9b193f5..ac67020 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.cpp +++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp @@ -33,8 +33,6 @@ namespace JSC { -static const unsigned numCharactersToStore = 0x100; - static inline bool isMarked(JSCell* string) { return string && Heap::isMarked(string); @@ -45,17 +43,22 @@ class SmallStringsStorage { public: SmallStringsStorage(); - StringImpl* rep(unsigned char character) { return m_reps[character].get(); } + StringImpl* rep(unsigned char character) + { + return m_reps[character].get(); + } private: - RefPtr<StringImpl> m_reps[numCharactersToStore]; + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + + RefPtr<StringImpl> m_reps[singleCharacterStringCount]; }; SmallStringsStorage::SmallStringsStorage() { UChar* characterBuffer = 0; - RefPtr<StringImpl> baseString = StringImpl::createUninitialized(numCharactersToStore, characterBuffer); - for (unsigned i = 0; i < numCharactersToStore; ++i) { + RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer); + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { characterBuffer[i] = i; m_reps[i] = StringImpl::create(baseString, i, 1); } @@ -63,7 +66,7 @@ SmallStringsStorage::SmallStringsStorage() SmallStrings::SmallStrings() { - COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); + COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); clear(); } @@ -71,7 +74,7 @@ SmallStrings::~SmallStrings() { } -void SmallStrings::markChildren(MarkStack& markStack) +void SmallStrings::markChildren(HeapRootMarker& heapRootMarker) { /* Our hypothesis is that small strings are very common. So, we cache them @@ -83,9 +86,9 @@ void SmallStrings::markChildren(MarkStack& markStack) so, it's probably reasonable to mark the rest. If not, we clear the cache. */ - bool isAnyStringMarked = isMarked(m_emptyString.get()); - for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i) - isAnyStringMarked = isMarked(m_singleCharacterStrings[i].get()); + bool isAnyStringMarked = isMarked(m_emptyString); + for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i) + isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); if (!isAnyStringMarked) { clear(); @@ -93,17 +96,17 @@ void SmallStrings::markChildren(MarkStack& markStack) } if (m_emptyString) - markStack.append(&m_emptyString); - for (unsigned i = 0; i < numCharactersToStore; ++i) { + heapRootMarker.mark(&m_emptyString); + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { if (m_singleCharacterStrings[i]) - markStack.append(&m_singleCharacterStrings[i]); + heapRootMarker.mark(&m_singleCharacterStrings[i]); } } void SmallStrings::clear() { m_emptyString = 0; - for (unsigned i = 0; i < numCharactersToStore; ++i) + for (unsigned i = 0; i < singleCharacterStringCount; ++i) m_singleCharacterStrings[i] = 0; } @@ -112,7 +115,7 @@ unsigned SmallStrings::count() const unsigned count = 0; if (m_emptyString) ++count; - for (unsigned i = 0; i < numCharactersToStore; ++i) { + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { if (m_singleCharacterStrings[i]) ++count; } diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h index cd9c325..b54d020 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.h +++ b/Source/JavaScriptCore/runtime/SmallStrings.h @@ -33,13 +33,16 @@ namespace JSC { + class HeapRootMarker; class JSGlobalData; class JSString; class MarkStack; class SmallStringsStorage; + static const unsigned maxSingleCharacterString = 0xFF; + class SmallStrings { - WTF_MAKE_NONCOPYABLE(SmallStrings); WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(SmallStrings); public: SmallStrings(); ~SmallStrings(); @@ -48,30 +51,33 @@ namespace JSC { { if (!m_emptyString) createEmptyString(globalData); - return m_emptyString.get(); + return m_emptyString; } + JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character) { if (!m_singleCharacterStrings[character]) createSingleCharacterString(globalData, character); - return m_singleCharacterStrings[character].get(); + return m_singleCharacterStrings[character]; } StringImpl* singleCharacterStringRep(unsigned char character); - void markChildren(MarkStack&); + void markChildren(HeapRootMarker&); void clear(); unsigned count() const; - JSCell** singleCharacterStrings() { return m_singleCharacterStrings[0].slot(); } + JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; } private: + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); - DeprecatedPtr<JSString> m_emptyString; - FixedArray<DeprecatedPtr<JSString>, 0x100> m_singleCharacterStrings; + JSString* m_emptyString; + JSString* m_singleCharacterStrings[singleCharacterStringCount]; OwnPtr<SmallStringsStorage> m_storage; }; diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp index 5398f31..ed088e4 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.cpp +++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp @@ -67,9 +67,10 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje // ECMA 15.5.2 static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* exec) { + JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); if (!exec->argumentCount()) - return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure())); - return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), exec->argument(0).toString(exec))); + return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure())); + return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec))); } ConstructType StringConstructor::getConstructData(ConstructData& constructData) diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index 5fe7544..47e5860 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -30,21 +30,21 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 }; StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsEmptyString(exec)); } StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string) - : JSWrapperObject(globalData, structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(globalData, string); } StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(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 99f9add..ae3376d 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -31,7 +31,7 @@ namespace JSC { StringObject(ExecState*, NonNullPassRefPtr<Structure>); StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&); - static StringObject* create(ExecState*, JSString*); + static StringObject* create(ExecState*, JSGlobalObject*, JSString*); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); @@ -45,15 +45,15 @@ namespace JSC { JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; StringObject(JSGlobalData&, NonNullPassRefPtr<Structure>, JSString*); - }; + }; StringObject* asStringObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index 0a44ed3..e4c7061 100644 --- a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -33,7 +33,7 @@ namespace JSC { static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string) { return new (exec) StringObjectThatMasqueradesAsUndefined(exec, - createStructure(exec->lexicalGlobalObject()->stringPrototype()), string); + createStructure(exec->globalData(), exec->lexicalGlobalObject()->stringPrototype()), string); } private: @@ -42,9 +42,9 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index aa37122..a6bf4e6 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -604,9 +604,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) JSValue a0 = exec->argument(0); - UString u = s; RefPtr<RegExp> reg; - RegExpObject* imp = 0; if (a0.inherits(&RegExpObject::s_info)) reg = asRegExpObject(a0)->regExp(); else { @@ -615,12 +613,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength = 0; - regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) @@ -630,15 +628,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) // return array of matches MarkedArgumentBuffer list; - int lastIndex = 0; + unsigned lastIndex = 0; while (pos >= 0) { - list.append(jsSubstring(exec, u, pos, matchLength)); + list.append(jsSubstring(exec, s, pos, matchLength)); lastIndex = pos; pos += matchLength == 0 ? 1 : matchLength; - regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, pos, pos, matchLength); } - if (imp) - imp->setLastIndex(lastIndex); if (list.isEmpty()) { // if there are no matches at all, it's important to return // Null instead of an empty array, because this matches @@ -658,7 +654,6 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) JSValue a0 = exec->argument(0); - UString u = s; RefPtr<RegExp> reg; if (a0.inherits(&RegExpObject::s_info)) reg = asRegExpObject(a0)->regExp(); @@ -668,12 +663,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength = 0; - regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength); return JSValue::encode(jsNumber(pos)); } diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h index feea2e2..57def22 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.h +++ b/Source/JavaScriptCore/runtime/StringPrototype.h @@ -34,12 +34,18 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const ClassInfo s_info; + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags; + + COMPILE_ASSERT(!StringObject::AnonymousSlotCount, StringPrototype_stomps_on_your_anonymous_slot); + static const unsigned AnonymousSlotCount = 1; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index bf27334..c9f900a 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -32,7 +32,6 @@ #include "PropertyMapHashTable.h" #include "PropertyNameArray.h" #include "Protect.h" -#include "StructureChain.h" #include "StructureTransitionTable.h" #include "JSTypeInfo.h" #include "UString.h" @@ -46,6 +45,7 @@ namespace JSC { class MarkStack; class PropertyNameArray; class PropertyNameArrayData; + class StructureChain; struct ClassInfo; @@ -56,13 +56,18 @@ namespace JSC { class Structure : public RefCounted<Structure> { public: - friend class JIT; friend class StructureTransitionTable; - static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) + static PassRefPtr<Structure> create(JSGlobalData&, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) { return adoptRef(new Structure(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(); @@ -102,6 +107,7 @@ namespace JSC { DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; } JSValue prototypeForLookup(ExecState*) const; StructureChain* prototypeChain(ExecState*) const; + DeprecatedPtr<StructureChain>* cachedPrototypeChainSlot() { return &m_cachedPrototypeChain; } Structure* previousID() const { return m_previous.get(); } @@ -140,6 +146,21 @@ namespace JSC { static void initializeThreading(); + static ptrdiff_t prototypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_prototype); + } + + static ptrdiff_t typeInfoFlagsOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset(); + } + + static ptrdiff_t typeInfoTypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset(); + } + private: Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*); Structure(const Structure*); @@ -190,7 +211,7 @@ namespace JSC { TypeInfo m_typeInfo; DeprecatedPtr<Unknown> m_prototype; - mutable RefPtr<StructureChain> m_cachedPrototypeChain; + mutable DeprecatedPtr<StructureChain> m_cachedPrototypeChain; RefPtr<Structure> m_previous; RefPtr<StringImpl> m_nameInPrevious; diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp index e4523c3..4fa4a4b 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.cpp +++ b/Source/JavaScriptCore/runtime/StructureChain.cpp @@ -32,7 +32,8 @@ namespace JSC { -StructureChain::StructureChain(Structure* head) +StructureChain::StructureChain(NonNullPassRefPtr<Structure> structure, Structure* head) + : JSCell(structure.releaseRef()) { size_t size = 0; for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h index 816b66d..88592dc 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.h +++ b/Source/JavaScriptCore/runtime/StructureChain.h @@ -26,6 +26,8 @@ #ifndef StructureChain_h #define StructureChain_h +#include "JSCell.h" + #include <wtf/OwnArrayPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -35,15 +37,16 @@ namespace JSC { class Structure; - class StructureChain : public RefCounted<StructureChain> { + class StructureChain : public JSCell { friend class JIT; public: - static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } + static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData.structureChainStructure, head); } RefPtr<Structure>* head() { return m_vector.get(); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), 0, 0); } private: - StructureChain(Structure* head); + StructureChain(NonNullPassRefPtr<Structure>, Structure* head); OwnArrayPtr<RefPtr<Structure> > m_vector; }; diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp index 04d904d..d3867d4 100644 --- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -101,7 +101,7 @@ static inline unsigned getCPUTime() // use a relative time from first call in order to avoid an overflow static double firstTime = currentTime(); - return (currentTime() - firstTime) * 1000; + return static_cast<unsigned> ((currentTime() - firstTime) * 1000); #endif } diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h index 44840ad..af018a8 100644 --- a/Source/JavaScriptCore/runtime/WriteBarrier.h +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -35,6 +35,7 @@ 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) { } @@ -54,6 +55,7 @@ protected: JSCell* m_cell; }; +// FIXME: Remove all uses of this class. template <> class DeprecatedPtr<Unknown> { public: DeprecatedPtr() { } @@ -73,17 +75,23 @@ private: JSValue m_value; }; -template <typename T> struct WriteBarrierCheck { +template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) +{ + return lhs.get() == rhs.get(); +} + +template <typename T> struct JSValueChecker { static const bool IsJSValue = false; }; -template <> struct WriteBarrierCheck<JSValue> { +template <> struct JSValueChecker<JSValue> { static const bool IsJSValue = true; }; +// We have a separate base class with no constructors for use in Unions. template <typename T> class WriteBarrierBase { public: - COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); + 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); } T* get() const { return reinterpret_cast<T*>(m_cell); } @@ -100,20 +108,10 @@ public: void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } -protected: +private: JSCell* m_cell; }; -template <typename T> class WriteBarrier : public WriteBarrierBase<T> { -public: - WriteBarrier() { this->m_cell = 0; } - WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) - { - this->set(globalData, owner, value); - } - -}; - template <> class WriteBarrierBase<Unknown> { public: void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); } @@ -138,29 +136,41 @@ public: operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } bool operator!() const { return !get(); } -protected: +private: EncodedJSValue m_value; }; +template <typename T> class WriteBarrier : public WriteBarrierBase<T> { +public: + WriteBarrier() + { + this->setWithoutWriteBarrier(0); + } + + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) + { + this->set(globalData, owner, value); + } +}; + template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> { public: - WriteBarrier() { m_value = JSValue::encode(JSValue()); } + WriteBarrier() + { + this->setWithoutWriteBarrier(JSValue()); + } + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value) { this->set(globalData, owner, value); } }; -template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) -{ - return lhs.get() == rhs.get(); -} - template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs) { return lhs.get() == rhs.get(); } -} +} // namespace JSC #endif // WriteBarrier_h |