diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime')
24 files changed, 128 insertions, 271 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index e5e503ee1..fdf202192 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -343,6 +343,18 @@ void Arguments::tearOff(CallFrame* callFrame) m_registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[m_numArguments]); m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); + // If we have a captured argument that logically aliases activation storage, + // but we optimize away the activation, the argument needs to tear off into + // our storage. The simplest way to do this is to revert it to Normal status. + if (m_slowArguments && !m_activation) { + for (size_t i = 0; i < m_numArguments; ++i) { + if (m_slowArguments[i].status != SlowArgument::Captured) + continue; + m_slowArguments[i].status = SlowArgument::Normal; + m_slowArguments[i].index = CallFrame::argumentOffset(i); + } + } + if (!callFrame->isInlineCallFrame()) { for (size_t i = 0; i < m_numArguments; ++i) trySetArgument(callFrame->globalData(), i, callFrame->argumentAfterCapture(i)); @@ -362,20 +374,8 @@ void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) if (!m_numArguments) return; - tearOff(exec); - - SharedSymbolTable* symbolTable = activation->symbolTable(); - const SlowArgument* slowArguments = symbolTable->slowArguments(); - if (!slowArguments) - return; - - ASSERT(symbolTable->captureMode() == SharedSymbolTable::AllOfTheThings); m_activation.set(exec->globalData(), this, activation); - - allocateSlowArguments(); - size_t count = min<unsigned>(m_numArguments, symbolTable->parameterCount()); - for (size_t i = 0; i < count; ++i) - m_slowArguments[i] = slowArguments[i]; + tearOff(exec); } void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index c9d0d503d..40063bead 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -161,6 +161,10 @@ namespace JSC { if (m_slowArguments) return; m_slowArguments = adoptArrayPtr(new SlowArgument[m_numArguments]); + for (size_t i = 0; i < m_numArguments; ++i) { + ASSERT(m_slowArguments[i].status == SlowArgument::Normal); + m_slowArguments[i].index = CallFrame::argumentOffset(i); + } } inline bool Arguments::tryDeleteArgument(size_t argument) @@ -210,14 +214,14 @@ namespace JSC { inline WriteBarrierBase<Unknown>& Arguments::argument(size_t argument) { ASSERT(isArgument(argument)); - if (!m_slowArguments || m_slowArguments[argument].status == SlowArgument::Normal) + if (!m_slowArguments) return m_registers[CallFrame::argumentOffset(argument)]; - ASSERT(m_slowArguments[argument].status == SlowArgument::Captured); - if (!m_activation) - return m_registers[m_slowArguments[argument].indexIfCaptured]; + int index = m_slowArguments[argument].index; + if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured) + return m_registers[index]; - return m_activation->registerAt(m_slowArguments[argument].indexIfCaptured); + return m_activation->registerAt(index); } inline void Arguments::finishCreation(CallFrame* callFrame) @@ -234,6 +238,15 @@ namespace JSC { m_overrodeCaller = false; m_isStrictMode = callFrame->codeBlock()->isStrictMode(); + SharedSymbolTable* symbolTable = callFrame->codeBlock()->symbolTable(); + const SlowArgument* slowArguments = symbolTable->slowArguments(); + if (slowArguments) { + allocateSlowArguments(); + size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount()); + for (size_t i = 0; i < count; ++i) + m_slowArguments[i] = slowArguments[i]; + } + // The bytecode generator omits op_tear_off_activation in cases of no // declared parameters, so we need to tear off immediately. if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) @@ -254,6 +267,8 @@ namespace JSC { m_overrodeCaller = false; m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); + ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable()->slowArguments()); + // The bytecode generator omits op_tear_off_activation in cases of no // declared parameters, so we need to tear off immediately. if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) diff --git a/Source/JavaScriptCore/runtime/ArrayConventions.h b/Source/JavaScriptCore/runtime/ArrayConventions.h index af98e15fa..3ea6b0471 100644 --- a/Source/JavaScriptCore/runtime/ArrayConventions.h +++ b/Source/JavaScriptCore/runtime/ArrayConventions.h @@ -26,8 +26,6 @@ namespace JSC { -#define CHECK_ARRAY_CONSISTENCY 0 - // Overview of JSArray // // Properties of JSArray objects may be stored in one of three locations: diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index c70e40d77..95cba0936 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -629,6 +629,15 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) return JSValue::encode(result); } +inline JSValue getOrHole(JSObject* obj, ExecState* exec, unsigned propertyName) +{ + PropertySlot slot(obj); + if (obj->getPropertySlot(exec, propertyName, slot)) + return slot.getValue(exec, propertyName); + + return JSValue(); +} + EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toObject(exec); @@ -653,17 +662,21 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) // "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) { - JSValue iObj = thisObj->get(exec, i); + JSValue iObj = getOrHole(thisObj, exec, i); if (exec->hadException()) return JSValue::encode(jsUndefined()); unsigned themin = i; JSValue minObj = iObj; for (unsigned j = i + 1; j < length; ++j) { - JSValue jObj = thisObj->get(exec, j); + JSValue jObj = getOrHole(thisObj, exec, j); if (exec->hadException()) return JSValue::encode(jsUndefined()); double compareResult; - if (jObj.isUndefined()) + if (!jObj) + compareResult = 1; + else if (!minObj) + compareResult = -1; + else if (jObj.isUndefined()) compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) else if (minObj.isUndefined()) compareResult = -1; @@ -682,12 +695,22 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) } // Swap themin and i if (themin > i) { - thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true); - if (exec->hadException()) + if (minObj) { + thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, i)) { + throwTypeError(exec, "Unable to delete property."); return JSValue::encode(jsUndefined()); - thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true); - if (exec->hadException()) + } + if (iObj) { + thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, themin)) { + throwTypeError(exec, "Unable to delete property."); return JSValue::encode(jsUndefined()); + } } } return JSValue::encode(thisObj); @@ -730,7 +753,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) return JSValue::encode(jsUndefined()); resObj->initializeIndex(globalData, k, v); } - resObj->completeInitialization(deleteCount); unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0); if (additionalArgs < deleteCount) { diff --git a/Source/JavaScriptCore/runtime/ArrayStorage.h b/Source/JavaScriptCore/runtime/ArrayStorage.h index d967d0b5a..1ab936335 100644 --- a/Source/JavaScriptCore/runtime/ArrayStorage.h +++ b/Source/JavaScriptCore/runtime/ArrayStorage.h @@ -64,10 +64,6 @@ public: m_sparseMap.copyFrom(other.m_sparseMap); m_indexBias = other.m_indexBias; m_numValuesInVector = other.m_numValuesInVector; -#if CHECK_ARRAY_CONSISTENCY - m_initializationIndex = other.m_initializationIndex; - m_inCompactInitialization = other.m_inCompactInitialization; -#endif } bool inSparseMode() @@ -78,11 +74,7 @@ public: WriteBarrier<SparseArrayValueMap> m_sparseMap; unsigned m_indexBias; unsigned m_numValuesInVector; -#if CHECK_ARRAY_CONSISTENCY - // Needs to be a uintptr_t for alignment purposes. - uintptr_t m_initializationIndex; - uintptr_t m_inCompactInitialization; -#elif USE(JSVALUE32_64) +#if USE(JSVALUE32_64) uintptr_t m_padding; #endif WriteBarrier<Unknown> m_vector[1]; diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h index 0e1747b24..e8823d571 100644 --- a/Source/JavaScriptCore/runtime/ClassInfo.h +++ b/Source/JavaScriptCore/runtime/ClassInfo.h @@ -81,8 +81,8 @@ namespace JSC { typedef String (*ClassNameFunctionPtr)(const JSObject*); ClassNameFunctionPtr className; - typedef bool (*HasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue, JSValue); - HasInstanceFunctionPtr hasInstance; + typedef bool (*CustomHasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue); + CustomHasInstanceFunctionPtr customHasInstance; typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, PropertyName propertyName, JSValue, unsigned attributes); PutWithAttributesFunctionPtr putDirectVirtual; @@ -130,7 +130,7 @@ struct MemberCheck##member { \ &ClassName::getOwnNonIndexPropertyNames, \ &ClassName::getPropertyNames, \ &ClassName::className, \ - &ClassName::hasInstance, \ + &ClassName::customHasInstance, \ &ClassName::putDirectVirtual, \ &ClassName::defineOwnProperty, \ &ClassName::getOwnPropertyDescriptor, \ diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h index e4c76ad16..7edd9091c 100644 --- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h +++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h @@ -75,28 +75,6 @@ ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFi return newExec; } -ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto) -{ - ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell() - || !value.isObject() || !baseVal.isObject() || !proto.isObject() - || !asObject(baseVal)->structure()->typeInfo().implementsDefaultHasInstance()); - - - // ECMA-262 15.3.5.3: - // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function). - TypeInfo typeInfo(UnspecifiedType); - if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) { - exec->globalData().exception = createInvalidParamError(exec, "instanceof", baseVal); - return false; - } - ASSERT(typeInfo.type() != UnspecifiedType); - - if (!typeInfo.overridesHasInstance() && !value.isObject()) - return false; - - return asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), exec, value, proto); -} - inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) { if (!baseVal.isObject()) { diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 62211d302..9b2cb164f 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -195,7 +195,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil #elif USE(ICU_UNICODE) && !UCONFIG_NO_FORMATTING -static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format) { UDateFormatStyle timeStyle = (format != LocaleDate ? UDAT_LONG : UDAT_NONE); UDateFormatStyle dateStyle = (format != LocaleTime ? UDAT_LONG : UDAT_NONE); diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 2791c65d4..d7327d564 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -135,7 +135,6 @@ const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExec FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node) : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode()) - , m_numCapturedVariables(0) , m_forceUsesArguments(node->usesArguments()) , m_parameters(node->parameters()) , m_name(node->ident()) @@ -527,7 +526,6 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s m_numParametersForCall = m_codeBlockForCall->numParameters(); ASSERT(m_numParametersForCall); - m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars; m_symbolTable.set(exec->globalData(), this, m_codeBlockForCall->symbolTable()); #if ENABLE(JIT) @@ -570,7 +568,6 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco m_numParametersForConstruct = m_codeBlockForConstruct->numParameters(); ASSERT(m_numParametersForConstruct); - m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars; m_symbolTable.set(exec->globalData(), this, m_codeBlockForConstruct->symbolTable()); #if ENABLE(JIT) diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 76ed21d8b..808c78fba 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -692,7 +692,6 @@ namespace JSC { const Identifier& inferredName() { return m_inferredName; } JSString* nameValue() const { return m_nameValue.get(); } size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'! - unsigned capturedVariableCount() const { return m_numCapturedVariables; } String paramString() const; SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); } @@ -742,8 +741,7 @@ namespace JSC { } static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; - unsigned m_numCapturedVariables : 31; - bool m_forceUsesArguments : 1; + bool m_forceUsesArguments; RefPtr<FunctionParameters> m_parameters; OwnPtr<FunctionCodeBlock> m_codeBlockForCall; diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index 455a21877..dd1628b29 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -193,7 +193,6 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec) for (size_t i = 0; i < numBoundArgs; ++i) boundArgs->initializeIndex(exec->globalData(), i, exec->argument(i + 1)); - boundArgs->completeInitialization(numBoundArgs); // If the [[Class]] internal property of Target is "Function", then ... // Else set the length own property of F to 0. diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index dc061bc57..c34e10bc8 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -53,7 +53,7 @@ void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) if (!thisObject->isTornOff()) return; - for (size_t i = 0; i < thisObject->storageSize(); ++i) + for (int i = 0; i < thisObject->symbolTable()->captureCount(); ++i) visitor.append(&thisObject->storage()[i]); } diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 8211e7710..442941335 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -41,21 +41,20 @@ namespace JSC { class JSActivation : public JSVariableObject { private: - JSActivation(JSGlobalData& globalData, CallFrame*, SharedSymbolTable*, size_t storageSize); + JSActivation(JSGlobalData& globalData, CallFrame*, SharedSymbolTable*); public: typedef JSVariableObject Base; static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* functionExecutable) { - size_t storageSize = JSActivation::storageSize(functionExecutable->symbolTable()); JSActivation* activation = new ( NotNull, allocateCell<JSActivation>( globalData.heap, - allocationSize(storageSize) + allocationSize(functionExecutable->symbolTable()) ) - ) JSActivation(globalData, callFrame, functionExecutable->symbolTable(), storageSize); + ) JSActivation(globalData, callFrame, functionExecutable->symbolTable()); activation->finishCreation(globalData); return activation; } @@ -81,7 +80,9 @@ namespace JSC { static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); } - bool isValid(const SymbolTableEntry&); + WriteBarrierBase<Unknown>& registerAt(int) const; + bool isValidIndex(int) const; + bool isValid(const SymbolTableEntry&) const; bool isTornOff(); protected: @@ -97,19 +98,16 @@ namespace JSC { static JSValue argumentsGetter(ExecState*, JSValue, PropertyName); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); - static size_t allocationSize(size_t storageSize); - static size_t storageSize(SharedSymbolTable*); - static int captureStart(SharedSymbolTable*); + static size_t allocationSize(SharedSymbolTable*); int registerOffset(); - size_t storageSize(); - WriteBarrier<Unknown>* storage(); // storageSize() number of registers. + WriteBarrier<Unknown>* storage(); // captureCount() number of registers. }; extern int activationCount; extern int allTheThingsCount; - inline JSActivation::JSActivation(JSGlobalData& globalData, CallFrame* callFrame, SharedSymbolTable* symbolTable, size_t storageSize) + inline JSActivation::JSActivation(JSGlobalData& globalData, CallFrame* callFrame, SharedSymbolTable* symbolTable) : Base( globalData, callFrame->lexicalGlobalObject()->activationStructure(), @@ -119,7 +117,8 @@ namespace JSC { ) { WriteBarrier<Unknown>* storage = this->storage(); - for (size_t i = 0; i < storageSize; ++i) + size_t captureCount = symbolTable->captureCount(); + for (size_t i = 0; i < captureCount; ++i) new(&storage[i]) WriteBarrier<Unknown>; } @@ -142,26 +141,9 @@ namespace JSC { return false; } - inline int JSActivation::captureStart(SharedSymbolTable* symbolTable) - { - if (symbolTable->captureMode() == SharedSymbolTable::AllOfTheThings) - return -CallFrame::offsetFor(symbolTable->parameterCountIncludingThis()); - return symbolTable->captureStart(); - } - - inline size_t JSActivation::storageSize(SharedSymbolTable* symbolTable) - { - return symbolTable->captureEnd() - captureStart(symbolTable); - } - inline int JSActivation::registerOffset() { - return -captureStart(symbolTable()); - } - - inline size_t JSActivation::storageSize() - { - return storageSize(symbolTable()); + return -symbolTable()->captureStart(); } inline void JSActivation::tearOff(JSGlobalData& globalData) @@ -172,23 +154,9 @@ namespace JSC { WriteBarrierBase<Unknown>* dst = storage() + registerOffset; WriteBarrierBase<Unknown>* src = m_registers; - if (symbolTable()->captureMode() == SharedSymbolTable::AllOfTheThings) { - int from = -registerOffset; - int to = CallFrame::thisArgumentOffset(); // Skip 'this' because it's not lexically accessible. - for (int i = from; i < to; ++i) - dst[i].set(globalData, this, src[i].get()); - - dst[RegisterFile::ArgumentCount].set(globalData, this, JSValue( - CallFrame::create(reinterpret_cast<Register*>(src))->argumentCountIncludingThis())); - - int captureEnd = symbolTable()->captureEnd(); - for (int i = 0; i < captureEnd; ++i) - dst[i].set(globalData, this, src[i].get()); - } else { - int captureEnd = symbolTable()->captureEnd(); - for (int i = symbolTable()->captureStart(); i < captureEnd; ++i) - dst[i].set(globalData, this, src[i].get()); - } + int captureEnd = symbolTable()->captureEnd(); + for (int i = symbolTable()->captureStart(); i < captureEnd; ++i) + dst[i].set(globalData, this, src[i].get()); m_registers = dst; ASSERT(isTornOff()); @@ -207,22 +175,33 @@ namespace JSC { ); } - inline size_t JSActivation::allocationSize(size_t storageSize) + inline size_t JSActivation::allocationSize(SharedSymbolTable* symbolTable) { size_t objectSizeInBytes = WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation)); - size_t storageSizeInBytes = storageSize * sizeof(WriteBarrier<Unknown>); + size_t storageSizeInBytes = symbolTable->captureCount() * sizeof(WriteBarrier<Unknown>); return objectSizeInBytes + storageSizeInBytes; } - inline bool JSActivation::isValid(const SymbolTableEntry& entry) + inline bool JSActivation::isValidIndex(int index) const { - if (entry.getIndex() < captureStart(symbolTable())) + if (index < symbolTable()->captureStart()) return false; - if (entry.getIndex() >= symbolTable()->captureEnd()) + if (index >= symbolTable()->captureEnd()) return false; return true; } + inline bool JSActivation::isValid(const SymbolTableEntry& entry) const + { + return isValidIndex(entry.getIndex()); + } + + inline WriteBarrierBase<Unknown>& JSActivation::registerAt(int index) const + { + ASSERT(isValidIndex(index)); + return Base::registerAt(index); + } + } // namespace JSC #endif // JSActivation_h diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index ebbbd41aa..609781c65 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -60,10 +60,6 @@ Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData& globalData storage->m_indexBias = 0; storage->m_sparseMap.clear(); storage->m_numValuesInVector = 0; -#if CHECK_ARRAY_CONSISTENCY - storage->m_initializationIndex = 0; - storage->m_inCompactInitialization = 0; -#endif return butterfly; } @@ -330,8 +326,6 @@ bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, unsigned count) bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException) { - checkIndexingConsistency(); - ArrayStorage* storage = ensureArrayStorage(exec->globalData()); unsigned length = storage->length(); @@ -392,14 +386,11 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException storage->setLength(newLength); - checkIndexingConsistency(); return true; } JSValue JSArray::pop(ExecState* exec) { - checkIndexingConsistency(); - switch (structure()->indexingType()) { case ArrayClass: return jsUndefined(); @@ -424,7 +415,6 @@ JSValue JSArray::pop(ExecState* exec) ASSERT(isLengthWritable()); storage->setLength(index); - checkIndexingConsistency(); return element; } } @@ -441,7 +431,6 @@ JSValue JSArray::pop(ExecState* exec) // Call the [[Put]] internal method of O with arguments "length", indx, and true. setLength(exec, index, true); // Return element. - checkIndexingConsistency(); return element; } @@ -456,8 +445,6 @@ JSValue JSArray::pop(ExecState* exec) // - pushing to an array of length 2^32-1 stores the property, but throws a range error. void JSArray::push(ExecState* exec, JSValue value) { - checkIndexingConsistency(); - switch (structure()->indexingType()) { case ArrayClass: { putByIndexBeyondVectorLengthWithArrayStorage(exec, 0, value, true, createInitialArrayStorage(exec->globalData())); @@ -483,7 +470,6 @@ void JSArray::push(ExecState* exec, JSValue value) storage->m_vector[length].set(exec->globalData(), this, value); storage->setLength(length + 1); ++storage->m_numValuesInVector; - checkIndexingConsistency(); return; } @@ -498,7 +484,6 @@ void JSArray::push(ExecState* exec, JSValue value) // Handled the same as putIndex. putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage); - checkIndexingConsistency(); break; } @@ -622,7 +607,6 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal // side-effect from swapping the order of equal primitive values. qsort(storage->m_vector, size, sizeof(WriteBarrier<Unknown>), compareNumbersForQSort); - checkIndexingConsistency(SortConsistencyCheck); return; } @@ -711,7 +695,6 @@ void JSArray::sort(ExecState* exec) Heap::heap(this)->popTempSortVector(&values); - checkIndexingConsistency(SortConsistencyCheck); return; } @@ -807,7 +790,6 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, case ArrayWithArrayStorage: { ArrayStorage* storage = m_butterfly->arrayStorage(); - checkIndexingConsistency(); // FIXME: This ignores exceptions raised in the compare function or in toNumber. @@ -912,7 +894,6 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, storage->m_numValuesInVector = newUsedVectorLength; - checkIndexingConsistency(SortConsistencyCheck); return; } @@ -983,8 +964,6 @@ unsigned JSArray::compactForSorting(JSGlobalData& globalData) { ASSERT(!inSparseIndexingMode()); - checkIndexingConsistency(); - switch (structure()->indexingType()) { case ArrayClass: return 0; @@ -1040,8 +1019,6 @@ unsigned JSArray::compactForSorting(JSGlobalData& globalData) storage->m_numValuesInVector = newUsedVectorLength; - checkIndexingConsistency(SortConsistencyCheck); - return numDefined; } diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index c46e67863..6e539c9db 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -51,7 +51,6 @@ namespace JSC { // contents are known at time of creation. Clients of this interface must: // - null-check the result (indicating out of memory, or otherwise unable to allocate vector). // - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength. - // - called 'completeInitialization' after all properties have been initialized. static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength); JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool throwException); @@ -115,10 +114,6 @@ namespace JSC { storage->m_indexBias = 0; storage->m_sparseMap.clear(); storage->m_numValuesInVector = 0; -#if CHECK_ARRAY_CONSISTENCY - storage->m_initializationIndex = 0; - storage->m_inCompactInitialization = 0; -#endif return butterfly; } @@ -147,10 +142,6 @@ namespace JSC { storage->m_indexBias = 0; storage->m_sparseMap.clear(); storage->m_numValuesInVector = initialLength; -#if CHECK_ARRAY_CONSISTENCY - storage->m_initializationIndex = 0; - storage->m_inCompactInitialization = true; -#endif JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly); array->finishCreation(globalData); @@ -187,7 +178,6 @@ namespace JSC { for (unsigned i = 0; i < length; ++i) array->initializeIndex(globalData, i, values.at(i)); - array->completeInitialization(length); return array; } @@ -204,7 +194,6 @@ namespace JSC { for (unsigned i = 0; i < length; ++i) array->initializeIndex(globalData, i, values[i]); - array->completeInitialization(length); return array; } diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp index 08d6831c0..3815c144e 100644 --- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp @@ -89,14 +89,9 @@ JSBoundFunction* JSBoundFunction::create(ExecState* exec, JSGlobalObject* global return function; } -bool JSBoundFunction::hasInstance(JSObject* object, ExecState* exec, JSValue value, JSValue) +bool JSBoundFunction::customHasInstance(JSObject* object, ExecState* exec, JSValue value) { - JSBoundFunction* thisObject = jsCast<JSBoundFunction*>(object); - // FIXME: our instanceof implementation will have already (incorrectly) performed - // a [[Get]] of .prototype from the bound function object, which is incorrect! - // https://bugs.webkit.org/show_bug.cgi?id=68656 - JSValue proto = thisObject->m_targetFunction->get(exec, exec->propertyNames().prototype); - return thisObject->m_targetFunction->methodTable()->hasInstance(thisObject->m_targetFunction.get(), exec, value, proto); + return jsCast<JSBoundFunction*>(object)->m_targetFunction->hasInstance(exec, value); } JSBoundFunction::JSBoundFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs) diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h index 5067d194c..05a6ad8e1 100644 --- a/Source/JavaScriptCore/runtime/JSBoundFunction.h +++ b/Source/JavaScriptCore/runtime/JSBoundFunction.h @@ -39,7 +39,7 @@ public: static JSBoundFunction* create(ExecState*, JSGlobalObject*, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs, int, const String&); - static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue proto); + static bool customHasInstance(JSObject*, ExecState*, JSValue); JSObject* targetFunction() { return m_targetFunction.get(); } JSValue boundThis() { return m_boundThis.get(); } diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index e050a53ef..739247fb2 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -199,7 +199,7 @@ void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, Enumera ASSERT_NOT_REACHED(); } -bool JSCell::hasInstance(JSObject*, ExecState*, JSValue, JSValue) +bool JSCell::customHasInstance(JSObject*, ExecState*, JSValue) { ASSERT_NOT_REACHED(); return false; diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index d6abcba99..cf6f4ec45 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -160,7 +160,7 @@ namespace JSC { static NO_RETURN_DUE_TO_ASSERT void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); static String className(const JSObject*); - static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue); static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes); static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 27f68e55b..3d643a266 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -310,9 +310,9 @@ void JSGlobalObject::reset(JSValue prototype) putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum); putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum); + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum); GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly) diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 229d1aea6..acff8a6ae 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -341,7 +341,6 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { JSObject* thisObject = jsCast<JSObject*>(cell); - thisObject->checkIndexingConsistency(); if (propertyName > MAX_ARRAY_INDEX) { PutPropertySlot slot(shouldThrow); @@ -372,7 +371,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, ++storage->m_numValuesInVector; valueSlot.set(exec->globalData(), thisObject, value); - thisObject->checkIndexingConsistency(); return; } @@ -400,7 +398,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, } valueSlot.set(exec->globalData(), thisObject, value); - thisObject->checkIndexingConsistency(); return; } @@ -409,7 +406,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, } thisObject->putByIndexBeyondVectorLength(exec, propertyName, value, shouldThrow); - thisObject->checkIndexingConsistency(); } ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData& globalData, ArrayStorage* storage) @@ -485,10 +481,6 @@ ArrayStorage* JSObject::createArrayStorage(JSGlobalData& globalData, unsigned le result->m_sparseMap.clear(); result->m_numValuesInVector = 0; result->m_indexBias = 0; -#if CHECK_ARRAY_CONSISTENCY - result->m_initializationIndex = 0; - result->m_inCompactInitialization = 0; -#endif Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), structure()->suggestedIndexingTransition()); setButterfly(globalData, newButterfly, newStructure); return result; @@ -717,7 +709,6 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) } } - thisObject->checkIndexingConsistency(); return true; } @@ -792,7 +783,18 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, PropertyName p return 0; } -bool JSObject::hasInstance(JSObject*, ExecState* exec, JSValue value, JSValue proto) +bool JSObject::hasInstance(ExecState* exec, JSValue value) +{ + TypeInfo info = structure()->typeInfo(); + if (info.implementsDefaultHasInstance()) + return defaultHasInstance(exec, value, get(exec, exec->propertyNames().prototype)); + if (info.implementsHasInstance()) + return methodTable()->customHasInstance(this, exec, value); + throwError(exec, createInvalidParamError(exec, "instanceof" , this)); + return false; +} + +bool JSObject::defaultHasInstance(ExecState* exec, JSValue value, JSValue proto) { if (!value.isObject()) return false; @@ -1570,49 +1572,6 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength return true; } -#if CHECK_ARRAY_CONSISTENCY -void JSObject::checkIndexingConsistency(ConsistencyCheckType type) -{ - ArrayStorage* storage = arrayStorageOrNull(); - if (!storage) - return; - - ASSERT(!storage->m_inCompactInitialization); - - ASSERT(storage); - if (type == SortConsistencyCheck) - ASSERT(!storage->m_sparseMap); - - unsigned numValuesInVector = 0; - for (unsigned i = 0; i < storage->vectorLength(); ++i) { - if (JSValue value = storage->m_vector[i].get()) { - ASSERT(i < storage->length()); - if (type != DestructorConsistencyCheck) - value.isUndefined(); // Likely to crash if the object was deallocated. - ++numValuesInVector; - } else { - if (type == SortConsistencyCheck) - ASSERT(i >= storage->m_numValuesInVector); - } - } - ASSERT(numValuesInVector == storage->m_numValuesInVector); - ASSERT(numValuesInVector <= storage->length()); - - if (m_sparseValueMap) { - SparseArrayValueMap::const_iterator end = m_sparseValueMap->end(); - for (SparseArrayValueMap::const_iterator it = m_sparseValueMap->begin(); it != end; ++it) { - unsigned index = it->first; - ASSERT(index < storage->length()); - ASSERT(index >= storage->vectorLength()); - ASSERT(index <= MAX_ARRAY_INDEX); - ASSERT(it->second); - if (type != DestructorConsistencyCheck) - it->second.getNonSparseMode().isUndefined(); // Likely to crash if the object was deallocated. - } - } -} -#endif // CHECK_ARRAY_CONSISTENCY - Butterfly* JSObject::growOutOfLineStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize) { ASSERT(newSize > oldSize); diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index bf2dae20d..bb59eb32b 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -259,15 +259,6 @@ namespace JSC { switch (structure()->indexingType()) { case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); -#if CHECK_ARRAY_CONSISTENCY - ASSERT(storage->m_inCompactInitialization); - // Check that we are initializing the next index in sequence. - ASSERT(i == storage->m_initializationIndex); - // tryCreateUninitialized set m_numValuesInVector to the initialLength, - // check we do not try to initialize more than this number of properties. - ASSERT(storage->m_initializationIndex < storage->m_numValuesInVector); - storage->m_initializationIndex++; -#endif ASSERT(i < storage->length()); ASSERT(i < storage->m_numValuesInVector); storage->m_vector[i].set(globalData, this, v); @@ -278,27 +269,6 @@ namespace JSC { } } - void completeInitialization(unsigned newLength) - { - switch (structure()->indexingType()) { - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { - ArrayStorage* storage = m_butterfly->arrayStorage(); - // Check that we have initialized as meny properties as we think we have. - UNUSED_PARAM(storage); - ASSERT_UNUSED(newLength, newLength == storage->length()); -#if CHECK_ARRAY_CONSISTENCY - // Check that the number of propreties initialized matches the initialLength. - ASSERT(storage->m_initializationIndex == m_storage->m_numValuesInVector); - ASSERT(storage->m_inCompactInitialization); - storage->m_inCompactInitialization = false; -#endif - break; - } - default: - ASSERT_NOT_REACHED(); - } - } - bool inSparseIndexingMode() { switch (structure()->indexingType()) { @@ -336,7 +306,8 @@ namespace JSC { JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); - JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + bool hasInstance(ExecState*, JSValue); + static bool defaultHasInstance(ExecState*, JSValue, JSValue prototypeProperty); JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); @@ -591,13 +562,6 @@ namespace JSC { bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException); - enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck }; -#if !CHECK_ARRAY_CONSISTENCY - void checkIndexingConsistency(ConsistencyCheckType = NormalConsistencyCheck) { } -#else - void checkIndexingConsistency(ConsistencyCheckType = NormalConsistencyCheck); -#endif - void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*); bool increaseVectorLength(JSGlobalData&, unsigned newLength); diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index 16c0b5d43..b164948a5 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -35,6 +35,7 @@ #include <wtf/PageBlock.h> #include <wtf/StdLibExtras.h> #include <wtf/StringExtras.h> +#include <wtf/UnusedParam.h> #if OS(DARWIN) && ENABLE(PARALLEL_GC) #include <sys/sysctl.h> @@ -101,6 +102,8 @@ static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers) ASSERT(cpusToUse >= 1); if (cpusToUse < 1) cpusToUse = 1; +#else + UNUSED_PARAM(maxNumberOfGCMarkers); #endif return cpusToUse; diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h index 5427a009b..6063dbab4 100644 --- a/Source/JavaScriptCore/runtime/SymbolTable.h +++ b/Source/JavaScriptCore/runtime/SymbolTable.h @@ -49,12 +49,12 @@ namespace JSC { SlowArgument() : status(Normal) - , indexIfCaptured(0) + , index(0) { } Status status; - int indexIfCaptured; // If status is 'Captured', indexIfCaptured is our index in the CallFrame. + int index; // If status is 'Deleted', index is bogus. }; static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } @@ -360,20 +360,14 @@ namespace JSC { bool usesNonStrictEval() { return m_usesNonStrictEval; } void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } - enum CaptureMode { - SomeOfTheThings, - AllOfTheThings - }; - - CaptureMode captureMode() { return m_captureMode; } - void setCaptureMode(CaptureMode captureMode) { m_captureMode = captureMode; } - int captureStart() { return m_captureStart; } void setCaptureStart(int captureStart) { m_captureStart = captureStart; } int captureEnd() { return m_captureEnd; } void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } + int captureCount() { return m_captureEnd - m_captureStart; } + int parameterCount() { return m_parameterCountIncludingThis - 1; } int parameterCountIncludingThis() { return m_parameterCountIncludingThis; } void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; } @@ -389,7 +383,6 @@ namespace JSC { : JSCell(globalData, globalData.sharedSymbolTableStructure.get()) , m_parameterCountIncludingThis(0) , m_usesNonStrictEval(false) - , m_captureMode(SomeOfTheThings) , m_captureStart(0) , m_captureEnd(0) { @@ -398,7 +391,6 @@ namespace JSC { int m_parameterCountIncludingThis; bool m_usesNonStrictEval; - CaptureMode m_captureMode; int m_captureStart; int m_captureEnd; |