diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:15:52 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:16:06 +0100 |
commit | de4f791e30be4e4239b381c11745ffa4d87ddb8b (patch) | |
tree | 885e3a5d6670828b454cf676b4d42f78e28b1f0e /Source/JavaScriptCore/runtime | |
parent | b022df48697d40cdabdeafb2c29bb14fe489b6fe (diff) | |
download | qtwebkit-de4f791e30be4e4239b381c11745ffa4d87ddb8b.tar.gz |
Imported WebKit commit e2c32e2f53e02d388e70b9db88b91d8d9d28fc84 (http://svn.webkit.org/repository/webkit/trunk@133952)
Revert back to an older snapshot that should build on ARM
Diffstat (limited to 'Source/JavaScriptCore/runtime')
33 files changed, 550 insertions, 1797 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 8ae991422..7961d4bc8 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -34,246 +34,246 @@ namespace JSC { -class Arguments : public JSDestructibleObject { - friend class JIT; - friend class DFG::SpeculativeJIT; -public: - typedef JSDestructibleObject Base; + class Arguments : public JSDestructibleObject { + friend class JIT; + friend class DFG::SpeculativeJIT; + public: + typedef JSDestructibleObject Base; + + static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame) + { + Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame); + return arguments; + } + + static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + { + Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame, inlineCallFrame); + return arguments; + } + + enum { MaxArguments = 0x10000 }; + + private: + enum NoParametersType { NoParameters }; + + Arguments(CallFrame*); + Arguments(CallFrame*, NoParametersType); + + void tearOffForInlineCallFrame(JSGlobalData& globalData, Register*, InlineCallFrame*); - static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame) + public: + static const ClassInfo s_info; + + static void visitChildren(JSCell*, SlotVisitor&); + + void fillArgList(ExecState*, MarkedArgumentBuffer&); + + uint32_t length(ExecState* exec) const + { + if (UNLIKELY(m_overrodeLength)) + return get(exec, exec->propertyNames().length).toUInt32(exec); + return m_numArguments; + } + + void copyToArguments(ExecState*, CallFrame*, uint32_t length); + void tearOff(CallFrame*); + void tearOff(CallFrame*, InlineCallFrame*); + bool isTornOff() const { return m_registerArray; } + void didTearOffActivation(ExecState*, JSActivation*); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + + void finishCreation(CallFrame*); + void finishCreation(CallFrame*, InlineCallFrame*); + + private: + static void destroy(JSCell*); + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); + void createStrictModeCallerIfNecessary(ExecState*); + void createStrictModeCalleeIfNecessary(ExecState*); + + bool isArgument(size_t); + bool trySetArgument(JSGlobalData&, size_t argument, JSValue); + JSValue tryGetArgument(size_t argument); + bool isDeletedArgument(size_t); + bool tryDeleteArgument(size_t); + WriteBarrierBase<Unknown>& argument(size_t); + void allocateSlowArguments(); + + void init(CallFrame*); + + WriteBarrier<JSActivation> m_activation; + + unsigned m_numArguments; + + // We make these full byte booleans to make them easy to test from the JIT, + // and because even if they were single-bit booleans we still wouldn't save + // any space. + bool m_overrodeLength; + bool m_overrodeCallee; + bool m_overrodeCaller; + bool m_isStrictMode; + + WriteBarrierBase<Unknown>* m_registers; + OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; + + OwnArrayPtr<SlowArgument> m_slowArguments; + + WriteBarrier<JSFunction> m_callee; + }; + + Arguments* asArguments(JSValue); + + inline Arguments* asArguments(JSValue value) { - Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame); - arguments->finishCreation(callFrame); - return arguments; + ASSERT(asObject(value)->inherits(&Arguments::s_info)); + return static_cast<Arguments*>(asObject(value)); } - - static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + + inline Arguments::Arguments(CallFrame* callFrame) + : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) { - Arguments* arguments = new (NotNull, allocateCell<Arguments>(globalData.heap)) Arguments(callFrame); - arguments->finishCreation(callFrame, inlineCallFrame); - return arguments; } - enum { MaxArguments = 0x10000 }; + inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) + : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) + { + } -private: - enum NoParametersType { NoParameters }; - - Arguments(CallFrame*); - Arguments(CallFrame*, NoParametersType); - - void tearOffForInlineCallFrame(JSGlobalData& globalData, Register*, InlineCallFrame*); + inline void Arguments::allocateSlowArguments() + { + 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); + } + } -public: - static const ClassInfo s_info; + inline bool Arguments::tryDeleteArgument(size_t argument) + { + if (!isArgument(argument)) + return false; + allocateSlowArguments(); + m_slowArguments[argument].status = SlowArgument::Deleted; + return true; + } - static void visitChildren(JSCell*, SlotVisitor&); + inline bool Arguments::trySetArgument(JSGlobalData& globalData, size_t argument, JSValue value) + { + if (!isArgument(argument)) + return false; + this->argument(argument).set(globalData, this, value); + return true; + } - void fillArgList(ExecState*, MarkedArgumentBuffer&); + inline JSValue Arguments::tryGetArgument(size_t argument) + { + if (!isArgument(argument)) + return JSValue(); + return this->argument(argument).get(); + } - uint32_t length(ExecState* exec) const + inline bool Arguments::isDeletedArgument(size_t argument) { - if (UNLIKELY(m_overrodeLength)) - return get(exec, exec->propertyNames().length).toUInt32(exec); - return m_numArguments; + if (argument >= m_numArguments) + return false; + if (!m_slowArguments) + return false; + if (m_slowArguments[argument].status != SlowArgument::Deleted) + return false; + return true; } - - void copyToArguments(ExecState*, CallFrame*, uint32_t length); - void tearOff(CallFrame*); - void tearOff(CallFrame*, InlineCallFrame*); - bool isTornOff() const { return m_registerArray; } - void didTearOffActivation(ExecState*, JSActivation*); - - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) - { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + + inline bool Arguments::isArgument(size_t argument) + { + if (argument >= m_numArguments) + return false; + if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted) + return false; + return true; } - -protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; - - void finishCreation(CallFrame*); - void finishCreation(CallFrame*, InlineCallFrame*); - -private: - static void destroy(JSCell*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); - static bool deleteProperty(JSCell*, ExecState*, PropertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); - void createStrictModeCallerIfNecessary(ExecState*); - void createStrictModeCalleeIfNecessary(ExecState*); - - bool isArgument(size_t); - bool trySetArgument(JSGlobalData&, size_t argument, JSValue); - JSValue tryGetArgument(size_t argument); - bool isDeletedArgument(size_t); - bool tryDeleteArgument(size_t); - WriteBarrierBase<Unknown>& argument(size_t); - void allocateSlowArguments(); - - void init(CallFrame*); - - WriteBarrier<JSActivation> m_activation; - - unsigned m_numArguments; - - // We make these full byte booleans to make them easy to test from the JIT, - // and because even if they were single-bit booleans we still wouldn't save - // any space. - bool m_overrodeLength; - bool m_overrodeCallee; - bool m_overrodeCaller; - bool m_isStrictMode; - - WriteBarrierBase<Unknown>* m_registers; - OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; - - OwnArrayPtr<SlowArgument> m_slowArguments; - - WriteBarrier<JSFunction> m_callee; -}; - -Arguments* asArguments(JSValue); - -inline Arguments* asArguments(JSValue value) -{ - ASSERT(asObject(value)->inherits(&Arguments::s_info)); - return static_cast<Arguments*>(asObject(value)); -} - -inline Arguments::Arguments(CallFrame* callFrame) - : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) -{ -} - -inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) - : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) -{ -} - -inline void Arguments::allocateSlowArguments() -{ - 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 WriteBarrierBase<Unknown>& Arguments::argument(size_t argument) + { + ASSERT(isArgument(argument)); + if (!m_slowArguments) + return m_registers[CallFrame::argumentOffset(argument)]; + + int index = m_slowArguments[argument].index; + if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured) + return m_registers[index]; + + return m_activation->registerAt(index); } -} - -inline bool Arguments::tryDeleteArgument(size_t argument) -{ - if (!isArgument(argument)) - return false; - allocateSlowArguments(); - m_slowArguments[argument].status = SlowArgument::Deleted; - return true; -} - -inline bool Arguments::trySetArgument(JSGlobalData& globalData, size_t argument, JSValue value) -{ - if (!isArgument(argument)) - return false; - this->argument(argument).set(globalData, this, value); - return true; -} - -inline JSValue Arguments::tryGetArgument(size_t argument) -{ - if (!isArgument(argument)) - return JSValue(); - return this->argument(argument).get(); -} - -inline bool Arguments::isDeletedArgument(size_t argument) -{ - if (argument >= m_numArguments) - return false; - if (!m_slowArguments) - return false; - if (m_slowArguments[argument].status != SlowArgument::Deleted) - return false; - return true; -} - -inline bool Arguments::isArgument(size_t argument) -{ - if (argument >= m_numArguments) - return false; - if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted) - return false; - return true; -} - -inline WriteBarrierBase<Unknown>& Arguments::argument(size_t argument) -{ - ASSERT(isArgument(argument)); - if (!m_slowArguments) - return m_registers[CallFrame::argumentOffset(argument)]; - - int index = m_slowArguments[argument].index; - if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured) - return m_registers[index]; - - return m_activation->registerAt(index); -} - -inline void Arguments::finishCreation(CallFrame* callFrame) -{ - Base::finishCreation(callFrame->globalData()); - ASSERT(inherits(&s_info)); - - JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); - m_numArguments = callFrame->argumentCount(); - m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()); - m_callee.set(callFrame->globalData(), this, callee); - m_overrodeLength = false; - m_overrodeCallee = false; - 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]; + + inline void Arguments::finishCreation(CallFrame* callFrame) + { + Base::finishCreation(callFrame->globalData()); + ASSERT(inherits(&s_info)); + + JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); + m_numArguments = callFrame->argumentCount(); + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()); + m_callee.set(callFrame->globalData(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + 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()) + tearOff(callFrame); } - // 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()) - tearOff(callFrame); -} - -inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) -{ - Base::finishCreation(callFrame->globalData()); - ASSERT(inherits(&s_info)); - - JSFunction* callee = inlineCallFrame->callee.get(); - m_numArguments = inlineCallFrame->arguments.size() - 1; - m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset; - m_callee.set(callFrame->globalData(), this, callee); - m_overrodeLength = false; - m_overrodeCallee = false; - m_overrodeCaller = false; - m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); - ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->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()) - tearOff(callFrame, inlineCallFrame); -} + inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + { + Base::finishCreation(callFrame->globalData()); + ASSERT(inherits(&s_info)); + + JSFunction* callee = inlineCallFrame->callee.get(); + m_numArguments = inlineCallFrame->arguments.size() - 1; + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset; + m_callee.set(callFrame->globalData(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + m_overrodeCaller = false; + m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); + ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->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()) + tearOff(callFrame, inlineCallFrame); + } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index a3fce45f2..5c2cd7167 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -25,8 +25,8 @@ #include "ArrayConstructor.h" #include "ArrayPrototype.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "Error.h" #include "ExceptionHelpers.h" #include "JSArray.h" @@ -77,15 +77,15 @@ bool ArrayConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exe // ------------------------------ Functions --------------------------- -JSObject* constructArrayWithSizeQuirk(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, JSValue length) +JSObject* constructArrayWithSizeQuirk(ExecState* exec, JSGlobalObject* globalObject, JSValue length) { if (!length.isNumber()) - return constructArray(exec, profile, globalObject, &length, 1); + return constructArray(exec, globalObject, &length, 1); uint32_t n = length.toUInt32(exec); if (n != length.toNumber(exec)) return throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))); - return constructEmptyArray(exec, profile, globalObject, n); + return constructEmptyArray(exec, globalObject, n); } static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) @@ -94,10 +94,10 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi // a single numeric argument denotes the array size (!) if (args.size() == 1) - return constructArrayWithSizeQuirk(exec, 0, globalObject, args.at(0)); + return constructArrayWithSizeQuirk(exec, globalObject, args.at(0)); // otherwise the array is constructed with the arguments in it - return constructArray(exec, 0, globalObject, args); + return constructArray(exec, globalObject, args); } static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h index 96860b0fc..dcbf0a1b3 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.h +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h @@ -25,42 +25,42 @@ namespace JSC { -class ArrayPrototype; -class JSArray; + class ArrayPrototype; + class JSArray; -class ArrayConstructor : public InternalFunction { -public: - typedef InternalFunction Base; + class ArrayConstructor : public InternalFunction { + public: + typedef InternalFunction Base; - static ArrayConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype) - { - ArrayConstructor* constructor = new (NotNull, allocateCell<ArrayConstructor>(*exec->heap())) ArrayConstructor(globalObject, structure); - constructor->finishCreation(exec, arrayPrototype); - return constructor; - } + static ArrayConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype) + { + ArrayConstructor* constructor = new (NotNull, allocateCell<ArrayConstructor>(*exec->heap())) ArrayConstructor(globalObject, structure); + constructor->finishCreation(exec, arrayPrototype); + return constructor; + } - static const ClassInfo s_info; + static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) - { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); - } + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } -protected: - void finishCreation(ExecState*, ArrayPrototype*); - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags; + protected: + void finishCreation(ExecState*, ArrayPrototype*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags; -private: - ArrayConstructor(JSGlobalObject*, Structure*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); + private: + ArrayConstructor(JSGlobalObject*, Structure*); + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - static ConstructType getConstructData(JSCell*, ConstructData&); - static CallType getCallData(JSCell*, CallData&); -}; + static ConstructType getConstructData(JSCell*, ConstructData&); + static CallType getCallData(JSCell*, CallData&); + }; -JSObject* constructArrayWithSizeQuirk(ExecState*, ArrayAllocationProfile*, JSGlobalObject*, JSValue); + JSObject* constructArrayWithSizeQuirk(ExecState*, JSGlobalObject*, JSValue); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index cc847d8ff..6975dc778 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -24,10 +24,10 @@ #include "config.h" #include "ArrayPrototype.h" -#include "ButterflyInlines.h" +#include "ButterflyInlineMethods.h" #include "CachedCall.h" #include "CodeBlock.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" #include "Interpreter.h" #include "JIT.h" #include "JSStringBuilder.h" @@ -456,7 +456,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - JSArray* arr = constructEmptyArray(exec, 0); + JSArray* arr = constructEmptyArray(exec); unsigned n = 0; JSValue curArg = thisValue.toObject(exec); if (exec->hadException()) @@ -618,7 +618,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) return JSValue::encode(jsUndefined()); // We return a new array - JSArray* resObj = constructEmptyArray(exec, 0); + JSArray* resObj = constructEmptyArray(exec); JSValue result = resObj; unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); @@ -733,7 +733,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) return JSValue::encode(jsUndefined()); if (!exec->argumentCount()) - return JSValue::encode(constructEmptyArray(exec, 0)); + return JSValue::encode(constructEmptyArray(exec)); unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); @@ -748,7 +748,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) deleteCount = static_cast<unsigned>(deleteDouble); } - JSArray* resObj = JSArray::tryCreateUninitialized(exec->globalData(), exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount); + JSArray* resObj = JSArray::tryCreateUninitialized(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount); if (!resObj) return JSValue::encode(throwOutOfMemoryError(exec)); @@ -820,7 +820,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) return throwVMTypeError(exec); JSValue applyThis = exec->argument(1); - JSArray* resultArray = constructEmptyArray(exec, 0); + JSArray* resultArray = constructEmptyArray(exec); unsigned filterIndex = 0; unsigned k = 0; @@ -880,7 +880,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) JSValue applyThis = exec->argument(1); - JSArray* resultArray = constructEmptyArray(exec, 0, length); + JSArray* resultArray = constructEmptyArray(exec, length); unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { JSFunction* f = jsCast<JSFunction*>(function); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index 2b83d39b7..b33021121 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -26,28 +26,28 @@ namespace JSC { -class ArrayPrototype : public JSArray { -private: - ArrayPrototype(JSGlobalObject*, Structure*, Butterfly*); + class ArrayPrototype : public JSArray { + private: + ArrayPrototype(JSGlobalObject*, Structure*, Butterfly*); -public: - typedef JSArray Base; + public: + typedef JSArray Base; - static ArrayPrototype* create(ExecState*, JSGlobalObject*, Structure*); + static ArrayPrototype* create(ExecState*, JSGlobalObject*, Structure*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - static const ClassInfo s_info; + static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) - { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayWithArrayStorage); - } + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayWithArrayStorage); + } -protected: - void finishCreation(JSGlobalObject*); -}; + protected: + void finishCreation(JSGlobalObject*); + }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Butterfly.h b/Source/JavaScriptCore/runtime/Butterfly.h index 4b8d53f7e..cb93aea8a 100644 --- a/Source/JavaScriptCore/runtime/Butterfly.h +++ b/Source/JavaScriptCore/runtime/Butterfly.h @@ -88,18 +88,12 @@ public: template<typename T> T* indexingPayload() { return reinterpret_cast<T*>(this); } ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); } - WriteBarrier<Unknown>* contiguousInt32() { return indexingPayload<WriteBarrier<Unknown> >(); } - double* contiguousDouble() { return indexingPayload<double>(); } WriteBarrier<Unknown>* contiguous() { return indexingPayload<WriteBarrier<Unknown> >(); } static Butterfly* fromContiguous(WriteBarrier<Unknown>* contiguous) { return reinterpret_cast<Butterfly*>(contiguous); } - static Butterfly* fromContiguous(double* contiguous) - { - return reinterpret_cast<Butterfly*>(contiguous); - } static ptrdiff_t offsetOfPropertyStorage() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); } static int indexOfPropertyStorage() diff --git a/Source/JavaScriptCore/runtime/ButterflyInlines.h b/Source/JavaScriptCore/runtime/ButterflyInlineMethods.h index 9167497a4..86a836bef 100644 --- a/Source/JavaScriptCore/runtime/ButterflyInlines.h +++ b/Source/JavaScriptCore/runtime/ButterflyInlineMethods.h @@ -23,12 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ButterflyInlines_h -#define ButterflyInlines_h +#ifndef ButterflyInlineMethods_h +#define ButterflyInlineMethods_h #include "ArrayStorage.h" #include "Butterfly.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" #include "CopyVisitor.h" #include "JSGlobalData.h" #include "Structure.h" @@ -61,9 +61,8 @@ inline Butterfly* Butterfly::create(JSGlobalData& globalData, Structure* structu inline Butterfly* Butterfly::createUninitializedDuringCollection(CopyVisitor& visitor, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) { - size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); Butterfly* result = fromBase( - visitor.allocateNewSpace(size), + visitor.allocateNewSpace(totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes)), preCapacity, propertyCapacity); return result; } @@ -176,5 +175,5 @@ inline Butterfly* Butterfly::shift(Structure* structure, size_t numberOfSlots) } // namespace JSC -#endif // ButterflyInlines_h +#endif // ButterflyInlineMethods_h diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp index 068919528..4de760e49 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.cpp +++ b/Source/JavaScriptCore/runtime/CodeCache.cpp @@ -36,6 +36,7 @@ namespace JSC { CodeCache::CodeCache() + : m_randomGenerator(static_cast<uint32_t>(randomNumber() * UINT32_MAX)) { } @@ -66,9 +67,9 @@ UnlinkedCodeBlockType* CodeCache::getCodeBlock(JSGlobalData& globalData, Executa CodeBlockKey key = makeCodeBlockKey(source, CacheTypes<UnlinkedCodeBlockType>::codeType, strictness); bool storeInCache = false; if (debuggerMode == DebuggerOff && profilerMode == ProfilerOff) { - const Strong<UnlinkedCodeBlock>* result = m_cachedCodeBlocks.find(key); - if (result) { - UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(result->get()); + CodeBlockIndicesMap::iterator result = m_cachedCodeBlockIndices.find(key); + if (result != m_cachedCodeBlockIndices.end()) { + UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(m_cachedCodeBlocks[result->value].second.get()); unsigned firstLine = source.firstLine() + unlinkedCode->firstLine(); executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount()); return unlinkedCode; @@ -90,8 +91,14 @@ UnlinkedCodeBlockType* CodeCache::getCodeBlock(JSGlobalData& globalData, Executa if (error.m_type != ParserError::ErrorNone) return 0; - if (storeInCache) - m_cachedCodeBlocks.add(key, Strong<UnlinkedCodeBlock>(globalData, unlinkedCode)); + if (storeInCache) { + size_t index = m_randomGenerator.getUint32() % kMaxCodeBlockEntries; + if (m_cachedCodeBlocks[index].second) + m_cachedCodeBlockIndices.remove(m_cachedCodeBlocks[index].first); + m_cachedCodeBlockIndices.set(key, index); + m_cachedCodeBlocks[index].second.set(globalData, unlinkedCode); + m_cachedCodeBlocks[index].first = key; + } return unlinkedCode; } @@ -126,7 +133,6 @@ UnlinkedFunctionCodeBlock* CodeCache::generateFunctionCodeBlock(JSGlobalData& gl body->destroyData(); if (error.m_type != ParserError::ErrorNone) return 0; - m_cachedFunctionCode.add(result, Strong<UnlinkedFunctionCodeBlock>(globalData, result)); return result; } @@ -143,9 +149,9 @@ CodeCache::GlobalFunctionKey CodeCache::makeGlobalFunctionKey(const SourceCode& UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, ParserError& error) { GlobalFunctionKey key = makeGlobalFunctionKey(source, name.string()); - const Strong<UnlinkedFunctionExecutable>* result = m_cachedGlobalFunctions.find(key); - if (result) - return result->get(); + GlobalFunctionIndicesMap::iterator result = m_cachedGlobalFunctionIndices.find(key); + if (result != m_cachedGlobalFunctionIndices.end()) + return m_cachedGlobalFunctions[result->value].second.get(); RefPtr<ProgramNode> program = parse<ProgramNode>(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); if (!program) { @@ -167,13 +173,14 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlo UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&globalData, source, body); functionExecutable->m_nameValue.set(globalData, functionExecutable, jsString(&globalData, name.string())); - m_cachedGlobalFunctions.add(key, Strong<UnlinkedFunctionExecutable>(globalData, functionExecutable)); - return functionExecutable; -} + size_t index = m_randomGenerator.getUint32() % kMaxGlobalFunctionEntries; + if (m_cachedGlobalFunctions[index].second) + m_cachedGlobalFunctionIndices.remove(m_cachedGlobalFunctions[index].first); + m_cachedGlobalFunctionIndices.set(key, index); + m_cachedGlobalFunctions[index].second.set(globalData, functionExecutable); + m_cachedGlobalFunctions[index].first = key; -void CodeCache::usedFunctionCode(JSGlobalData& globalData, UnlinkedFunctionCodeBlock* codeBlock) -{ - m_cachedFunctionCode.add(codeBlock, Strong<UnlinkedFunctionCodeBlock>(globalData, codeBlock)); + return functionExecutable; } } diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h index 740aaa6df..4d4617189 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.h +++ b/Source/JavaScriptCore/runtime/CodeCache.h @@ -34,7 +34,6 @@ #include <wtf/FixedArray.h> #include <wtf/Forward.h> #include <wtf/PassOwnPtr.h> -#include <wtf/RandomNumber.h> #include <wtf/text/WTFString.h> namespace JSC { @@ -52,41 +51,6 @@ struct ParserError; class SourceCode; class SourceProvider; -template <typename KeyType, typename EntryType, int CacheSize> class Thingy { - typedef typename HashMap<KeyType, unsigned>::iterator iterator; -public: - Thingy() - : m_randomGenerator((static_cast<uint32_t>(randomNumber() * UINT32_MAX))) - { - } - const EntryType* find(const KeyType& key) - { - iterator result = m_map.find(key); - if (result == m_map.end()) - return 0; - return &m_data[result->value].second; - } - void add(const KeyType& key, const EntryType& value) - { - iterator result = m_map.find(key); - if (result != m_map.end()) { - m_data[result->value].second = value; - return; - } - size_t newIndex = m_randomGenerator.getUint32() % CacheSize; - if (m_data[newIndex].second) - m_map.remove(m_data[newIndex].first); - m_map.add(key, newIndex); - m_data[newIndex].first = key; - m_data[newIndex].second = value; - ASSERT(m_map.size() <= CacheSize); - } -private: - HashMap<KeyType, unsigned> m_map; - FixedArray<std::pair<KeyType, EntryType>, CacheSize> m_data; - WeakRandom m_randomGenerator; -}; - class CodeCache { public: static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); } @@ -95,12 +59,13 @@ public: UnlinkedEvalCodeBlock* getEvalCodeBlock(JSGlobalData&, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&); UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&); - void usedFunctionCode(JSGlobalData&, UnlinkedFunctionCodeBlock*); ~CodeCache(); enum CodeType { EvalType, ProgramType, FunctionType }; typedef std::pair<String, unsigned> CodeBlockKey; + typedef HashMap<CodeBlockKey, unsigned> CodeBlockIndicesMap; typedef std::pair<String, String> GlobalFunctionKey; + typedef HashMap<GlobalFunctionKey, unsigned> GlobalFunctionIndicesMap; private: CodeCache(); @@ -109,17 +74,18 @@ private: template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&); CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness); + CodeBlockIndicesMap m_cachedCodeBlockIndices; GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&); + GlobalFunctionIndicesMap m_cachedGlobalFunctionIndices; enum { kMaxCodeBlockEntries = 1024, - kMaxGlobalFunctionEntries = 1024, - kMaxFunctionCodeBlocks = 1024 + kMaxGlobalFunctionEntries = 1024 }; - Thingy<CodeBlockKey, Strong<UnlinkedCodeBlock>, kMaxCodeBlockEntries> m_cachedCodeBlocks; - Thingy<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions; - Thingy<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_cachedFunctionCode; + FixedArray<std::pair<CodeBlockKey, Strong<UnlinkedCodeBlock> >, kMaxCodeBlockEntries> m_cachedCodeBlocks; + FixedArray<std::pair<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable> >, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions; + WeakRandom m_randomGenerator; }; } diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 49a0e256d..20a2e2acb 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -620,17 +620,18 @@ void FunctionExecutable::clearCodeIfNotCompiling() clearCode(); } -void FunctionExecutable::clearUnlinkedCodeForRecompilationIfNotCompiling() +void FunctionExecutable::clearUnlinkedCodeIfNotCompiling() { if (isCompiling()) return; - m_unlinkedExecutable->clearCodeForRecompilation(); + m_unlinkedExecutable->clearCode(); } void FunctionExecutable::clearCode() { m_codeBlockForCall.clear(); m_codeBlockForConstruct.clear(); + m_unlinkedExecutable->clearCode(); Base::clearCode(); } diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 98471b85b..74b4add75 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -704,7 +704,7 @@ namespace JSC { SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); } void clearCodeIfNotCompiling(); - void clearUnlinkedCodeForRecompilationIfNotCompiling(); + void clearUnlinkedCodeIfNotCompiling(); static void visitChildren(JSCell*, SlotVisitor&); static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index 8e4390b1b..a4b2202c1 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -186,7 +186,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec) // Let A be a new (possibly empty) internal list of all of the argument values provided after thisArg (arg1, arg2 etc), in order. size_t numBoundArgs = exec->argumentCount() > 1 ? exec->argumentCount() - 1 : 0; - JSArray* boundArgs = JSArray::tryCreateUninitialized(exec->globalData(), globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), numBoundArgs); + JSArray* boundArgs = JSArray::tryCreateUninitialized(exec->globalData(), globalObject->arrayStructure(), numBoundArgs); if (!boundArgs) return JSValue::encode(throwOutOfMemoryError(exec)); diff --git a/Source/JavaScriptCore/runtime/IndexingHeaderInlines.h b/Source/JavaScriptCore/runtime/IndexingHeaderInlineMethods.h index cfad1c8c2..22785ce24 100644 --- a/Source/JavaScriptCore/runtime/IndexingHeaderInlines.h +++ b/Source/JavaScriptCore/runtime/IndexingHeaderInlineMethods.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef IndexingHeaderInlines_h -#define IndexingHeaderInlines_h +#ifndef IndexingHeaderInlineMethods_h +#define IndexingHeaderInlineMethods_h #include "ArrayStorage.h" #include "IndexingHeader.h" @@ -43,9 +43,6 @@ inline size_t IndexingHeader::preCapacity(Structure* structure) inline size_t IndexingHeader::indexingPayloadSizeInBytes(Structure* structure) { switch (structure->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return vectorLength() * sizeof(EncodedJSValue); @@ -60,5 +57,5 @@ inline size_t IndexingHeader::indexingPayloadSizeInBytes(Structure* structure) } // namespace JSC -#endif // IndexingHeaderInlines_h +#endif // IndexingHeaderInlineMethods_h diff --git a/Source/JavaScriptCore/runtime/IndexingType.cpp b/Source/JavaScriptCore/runtime/IndexingType.cpp index dc2733ad1..7261847a2 100644 --- a/Source/JavaScriptCore/runtime/IndexingType.cpp +++ b/Source/JavaScriptCore/runtime/IndexingType.cpp @@ -31,46 +31,6 @@ namespace JSC { -IndexingType leastUpperBoundOfIndexingTypes(IndexingType a, IndexingType b) -{ - // It doesn't make sense to LUB something that is an array with something that isn't. - ASSERT((a & IsArray) == (b & IsArray)); - - // Boy, this sure is easy right now. - return std::max(a, b); -} - -IndexingType leastUpperBoundOfIndexingTypeAndType(IndexingType indexingType, SpeculatedType type) -{ - if (!type) - return indexingType; - switch (indexingType) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - if (isInt32Speculation(type)) - return (indexingType & ~IndexingShapeMask) | Int32Shape; - if (isNumberSpeculation(type)) - return (indexingType & ~IndexingShapeMask) | DoubleShape; - return (indexingType & ~IndexingShapeMask) | ContiguousShape; - case ALL_DOUBLE_INDEXING_TYPES: - if (isNumberSpeculation(type)) - return indexingType; - return (indexingType & ~IndexingShapeMask) | ContiguousShape; - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return indexingType; - default: - CRASH(); - return 0; - } -} - -IndexingType leastUpperBoundOfIndexingTypeAndValue(IndexingType indexingType, JSValue value) -{ - return leastUpperBoundOfIndexingTypeAndType(indexingType, speculationFromValue(value)); -} - const char* indexingTypeToString(IndexingType indexingType) { static char result[128]; @@ -79,12 +39,6 @@ const char* indexingTypeToString(IndexingType indexingType) case NonArray: basicName = "NonArray"; break; - case NonArrayWithInt32: - basicName = "NonArrayWithInt32"; - break; - case NonArrayWithDouble: - basicName = "NonArrayWithDouble"; - break; case NonArrayWithContiguous: basicName = "NonArrayWithContiguous"; break; @@ -97,15 +51,6 @@ const char* indexingTypeToString(IndexingType indexingType) case ArrayClass: basicName = "ArrayClass"; break; - case ArrayWithUndecided: - basicName = "ArrayWithUndecided"; - break; - case ArrayWithInt32: - basicName = "ArrayWithInt32"; - break; - case ArrayWithDouble: - basicName = "ArrayWithDouble"; - break; case ArrayWithContiguous: basicName = "ArrayWithContiguous"; break; diff --git a/Source/JavaScriptCore/runtime/IndexingType.h b/Source/JavaScriptCore/runtime/IndexingType.h index ab253be1e..4bbe3cfa0 100644 --- a/Source/JavaScriptCore/runtime/IndexingType.h +++ b/Source/JavaScriptCore/runtime/IndexingType.h @@ -26,7 +26,6 @@ #ifndef IndexingType_h #define IndexingType_h -#include "SpeculatedType.h" #include <wtf/StdLibExtras.h> namespace JSC { @@ -38,32 +37,21 @@ static const IndexingType IsArray = 1; // The shape of the indexed property storage. static const IndexingType IndexingShapeMask = 30; -static const IndexingType NoIndexingShape = 0; -static const IndexingType UndecidedShape = 2; // Only useful for arrays. -static const IndexingType Int32Shape = 20; -static const IndexingType DoubleShape = 22; +static const IndexingType NoIndexingShape = 0; static const IndexingType ContiguousShape = 26; static const IndexingType ArrayStorageShape = 28; static const IndexingType SlowPutArrayStorageShape = 30; -static const IndexingType IndexingShapeShift = 1; -static const IndexingType NumberOfIndexingShapes = 16; - // Additional flags for tracking the history of the type. These are usually // masked off unless you ask for them directly. static const IndexingType MayHaveIndexedAccessors = 32; // List of acceptable array types. static const IndexingType NonArray = 0; -static const IndexingType NonArrayWithInt32 = Int32Shape; -static const IndexingType NonArrayWithDouble = DoubleShape; static const IndexingType NonArrayWithContiguous = ContiguousShape; static const IndexingType NonArrayWithArrayStorage = ArrayStorageShape; static const IndexingType NonArrayWithSlowPutArrayStorage = SlowPutArrayStorageShape; static const IndexingType ArrayClass = IsArray; // I'd want to call this "Array" but this would lead to disastrous namespace pollution. -static const IndexingType ArrayWithUndecided = IsArray | UndecidedShape; -static const IndexingType ArrayWithInt32 = IsArray | Int32Shape; -static const IndexingType ArrayWithDouble = IsArray | DoubleShape; static const IndexingType ArrayWithContiguous = IsArray | ContiguousShape; static const IndexingType ArrayWithArrayStorage = IsArray | ArrayStorageShape; static const IndexingType ArrayWithSlowPutArrayStorage = IsArray | SlowPutArrayStorageShape; @@ -72,17 +60,6 @@ static const IndexingType ArrayWithSlowPutArrayStorage = IsArray | SlowPutArr NonArray: \ case ArrayClass -#define ALL_UNDECIDED_INDEXING_TYPES \ - ArrayWithUndecided - -#define ALL_INT32_INDEXING_TYPES \ - NonArrayWithInt32: \ - case ArrayWithInt32 - -#define ALL_DOUBLE_INDEXING_TYPES \ - NonArrayWithDouble: \ - case ArrayWithDouble - #define ALL_CONTIGUOUS_INDEXING_TYPES \ NonArrayWithContiguous: \ case ArrayWithContiguous @@ -106,21 +83,6 @@ static inline bool hasIndexingHeader(IndexingType type) return hasIndexedProperties(type); } -static inline bool hasUndecided(IndexingType indexingType) -{ - return (indexingType & IndexingShapeMask) == UndecidedShape; -} - -static inline bool hasInt32(IndexingType indexingType) -{ - return (indexingType & IndexingShapeMask) == Int32Shape; -} - -static inline bool hasDouble(IndexingType indexingType) -{ - return (indexingType & IndexingShapeMask) == DoubleShape; -} - static inline bool hasContiguous(IndexingType indexingType) { return (indexingType & IndexingShapeMask) == ContiguousShape; @@ -143,12 +105,6 @@ static inline bool shouldUseSlowPut(IndexingType indexingType) return (indexingType & IndexingShapeMask) == SlowPutArrayStorageShape; } -// Return an indexing type that can handle all of the elements of both indexing types. -IndexingType leastUpperBoundOfIndexingTypes(IndexingType, IndexingType); - -IndexingType leastUpperBoundOfIndexingTypeAndType(IndexingType, SpeculatedType); -IndexingType leastUpperBoundOfIndexingTypeAndValue(IndexingType, JSValue); - const char* indexingTypeToString(IndexingType); // Mask of all possible types. diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index b8f5621af..fc6336463 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -30,7 +30,7 @@ #define JSActivation_h #include "CodeBlock.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" #include "JSVariableObject.h" #include "Nodes.h" #include "SymbolTable.h" diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 4ba5cc2bd..d1ece1a36 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -24,14 +24,14 @@ #include "JSArray.h" #include "ArrayPrototype.h" -#include "ButterflyInlines.h" -#include "CachedCall.h" +#include "ButterflyInlineMethods.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" +#include "CachedCall.h" #include "Error.h" #include "Executable.h" #include "GetterSetter.h" -#include "IndexingHeaderInlines.h" +#include "IndexingHeaderInlineMethods.h" #include "PropertyNameArray.h" #include "Reject.h" #include <wtf/AVLTree.h> @@ -410,33 +410,25 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException exec, newLength, throwException, convertContiguousToArrayStorage(exec->globalData())); } - createInitialUndecided(exec->globalData(), newLength); + createInitialContiguous(exec->globalData(), newLength); return true; - case ArrayWithUndecided: - case ArrayWithInt32: - case ArrayWithDouble: case ArrayWithContiguous: if (newLength == m_butterfly->publicLength()) return true; if (newLength >= MAX_ARRAY_INDEX // This case ensures that we can do fast push. || (newLength >= MIN_SPARSE_ARRAY_INDEX - && !isDenseEnoughForVector(newLength, countElements()))) { + && !isDenseEnoughForVector(newLength, countElementsInContiguous(m_butterfly)))) { return setLengthWithArrayStorage( exec, newLength, throwException, - ensureArrayStorage(exec->globalData())); + convertContiguousToArrayStorage(exec->globalData())); } if (newLength > m_butterfly->publicLength()) { - ensureLength(exec->globalData(), newLength); + ensureContiguousLength(exec->globalData(), newLength); return true; } - if (structure()->indexingType() == ArrayWithDouble) { - for (unsigned i = m_butterfly->publicLength(); i-- > newLength;) - m_butterfly->contiguousDouble()[i] = QNaN; - } else { - for (unsigned i = m_butterfly->publicLength(); i-- > newLength;) - m_butterfly->contiguous()[i].clear(); - } + for (unsigned i = m_butterfly->publicLength(); i-- > newLength;) + m_butterfly->contiguous()[i].clear(); m_butterfly->setPublicLength(newLength); return true; @@ -456,13 +448,6 @@ JSValue JSArray::pop(ExecState* exec) case ArrayClass: return jsUndefined(); - case ArrayWithUndecided: - if (!m_butterfly->publicLength()) - return jsUndefined(); - // We have nothing but holes. So, drop down to the slow version. - break; - - case ArrayWithInt32: case ArrayWithContiguous: { unsigned length = m_butterfly->publicLength(); @@ -479,22 +464,6 @@ JSValue JSArray::pop(ExecState* exec) break; } - case ArrayWithDouble: { - unsigned length = m_butterfly->publicLength(); - - if (!length--) - return jsUndefined(); - - ASSERT(length < m_butterfly->vectorLength()); - double value = m_butterfly->contiguousDouble()[length]; - if (value == value) { - m_butterfly->contiguousDouble()[length] = QNaN; - m_butterfly->setPublicLength(length); - return JSValue(JSValue::EncodeAsDouble, value); - } - break; - } - case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); @@ -549,42 +518,10 @@ void JSArray::push(ExecState* exec, JSValue value) { switch (structure()->indexingType()) { case ArrayClass: { - createInitialUndecided(exec->globalData(), 0); - // Fall through. - } - - case ArrayWithUndecided: { - convertUndecidedForValue(exec->globalData(), value); - push(exec, value); - return; + putByIndexBeyondVectorLengthWithArrayStorage(exec, 0, value, true, createInitialArrayStorage(exec->globalData())); + break; } - case ArrayWithInt32: { - if (!value.isInt32()) { - convertInt32ForValue(exec->globalData(), value); - push(exec, value); - return; - } - - unsigned length = m_butterfly->publicLength(); - ASSERT(length <= m_butterfly->vectorLength()); - if (length < m_butterfly->vectorLength()) { - m_butterfly->contiguousInt32()[length].setWithoutWriteBarrier(value); - m_butterfly->setPublicLength(length + 1); - return; - } - - if (length > MAX_ARRAY_INDEX) { - methodTable()->putByIndex(this, exec, length, value, true); - if (!exec->hadException()) - throwError(exec, createRangeError(exec, "Invalid array length")); - return; - } - - putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value); - return; - } - case ArrayWithContiguous: { unsigned length = m_butterfly->publicLength(); ASSERT(length <= m_butterfly->vectorLength()); @@ -601,42 +538,10 @@ void JSArray::push(ExecState* exec, JSValue value) return; } - putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value); + putByIndexBeyondVectorLengthContiguousWithoutAttributes(exec, length, value); return; } - case ArrayWithDouble: { - if (!value.isNumber()) { - convertDoubleToContiguous(exec->globalData()); - push(exec, value); - return; - } - double valueAsDouble = value.asNumber(); - if (valueAsDouble != valueAsDouble) { - convertDoubleToContiguous(exec->globalData()); - push(exec, value); - return; - } - - unsigned length = m_butterfly->publicLength(); - ASSERT(length <= m_butterfly->vectorLength()); - if (length < m_butterfly->vectorLength()) { - m_butterfly->contiguousDouble()[length] = valueAsDouble; - m_butterfly->setPublicLength(length + 1); - return; - } - - if (length > MAX_ARRAY_INDEX) { - methodTable()->putByIndex(this, exec, length, value, true); - if (!exec->hadException()) - throwError(exec, createRangeError(exec, "Invalid array length")); - return; - } - - putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value); - break; - } - case ArrayWithSlowPutArrayStorage: { unsigned oldLength = length(); if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true)) { @@ -742,11 +647,6 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex case ArrayClass: return true; - case ArrayWithUndecided: - // Don't handle this because it's confusing and it shouldn't come up. - return false; - - case ArrayWithInt32: case ArrayWithContiguous: { unsigned oldLength = m_butterfly->publicLength(); ASSERT(count <= oldLength); @@ -754,7 +654,7 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex // We may have to walk the entire array to do the shift. We're willing to do // so only if it's not horribly slow. if (oldLength - (startIndex + count) >= MIN_SPARSE_ARRAY_INDEX) - return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData())); + return shiftCountWithArrayStorage(startIndex, count, convertContiguousToArrayStorage(exec->globalData())); unsigned end = oldLength - count; for (unsigned i = startIndex; i < end; ++i) { @@ -768,7 +668,7 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex // about holes (at least for now), but it can detect them quickly. So // we convert to array storage and then allow the array storage path to // figure it out. - return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData())); + return shiftCountWithArrayStorage(startIndex, count, convertContiguousToArrayStorage(exec->globalData())); } // No need for a barrier since we're just moving data around in the same vector. // This is in line with our standing assumption that we won't have a deletion @@ -782,41 +682,6 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex return true; } - case ArrayWithDouble: { - unsigned oldLength = m_butterfly->publicLength(); - ASSERT(count <= oldLength); - - // We may have to walk the entire array to do the shift. We're willing to do - // so only if it's not horribly slow. - if (oldLength - (startIndex + count) >= MIN_SPARSE_ARRAY_INDEX) - return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData())); - - unsigned end = oldLength - count; - for (unsigned i = startIndex; i < end; ++i) { - // Storing to a hole is fine since we're still having a good time. But reading - // from a hole is totally not fine, since we might have to read from the proto - // chain. - double v = m_butterfly->contiguousDouble()[i + count]; - if (UNLIKELY(v != v)) { - // The purpose of this path is to ensure that we don't make the same - // mistake in the future: shiftCountWithArrayStorage() can't do anything - // about holes (at least for now), but it can detect them quickly. So - // we convert to array storage and then allow the array storage path to - // figure it out. - return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData())); - } - // No need for a barrier since we're just moving data around in the same vector. - // This is in line with our standing assumption that we won't have a deletion - // barrier. - m_butterfly->contiguousDouble()[i] = v; - } - for (unsigned i = end; i < oldLength; ++i) - m_butterfly->contiguousDouble()[i] = QNaN; - - m_butterfly->setPublicLength(oldLength - count); - return true; - } - case ArrayWithArrayStorage: case ArrayWithSlowPutArrayStorage: return shiftCountWithArrayStorage(startIndex, count, arrayStorage()); @@ -875,25 +740,23 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd { switch (structure()->indexingType()) { case ArrayClass: - case ArrayWithUndecided: // We could handle this. But it shouldn't ever come up, so we won't. return false; - - case ArrayWithInt32: + case ArrayWithContiguous: { unsigned oldLength = m_butterfly->publicLength(); // We may have to walk the entire array to do the unshift. We're willing to do so // only if it's not horribly slow. if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX) - return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData())); + return unshiftCountWithArrayStorage(exec, startIndex, count, convertContiguousToArrayStorage(exec->globalData())); - ensureLength(exec->globalData(), oldLength + count); + ensureContiguousLength(exec->globalData(), oldLength + count); for (unsigned i = oldLength; i-- > startIndex;) { JSValue v = m_butterfly->contiguous()[i].get(); if (UNLIKELY(!v)) - return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData())); + return unshiftCountWithArrayStorage(exec, startIndex, count, convertContiguousToArrayStorage(exec->globalData())); m_butterfly->contiguous()[i + count].setWithoutWriteBarrier(v); } @@ -905,31 +768,6 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd return true; } - case ArrayWithDouble: { - unsigned oldLength = m_butterfly->publicLength(); - - // We may have to walk the entire array to do the unshift. We're willing to do so - // only if it's not horribly slow. - if (oldLength - startIndex >= MIN_SPARSE_ARRAY_INDEX) - return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData())); - - ensureLength(exec->globalData(), oldLength + count); - - for (unsigned i = oldLength; i-- > startIndex;) { - double v = m_butterfly->contiguousDouble()[i]; - if (UNLIKELY(v != v)) - return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData())); - m_butterfly->contiguousDouble()[i + count] = v; - } - - // NOTE: we're leaving being garbage in the part of the array that we shifted out - // of. This is fine because the caller is required to store over that area, and - // in contiguous mode storing into a hole is guaranteed to behave exactly the same - // as storing over an existing element. - - return true; - } - case ArrayWithArrayStorage: case ArrayWithSlowPutArrayStorage: return unshiftCountWithArrayStorage(exec, startIndex, count, arrayStorage()); @@ -940,20 +778,6 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd } } -static int compareNumbersForQSortWithInt32(const void* a, const void* b) -{ - int32_t ia = static_cast<const JSValue*>(a)->asInt32(); - int32_t ib = static_cast<const JSValue*>(b)->asInt32(); - return ia - ib; -} - -static int compareNumbersForQSortWithDouble(const void* a, const void* b) -{ - double da = *static_cast<const double*>(a); - double db = *static_cast<const double*>(b); - return (da > db) - (da < db); -} - static int compareNumbersForQSort(const void* a, const void* b) { double da = static_cast<const JSValue*>(a)->asNumber(); @@ -971,7 +795,7 @@ static int compareByStringPairForQSort(const void* a, const void* b) template<IndexingType indexingType> void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData) { - ASSERT(indexingType == ArrayWithInt32 || indexingType == ArrayWithDouble || indexingType == ArrayWithContiguous || indexingType == ArrayWithArrayStorage); + ASSERT(indexingType == ArrayWithContiguous || indexingType == ArrayWithArrayStorage); unsigned lengthNotIncludingUndefined; unsigned newRelevantLength; @@ -990,19 +814,11 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy return; bool allValuesAreNumbers = true; - switch (indexingType) { - case ArrayWithInt32: - case ArrayWithDouble: - break; - - default: - for (size_t i = 0; i < newRelevantLength; ++i) { - if (!data[i].isNumber()) { - allValuesAreNumbers = false; - break; - } + for (size_t i = 0; i < newRelevantLength; ++i) { + if (!data[i].isNumber()) { + allValuesAreNumbers = false; + break; } - break; } if (!allValuesAreNumbers) @@ -1011,23 +827,7 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy // For numeric comparison, which is fast, qsort is faster than mergesort. We // also don't require mergesort's stability, since there's no user visible // side-effect from swapping the order of equal primitive values. - int (*compare)(const void*, const void*); - switch (indexingType) { - case ArrayWithInt32: - compare = compareNumbersForQSortWithInt32; - break; - - case ArrayWithDouble: - compare = compareNumbersForQSortWithDouble; - ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(double)); - break; - - default: - compare = compareNumbersForQSort; - break; - } - - qsort(data, newRelevantLength, sizeof(WriteBarrier<Unknown>), compare); + qsort(data, newRelevantLength, sizeof(WriteBarrier<Unknown>), compareNumbersForQSort); return; } @@ -1039,14 +839,6 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal case ArrayClass: return; - case ArrayWithInt32: - sortNumericVector<ArrayWithInt32>(exec, compareFunction, callType, callData); - break; - - case ArrayWithDouble: - sortNumericVector<ArrayWithDouble>(exec, compareFunction, callType, callData); - break; - case ArrayWithContiguous: sortNumericVector<ArrayWithContiguous>(exec, compareFunction, callType, callData); return; @@ -1062,7 +854,7 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal } template<IndexingType indexingType> -void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevantLength) +void JSArray::sortCompactedVector(ExecState* exec, WriteBarrier<Unknown>* begin, unsigned relevantLength) { if (!relevantLength) return; @@ -1083,31 +875,11 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan Heap::heap(this)->pushTempSortVector(&values); bool isSortingPrimitiveValues = true; - switch (indexingType) { - case ArrayWithInt32: - for (size_t i = 0; i < relevantLength; i++) { - JSValue value = static_cast<WriteBarrier<Unknown>*>(begin)[i].get(); - ASSERT(value.isInt32()); - values[i].first = value; - } - break; - - case ArrayWithDouble: - for (size_t i = 0; i < relevantLength; i++) { - double value = static_cast<double*>(begin)[i]; - ASSERT(value == value); - values[i].first = JSValue(JSValue::EncodeAsDouble, value); - } - break; - - default: - for (size_t i = 0; i < relevantLength; i++) { - JSValue value = static_cast<WriteBarrier<Unknown>*>(begin)[i].get(); - ASSERT(!value.isUndefined()); - values[i].first = value; - isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive(); - } - break; + for (size_t i = 0; i < relevantLength; i++) { + JSValue value = begin[i].get(); + ASSERT(!value.isUndefined()); + values[i].first = value; + isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive(); } // FIXME: The following loop continues to call toString on subsequent values even after @@ -1138,10 +910,8 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan // If the toString function changed the length of the array or vector storage, // increase the length to handle the orignal number of actual values. switch (indexingType) { - case ArrayWithInt32: - case ArrayWithDouble: case ArrayWithContiguous: - ensureLength(globalData, relevantLength); + ensureContiguousLength(globalData, relevantLength); break; case ArrayWithArrayStorage: @@ -1157,12 +927,8 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan CRASH(); } - for (size_t i = 0; i < relevantLength; i++) { - if (indexingType == ArrayWithDouble) - static_cast<double*>(begin)[i] = values[i].first.asNumber(); - else - static_cast<WriteBarrier<Unknown>*>(begin)[i].set(globalData, this, values[i].first); - } + for (size_t i = 0; i < relevantLength; i++) + begin[i].set(globalData, this, values[i].first); Heap::heap(this)->popTempSortVector(&values); } @@ -1173,31 +939,8 @@ void JSArray::sort(ExecState* exec) switch (structure()->indexingType()) { case ArrayClass: - case ArrayWithUndecided: return; - case ArrayWithInt32: { - unsigned lengthNotIncludingUndefined; - unsigned newRelevantLength; - compactForSorting<ArrayWithInt32>( - lengthNotIncludingUndefined, newRelevantLength); - - sortCompactedVector<ArrayWithInt32>( - exec, m_butterfly->contiguousInt32(), lengthNotIncludingUndefined); - return; - } - - case ArrayWithDouble: { - unsigned lengthNotIncludingUndefined; - unsigned newRelevantLength; - compactForSorting<ArrayWithDouble>( - lengthNotIncludingUndefined, newRelevantLength); - - sortCompactedVector<ArrayWithDouble>( - exec, m_butterfly->contiguousDouble(), lengthNotIncludingUndefined); - return; - } - case ArrayWithContiguous: { unsigned lengthNotIncludingUndefined; unsigned newRelevantLength; @@ -1344,12 +1087,12 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call unsigned numDefined = 0; unsigned numUndefined = 0; - + // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. for (; numDefined < usedVectorLength; ++numDefined) { if (numDefined > m_butterfly->vectorLength()) break; - JSValue v = getHolyIndexQuickly(numDefined); + JSValue v = currentIndexingData()[numDefined].get(); if (!v || v.isUndefined()) break; tree.abstractor().m_nodes[numDefined].value = v; @@ -1358,7 +1101,7 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call for (unsigned i = numDefined; i < usedVectorLength; ++i) { if (i > m_butterfly->vectorLength()) break; - JSValue v = getHolyIndexQuickly(i); + JSValue v = currentIndexingData()[i].get(); if (v) { if (v.isUndefined()) ++numUndefined; @@ -1369,7 +1112,7 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call } } } - + unsigned newUsedVectorLength = numDefined + numUndefined; // The array size may have changed. Figure out the new bounds. @@ -1384,31 +1127,16 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call iter.start_iter_least(tree); JSGlobalData& globalData = exec->globalData(); for (unsigned i = 0; i < elementsToExtractThreshold; ++i) { - if (structure()->indexingType() == ArrayWithDouble) - butterfly()->contiguousDouble()[i] = tree.abstractor().m_nodes[*iter].value.asNumber(); - else - currentIndexingData()[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); + currentIndexingData()[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); ++iter; } // Put undefined values back in. - switch (structure()->indexingType()) { - case ArrayWithInt32: - case ArrayWithDouble: - ASSERT(elementsToExtractThreshold == undefinedElementsThreshold); - break; - - default: - for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i) - currentIndexingData()[i].setUndefined(); - } + for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i) + currentIndexingData()[i].setUndefined(); // Ensure that unused values in the vector are zeroed out. - for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i) { - if (structure()->indexingType() == ArrayWithDouble) - butterfly()->contiguousDouble()[i] = QNaN; - else - currentIndexingData()[i].clear(); - } + for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i) + currentIndexingData()[i].clear(); if (hasArrayStorage(structure()->indexingType())) arrayStorage()->m_numValuesInVector = newUsedVectorLength; @@ -1420,17 +1148,8 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, switch (structure()->indexingType()) { case ArrayClass: - case ArrayWithUndecided: return; - case ArrayWithInt32: - sortVector<ArrayWithInt32>(exec, compareFunction, callType, callData); - return; - - case ArrayWithDouble: - sortVector<ArrayWithDouble>(exec, compareFunction, callType, callData); - return; - case ArrayWithContiguous: sortVector<ArrayWithContiguous>(exec, compareFunction, callType, callData); return; @@ -1454,30 +1173,11 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) case ArrayClass: return; - case ArrayWithUndecided: { - vector = 0; - vectorEnd = 0; - break; - } - - case ArrayWithInt32: case ArrayWithContiguous: { vectorEnd = m_butterfly->publicLength(); vector = m_butterfly->contiguous(); break; } - - case ArrayWithDouble: { - vector = 0; - vectorEnd = 0; - for (; i < m_butterfly->publicLength(); ++i) { - double v = butterfly()->contiguousDouble()[i]; - if (v != v) - break; - args.append(JSValue(JSValue::EncodeAsDouble, v)); - } - break; - } case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); @@ -1516,31 +1216,12 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le case ArrayClass: return; - case ArrayWithUndecided: { - vector = 0; - vectorEnd = 0; - break; - } - - case ArrayWithInt32: case ArrayWithContiguous: { vector = m_butterfly->contiguous(); vectorEnd = m_butterfly->publicLength(); break; } - case ArrayWithDouble: { - vector = 0; - vectorEnd = 0; - for (; i < m_butterfly->publicLength(); ++i) { - double v = m_butterfly->contiguousDouble()[i]; - if (v != v) - break; - callFrame->setArgument(i, JSValue(JSValue::EncodeAsDouble, v)); - } - break; - } - case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); vector = storage->m_vector; @@ -1578,40 +1259,12 @@ void JSArray::compactForSorting(unsigned& numDefined, unsigned& newRelevantLengt unsigned numUndefined = 0; for (; numDefined < myRelevantLength; ++numDefined) { - if (indexingType == ArrayWithInt32) { - JSValue v = m_butterfly->contiguousInt32()[numDefined].get(); - if (!v) - break; - ASSERT(v.isInt32()); - continue; - } - if (indexingType == ArrayWithDouble) { - double v = m_butterfly->contiguousDouble()[numDefined]; - if (v != v) - break; - continue; - } JSValue v = indexingData<indexingType>()[numDefined].get(); if (!v || v.isUndefined()) break; } for (unsigned i = numDefined; i < myRelevantLength; ++i) { - if (indexingType == ArrayWithInt32) { - JSValue v = m_butterfly->contiguousInt32()[i].get(); - if (!v) - continue; - ASSERT(v.isInt32()); - m_butterfly->contiguousInt32()[numDefined++].setWithoutWriteBarrier(v); - continue; - } - if (indexingType == ArrayWithDouble) { - double v = m_butterfly->contiguousDouble()[i]; - if (v != v) - continue; - m_butterfly->contiguousDouble()[numDefined++] = v; - continue; - } JSValue v = indexingData<indexingType>()[i].get(); if (v) { if (v.isUndefined()) @@ -1626,23 +1279,10 @@ void JSArray::compactForSorting(unsigned& numDefined, unsigned& newRelevantLengt if (hasArrayStorage(indexingType)) ASSERT(!arrayStorage()->m_sparseMap); - switch (indexingType) { - case ArrayWithInt32: - case ArrayWithDouble: - ASSERT(numDefined == newRelevantLength); - break; - - default: - for (unsigned i = numDefined; i < newRelevantLength; ++i) - indexingData<indexingType>()[i].setUndefined(); - break; - } - for (unsigned i = newRelevantLength; i < myRelevantLength; ++i) { - if (indexingType == ArrayWithDouble) - m_butterfly->contiguousDouble()[i] = QNaN; - else - indexingData<indexingType>()[i].clear(); - } + for (unsigned i = numDefined; i < newRelevantLength; ++i) + indexingData<indexingType>()[i].setUndefined(); + for (unsigned i = newRelevantLength; i < myRelevantLength; ++i) + indexingData<indexingType>()[i].clear(); if (hasArrayStorage(indexingType)) arrayStorage()->m_numValuesInVector = newRelevantLength; diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index ea1ed9047..1d1e64173 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -22,7 +22,7 @@ #define JSArray_h #include "ArrayConventions.h" -#include "ButterflyInlines.h" +#include "ButterflyInlineMethods.h" #include "JSObject.h" namespace JSC { @@ -162,7 +162,7 @@ private: void sortNumericVector(ExecState*, JSValue compareFunction, CallType, const CallData&); template<IndexingType indexingType> - void sortCompactedVector(ExecState*, void* begin, unsigned relevantLength); + void sortCompactedVector(ExecState*, WriteBarrier<Unknown>* begin, unsigned relevantLength); template<IndexingType indexingType> void sortVector(ExecState*, JSValue compareFunction, CallType, const CallData&); @@ -174,14 +174,13 @@ private: void compactForSorting(unsigned& numDefined, unsigned& newRelevantLength); }; -inline Butterfly* createContiguousArrayButterfly(JSGlobalData& globalData, unsigned length, unsigned& vectorLength) +inline Butterfly* createContiguousArrayButterfly(JSGlobalData& globalData, unsigned length) { IndexingHeader header; - vectorLength = std::max(length, BASE_VECTOR_LEN); - header.setVectorLength(vectorLength); + header.setVectorLength(std::max(length, BASE_VECTOR_LEN)); header.setPublicLength(length); Butterfly* result = Butterfly::create( - globalData, 0, 0, true, header, vectorLength * sizeof(EncodedJSValue)); + globalData, 0, 0, true, header, header.vectorLength() * sizeof(EncodedJSValue)); return result; } @@ -201,23 +200,13 @@ Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData&, unsigned inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength) { Butterfly* butterfly; - if (LIKELY(!hasArrayStorage(structure->indexingType()))) { - ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); - unsigned vectorLength; - butterfly = createContiguousArrayButterfly(globalData, initialLength, vectorLength); + if (LIKELY(structure->indexingType() == ArrayWithContiguous)) { + butterfly = createContiguousArrayButterfly(globalData, initialLength); ASSERT(initialLength < MIN_SPARSE_ARRAY_INDEX); - if (hasDouble(structure->indexingType())) { - for (unsigned i = 0; i < vectorLength; ++i) - butterfly->contiguousDouble()[i] = QNaN; - } } else { ASSERT( structure->indexingType() == ArrayWithSlowPutArrayStorage - || structure->indexingType() == ArrayWithArrayStorage); + || (initialLength && structure->indexingType() == ArrayWithArrayStorage)); butterfly = createArrayButterfly(globalData, initialLength); } JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly); @@ -232,13 +221,8 @@ inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Struct return 0; Butterfly* butterfly; - if (LIKELY(!hasArrayStorage(structure->indexingType()))) { - ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); - + if (LIKELY(structure->indexingType() == ArrayWithContiguous)) { + void* temp; if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, vectorLength * sizeof(EncodedJSValue)), &temp)) return 0; diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index df31b8542..3b37613d1 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -28,9 +28,9 @@ #include "ConstructData.h" #include "Heap.h" #include "JSLock.h" -#include "JSValueInlines.h" +#include "JSValueInlineMethods.h" #include "SlotVisitor.h" -#include "SlotVisitorInlines.h" +#include "SlotVisitorInlineMethods.h" #include "TypedArrayDescriptor.h" #include "WriteBarrier.h" #include <wtf/Noncopyable.h> diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index a7c6c8c18..c466a2b04 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -230,16 +230,9 @@ void JSGlobalObject::reset(JSValue prototype) m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->globalData(), this, m_objectPrototype.get())); m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); - - m_originalArrayStructureForIndexingShape[UndecidedShape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithUndecided)); - m_originalArrayStructureForIndexingShape[Int32Shape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithInt32)); - m_originalArrayStructureForIndexingShape[DoubleShape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithDouble)); - m_originalArrayStructureForIndexingShape[ContiguousShape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithContiguous)); - m_originalArrayStructureForIndexingShape[ArrayStorageShape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithArrayStorage)); - m_originalArrayStructureForIndexingShape[SlowPutArrayStorageShape >> IndexingShapeShift].set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage)); - for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) - m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i]; - + m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithContiguous)); + m_arrayStructureWithArrayStorage.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithArrayStorage)); + m_arrayStructureForSlowPut.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage)); m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); @@ -367,9 +360,7 @@ inline bool hasBrokenIndexing(JSObject* object) { // This will change if we have more indexing types. IndexingType type = object->structure()->indexingType(); - // This could be made obviously more efficient, but isn't made so right now, because - // we expect this to be an unlikely slow path anyway. - return hasUndecided(type) || hasInt32(type) || hasDouble(type) || hasContiguous(type) || hasFastArrayStorage(type); + return hasContiguous(type) || hasFastArrayStorage(type); } void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell) @@ -421,8 +412,8 @@ void JSGlobalObject::haveABadTime(JSGlobalData& globalData) // Make sure that all JSArray allocations that load the appropriate structure from // this object now load a structure that uses SlowPut. - for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) - m_arrayStructureForIndexingShapeDuringAllocation[i].set(globalData, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage)); + m_arrayStructure.set(globalData, this, m_arrayStructureForSlowPut.get()); + m_arrayStructureWithArrayStorage.set(globalData, this, m_arrayStructureForSlowPut.get()); // Make sure that all objects that have indexed storage switch to the slow kind of // indexed storage. @@ -497,10 +488,9 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) visitor.append(&thisObject->m_activationStructure); visitor.append(&thisObject->m_nameScopeStructure); visitor.append(&thisObject->m_argumentsStructure); - for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) - visitor.append(&thisObject->m_originalArrayStructureForIndexingShape[i]); - for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) - visitor.append(&thisObject->m_arrayStructureForIndexingShapeDuringAllocation[i]); + visitor.append(&thisObject->m_arrayStructure); + visitor.append(&thisObject->m_arrayStructureWithArrayStorage); + visitor.append(&thisObject->m_arrayStructureForSlowPut); visitor.append(&thisObject->m_booleanObjectStructure); visitor.append(&thisObject->m_callbackConstructorStructure); visitor.append(&thisObject->m_callbackFunctionStructure); diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 121b71b72..3212363ab 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -22,7 +22,6 @@ #ifndef JSGlobalObject_h #define JSGlobalObject_h -#include "ArrayAllocationProfile.h" #include "JSArray.h" #include "JSGlobalData.h" #include "JSSegmentedVariableObject.h" @@ -131,12 +130,9 @@ namespace JSC { WriteBarrier<Structure> m_activationStructure; WriteBarrier<Structure> m_nameScopeStructure; WriteBarrier<Structure> m_argumentsStructure; - - // Lists the actual structures used for having these particular indexing shapes. - WriteBarrier<Structure> m_originalArrayStructureForIndexingShape[NumberOfIndexingShapes]; - // Lists the structures we should use during allocation for these particular indexing shapes. - WriteBarrier<Structure> m_arrayStructureForIndexingShapeDuringAllocation[NumberOfIndexingShapes]; - + WriteBarrier<Structure> m_arrayStructure; // This gets set to m_arrayStructureForSlowPut as soon as we decide to have a bad time. + WriteBarrier<Structure> m_arrayStructureWithArrayStorage; // This gets set to m_arrayStructureForSlowPut as soon as we decide to have a bad time. + WriteBarrier<Structure> m_arrayStructureForSlowPut; WriteBarrier<Structure> m_booleanObjectStructure; WriteBarrier<Structure> m_callbackConstructorStructure; WriteBarrier<Structure> m_callbackFunctionStructure; @@ -279,26 +275,14 @@ namespace JSC { Structure* activationStructure() const { return m_activationStructure.get(); } Structure* nameScopeStructure() const { return m_nameScopeStructure.get(); } Structure* argumentsStructure() const { return m_argumentsStructure.get(); } - Structure* originalArrayStructureForIndexingType(IndexingType indexingType) const - { - ASSERT(indexingType & IsArray); - return m_originalArrayStructureForIndexingShape[(indexingType & IndexingShapeMask) >> IndexingShapeShift].get(); - } - Structure* arrayStructureForIndexingTypeDuringAllocation(IndexingType indexingType) const - { - ASSERT(indexingType & IsArray); - return m_arrayStructureForIndexingShapeDuringAllocation[(indexingType & IndexingShapeMask) >> IndexingShapeShift].get(); - } - Structure* arrayStructureForProfileDuringAllocation(ArrayAllocationProfile* profile) const - { - return arrayStructureForIndexingTypeDuringAllocation(ArrayAllocationProfile::selectIndexingTypeFor(profile)); - } - + Structure* arrayStructure() const { return m_arrayStructure.get(); } + Structure* arrayStructureWithArrayStorage() const { return m_arrayStructureWithArrayStorage.get(); } + void* addressOfArrayStructure() { return &m_arrayStructure; } + void* addressOfArrayStructureWithArrayStorage() { return &m_arrayStructureWithArrayStorage; } bool isOriginalArrayStructure(Structure* structure) { - return originalArrayStructureForIndexingType(structure->indexingType() | IsArray) == structure; + return structure == m_arrayStructure.get() || structure == m_arrayStructureWithArrayStorage.get(); } - Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } @@ -513,34 +497,34 @@ namespace JSC { return constructEmptyObject(exec, exec->lexicalGlobalObject()); } - inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, unsigned initialLength = 0) + inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength = 0) { - return ArrayAllocationProfile::updateLastAllocationFor(profile, JSArray::create(exec->globalData(), initialLength >= MIN_SPARSE_ARRAY_INDEX ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : globalObject->arrayStructureForProfileDuringAllocation(profile), initialLength)); + return JSArray::create(exec->globalData(), initialLength >= MIN_SPARSE_ARRAY_INDEX ? globalObject->arrayStructureWithArrayStorage() : globalObject->arrayStructure(), initialLength); } - inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, unsigned initialLength = 0) + inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength = 0) { - return constructEmptyArray(exec, profile, exec->lexicalGlobalObject(), initialLength); + return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength); } - inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values) + inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values) { - return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values)); + return constructArray(exec, globalObject->arrayStructure(), values); } - inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values) + inline JSArray* constructArray(ExecState* exec, const ArgList& values) { - return constructArray(exec, profile, exec->lexicalGlobalObject(), values); + return constructArray(exec, exec->lexicalGlobalObject(), values); } - inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length) + inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length) { - return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values, length)); + return constructArray(exec, globalObject->arrayStructure(), values, length); } - inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length) + inline JSArray* constructArray(ExecState* exec, const JSValue* values, unsigned length) { - return constructArray(exec, profile, exec->lexicalGlobalObject(), values, length); + return constructArray(exec, exec->lexicalGlobalObject(), values, length); } class DynamicGlobalObjectScope { diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index a67896b1a..6a3fb84e4 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -24,14 +24,14 @@ #include "config.h" #include "JSObject.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "CopyVisitor.h" -#include "CopyVisitorInlines.h" +#include "CopyVisitorInlineMethods.h" #include "DatePrototype.h" #include "ErrorConstructor.h" #include "GetterSetter.h" -#include "IndexingHeaderInlines.h" +#include "IndexingHeaderInlineMethods.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Lookup.h" @@ -42,7 +42,7 @@ #include "PropertyDescriptor.h" #include "PropertyNameArray.h" #include "Reject.h" -#include "SlotVisitorInlines.h" +#include "SlotVisitorInlineMethods.h" #include <math.h> #include <wtf/Assertions.h> @@ -129,16 +129,7 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt size_t count; switch (structure->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: { - currentTarget = 0; - currentSource = 0; - count = 0; - break; - } - - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: { + case ALL_CONTIGUOUS_INDEXING_TYPES: { currentTarget = newButterfly->contiguous(); currentSource = butterfly->contiguous(); ASSERT(newButterfly->publicLength() <= newButterfly->vectorLength()); @@ -161,7 +152,8 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt break; } - memcpy(currentTarget, currentSource, count * sizeof(EncodedJSValue)); + while (count--) + (currentTarget++)->setWithoutWriteBarrier((currentSource++)->get()); } m_butterfly = newButterfly; @@ -280,10 +272,8 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned switch (thisObject->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: break; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (i >= butterfly->vectorLength()) @@ -298,20 +288,6 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned return false; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = thisObject->m_butterfly; - if (i >= butterfly->vectorLength()) - return false; - - double value = butterfly->contiguousDouble()[i]; - if (value == value) { - slot.setValue(JSValue(JSValue::EncodeAsDouble, value)); - return true; - } - - return false; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); if (i >= storage->length()) @@ -429,22 +405,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, case ALL_BLANK_INDEXING_TYPES: break; - case ALL_UNDECIDED_INDEXING_TYPES: { - thisObject->convertUndecidedForValue(exec->globalData(), value); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - - case ALL_INT32_INDEXING_TYPES: { - if (!value.isInt32()) { - thisObject->convertInt32ForValue(exec->globalData(), value); - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - // Fall through. - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (propertyName >= butterfly->vectorLength()) @@ -455,29 +415,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, return; } - case ALL_DOUBLE_INDEXING_TYPES: { - if (!value.isNumber()) { - thisObject->convertDoubleToContiguous(exec->globalData()); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - double valueAsDouble = value.asNumber(); - if (valueAsDouble != valueAsDouble) { - thisObject->convertDoubleToContiguous(exec->globalData()); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - Butterfly* butterfly = thisObject->m_butterfly; - if (propertyName >= butterfly->vectorLength()) - break; - butterfly->contiguousDouble()[propertyName] = valueAsDouble; - if (propertyName >= butterfly->publicLength()) - butterfly->setPublicLength(propertyName + 1); - return; - } - case NonArrayWithArrayStorage: case ArrayWithArrayStorage: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); @@ -570,13 +507,10 @@ ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: // NOTE: this is horribly inefficient, as it will perform two conversions. We could optimize // this case if we ever cared. - enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, ensureArrayStorageSlow(globalData)); + enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); break; case ALL_ARRAY_STORAGE_INDEXING_TYPES: enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); @@ -600,7 +534,7 @@ void JSObject::notifyPresenceOfIndexedAccessors(JSGlobalData& globalData) globalObject()->haveABadTime(globalData); } -Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsigned length, size_t elementSize) +WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); IndexingType oldType = structure()->indexingType(); @@ -610,41 +544,9 @@ Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsig unsigned vectorLength = std::max(length, BASE_VECTOR_LEN); Butterfly* newButterfly = m_butterfly->growArrayRight( globalData, structure(), structure()->outOfLineCapacity(), false, 0, - elementSize * vectorLength); + sizeof(EncodedJSValue) * vectorLength); newButterfly->setPublicLength(length); newButterfly->setVectorLength(vectorLength); - return newButterfly; -} - -Butterfly* JSObject::createInitialUndecided(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateUndecided); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly; -} - -WriteBarrier<Unknown>* JSObject::createInitialInt32(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateInt32); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly->contiguousInt32(); -} - -double* JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(double)); - for (unsigned i = newButterfly->vectorLength(); i--;) - newButterfly->contiguousDouble()[i] = QNaN; - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateDouble); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous); setButterfly(globalData, newButterfly, newStructure); return newButterfly->contiguous(); @@ -675,33 +577,10 @@ ArrayStorage* JSObject::createInitialArrayStorage(JSGlobalData& globalData) return createArrayStorage(globalData, 0, BASE_VECTOR_LEN); } -WriteBarrier<Unknown>* JSObject::convertUndecidedToInt32(JSGlobalData& globalData) -{ - ASSERT(hasUndecided(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateInt32)); - return m_butterfly->contiguousInt32(); -} - -double* JSObject::convertUndecidedToDouble(JSGlobalData& globalData) +ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) { - ASSERT(hasUndecided(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) - m_butterfly->contiguousDouble()[i] = QNaN; + ASSERT(hasContiguous(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble)); - return m_butterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::convertUndecidedToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasUndecided(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSGlobalData& globalData, unsigned neededLength) -{ unsigned publicLength = m_butterfly->publicLength(); unsigned propertyCapacity = structure()->outOfLineCapacity(); unsigned propertySize = structure()->outOfLineSize(); @@ -720,141 +599,7 @@ ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSG newStorage->m_sparseMap.clear(); newStorage->m_indexBias = 0; newStorage->m_numValuesInVector = 0; - - return newStorage; -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasUndecided(structure()->indexingType())); - - ArrayStorage* storage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - // No need to copy elements. - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, storage->butterfly(), newStructure); - return storage; -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertUndecidedToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData) -{ - return convertUndecidedToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -double* JSObject::convertInt32ToDouble(JSGlobalData& globalData) -{ - ASSERT(hasInt32(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) { - WriteBarrier<Unknown>* current = &m_butterfly->contiguousInt32()[i]; - double* currentAsDouble = bitwise_cast<double*>(current); - JSValue v = current->get(); - if (!v) { - *currentAsDouble = QNaN; - continue; - } - ASSERT(v.isInt32()); - *currentAsDouble = v.asInt32(); - } - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble)); - return m_butterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::convertInt32ToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasInt32(structure()->indexingType())); - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasInt32(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { - JSValue v = m_butterfly->contiguous()[i].get(); - if (!v) - continue; - newStorage->m_vector[i].setWithoutWriteBarrier(v); - newStorage->m_numValuesInVector++; - } - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); - return newStorage; -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertInt32ToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData) -{ - return convertInt32ToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -WriteBarrier<Unknown>* JSObject::convertDoubleToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasDouble(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) { - double* current = &m_butterfly->contiguousDouble()[i]; - WriteBarrier<Unknown>* currentAsValue = bitwise_cast<WriteBarrier<Unknown>*>(current); - double value = *current; - if (value != value) { - currentAsValue->clear(); - continue; - } - currentAsValue->setWithoutWriteBarrier(JSValue(JSValue::EncodeAsDouble, value)); - } - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasDouble(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { - double value = m_butterfly->contiguousDouble()[i]; - if (value != value) - continue; - newStorage->m_vector[i].setWithoutWriteBarrier(JSValue(JSValue::EncodeAsDouble, value)); - newStorage->m_numValuesInVector++; - } - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); - return newStorage; -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertDoubleToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData) -{ - return convertDoubleToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasContiguous(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { + for (unsigned i = publicLength; i--;) { JSValue v = m_butterfly->contiguous()[i].get(); if (!v) continue; @@ -863,7 +608,7 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData } Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); + setButterfly(globalData, newButterfly, newStructure); return newStorage; } @@ -877,154 +622,48 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData return convertContiguousToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); } -void JSObject::convertUndecidedForValue(JSGlobalData& globalData, JSValue value) -{ - if (value.isInt32()) { - convertUndecidedToInt32(globalData); - return; - } - - if (value.isDouble()) { - convertUndecidedToDouble(globalData); - return; - } - - convertUndecidedToContiguous(globalData); -} - -void JSObject::convertInt32ForValue(JSGlobalData& globalData, JSValue value) -{ - ASSERT(!value.isInt32()); - - if (value.isDouble()) { - convertInt32ToDouble(globalData); - return; - } - - convertInt32ToContiguous(globalData); -} - -void JSObject::setIndexQuicklyToUndecided(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(index < m_butterfly->publicLength()); - ASSERT(index < m_butterfly->vectorLength()); - convertUndecidedForValue(globalData, value); - setIndexQuickly(globalData, index, value); -} - -void JSObject::convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(!value.isInt32()); - convertInt32ForValue(globalData, value); - setIndexQuickly(globalData, index, value); -} - -void JSObject::convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(!value.isNumber() || value.asNumber() != value.asNumber()); - convertDoubleToContiguous(globalData); - setIndexQuickly(globalData, index, value); -} - -WriteBarrier<Unknown>* JSObject::ensureInt32Slow(JSGlobalData& globalData) +WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) return 0; - return createInitialInt32(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToInt32(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + return createInitialContiguous(globalData, 0); default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } -double* JSObject::ensureDoubleSlow(JSGlobalData& globalData) +ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) - return 0; - return createInitialDouble(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToDouble(globalData); - - case ALL_INT32_INDEXING_TYPES: - return convertInt32ToDouble(globalData); - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + ASSERT(!indexingShouldBeSparse()); + ASSERT(!structure()->needsSlowPutIndexing()); + return convertContiguousToArrayStorage(globalData); - default: - CRASH(); - return 0; - } -} - -WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData) -{ - switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) - return 0; - return createInitialContiguous(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToContiguous(globalData); - - case ALL_INT32_INDEXING_TYPES: - return convertInt32ToContiguous(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - return convertDoubleToContiguous(globalData); - - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + if (UNLIKELY(indexingShouldBeSparse())) + return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData); + return createInitialArrayStorage(globalData); default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } -ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) +Butterfly* JSObject::ensureIndexedStorageSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: + if (UNLIKELY(structure()->needsSlowPutIndexing())) + return createInitialArrayStorage(globalData)->butterfly(); if (UNLIKELY(indexingShouldBeSparse())) - return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData); - return createInitialArrayStorage(globalData); - - case ALL_UNDECIDED_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertUndecidedToArrayStorage(globalData); - - case ALL_INT32_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertInt32ToArrayStorage(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertDoubleToArrayStorage(globalData); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertContiguousToArrayStorage(globalData); + return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData)->butterfly(); + return Butterfly::fromContiguous(createInitialContiguous(globalData, 0)); default: ASSERT_NOT_REACHED(); @@ -1035,6 +674,13 @@ ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { + case ALL_CONTIGUOUS_INDEXING_TYPES: + // FIXME: This could be made way more efficient, if we cared. + return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); + + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); + case ALL_BLANK_INDEXING_TYPES: { createArrayStorage(globalData, 0, 0); SparseArrayValueMap* map = allocateSparseIndexMap(globalData); @@ -1042,23 +688,8 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J return arrayStorage(); } - case ALL_UNDECIDED_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertUndecidedToArrayStorage(globalData)); - - case ALL_INT32_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertInt32ToArrayStorage(globalData)); - - case ALL_DOUBLE_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertDoubleToArrayStorage(globalData)); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); - - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); - default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } @@ -1066,21 +697,10 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: - convertUndecidedToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_INT32_INDEXING_TYPES: - convertInt32ToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_DOUBLE_INDEXING_TYPES: - convertDoubleToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_CONTIGUOUS_INDEXING_TYPES: { convertContiguousToArrayStorage(globalData, AllocateSlowPutArrayStorage); break; + } case NonArrayWithArrayStorage: case ArrayWithArrayStorage: { @@ -1090,7 +710,7 @@ void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData) } default: - CRASH(); + ASSERT_NOT_REACHED(); break; } } @@ -1257,10 +877,8 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) switch (thisObject->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return true; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (i >= butterfly->vectorLength()) @@ -1269,14 +887,6 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) return true; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = thisObject->m_butterfly; - if (i >= butterfly->vectorLength()) - return true; - butterfly->contiguousDouble()[i] = QNaN; - return true; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); @@ -1448,10 +1058,8 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa // which almost certainly means a different structure for PropertyNameArray. switch (object->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: break; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = object->m_butterfly; unsigned usedLength = butterfly->publicLength(); @@ -1463,18 +1071,6 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa break; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = object->m_butterfly; - unsigned usedLength = butterfly->publicLength(); - for (unsigned i = 0; i < usedLength; ++i) { - double value = butterfly->contiguousDouble()[i]; - if (value != value) - continue; - propertyNames.add(Identifier::from(exec, i)); - } - break; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); @@ -1864,10 +1460,9 @@ bool JSObject::attemptToInterceptPutByIndexOnHole(ExecState* exec, unsigned i, J return asObject(prototypeValue)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, this, i, value, shouldThrow); } -template<IndexingType indexingShape> -void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, unsigned i, JSValue value) +void JSObject::putByIndexBeyondVectorLengthContiguousWithoutAttributes(ExecState* exec, unsigned i, JSValue value) { - ASSERT((structure()->indexingType() & IndexingShapeMask) == indexingShape); + ASSERT(hasContiguous(structure()->indexingType())); ASSERT(!indexingShouldBeSparse()); // For us to get here, the index is either greater than the public length, or greater than @@ -1878,9 +1473,9 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un if (i >= MAX_ARRAY_INDEX - 1 || (i >= MIN_SPARSE_ARRAY_INDEX - && !isDenseEnoughForVector(i, countElements<indexingShape>(m_butterfly)))) { + && !isDenseEnoughForVector(i, countElementsInContiguous(m_butterfly)))) { ASSERT(i <= MAX_ARRAY_INDEX); - ensureArrayStorageSlow(globalData); + convertContiguousToArrayStorage(globalData, AllocateArrayStorage); SparseArrayValueMap* map = allocateSparseIndexMap(globalData); map->putEntry(exec, this, i, value, false); ASSERT(i >= arrayStorage()->length()); @@ -1888,30 +1483,10 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un return; } - ensureLength(globalData, i + 1); + ensureContiguousLength(globalData, i + 1); ASSERT(i < m_butterfly->vectorLength()); - switch (indexingShape) { - case Int32Shape: - ASSERT(value.isInt32()); - m_butterfly->contiguousInt32()[i].setWithoutWriteBarrier(value); - break; - - case DoubleShape: { - ASSERT(value.isNumber()); - double valueAsDouble = value.asNumber(); - ASSERT(valueAsDouble == valueAsDouble); - m_butterfly->contiguousDouble()[i] = valueAsDouble; - break; - } - - case ContiguousShape: - m_butterfly->contiguous()[i].set(globalData, this, value); - break; - - default: - CRASH(); - } + m_butterfly->contiguous()[i].set(globalData, this, value); } void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, bool shouldThrow, ArrayStorage* storage) @@ -2017,23 +1592,8 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue break; } - case ALL_UNDECIDED_INDEXING_TYPES: { - CRASH(); - break; - } - - case ALL_INT32_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value); - break; - } - - case ALL_DOUBLE_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value); - break; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, i, value); + putByIndexBeyondVectorLengthContiguousWithoutAttributes(exec, i, value); break; } @@ -2164,49 +1724,12 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV return true; } - case ALL_UNDECIDED_INDEXING_TYPES: { - convertUndecidedForValue(exec->globalData(), value); - // Reloop. - return putDirectIndex(exec, i, value, attributes, mode); - } - - case ALL_INT32_INDEXING_TYPES: { - if (attributes & (ReadOnly | Accessor)) { - return putDirectIndexBeyondVectorLengthWithArrayStorage( - exec, i, value, attributes, mode, convertInt32ToArrayStorage(globalData)); - } - if (!value.isInt32()) { - convertInt32ForValue(globalData, value); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value); - return true; - } - - case ALL_DOUBLE_INDEXING_TYPES: { - if (attributes & (ReadOnly | Accessor)) { - return putDirectIndexBeyondVectorLengthWithArrayStorage( - exec, i, value, attributes, mode, convertDoubleToArrayStorage(globalData)); - } - if (!value.isNumber()) { - convertDoubleToContiguous(globalData); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - double valueAsDouble = value.asNumber(); - if (valueAsDouble != valueAsDouble) { - convertDoubleToContiguous(globalData); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value); - return true; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { if (attributes & (ReadOnly | Accessor)) { return putDirectIndexBeyondVectorLengthWithArrayStorage( exec, i, value, attributes, mode, convertContiguousToArrayStorage(globalData)); } - putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, i, value); + putByIndexBeyondVectorLengthContiguousWithoutAttributes(exec, i, value); return true; } @@ -2246,65 +1769,33 @@ ALWAYS_INLINE unsigned JSObject::getNewVectorLength(unsigned desiredLength) unsigned vectorLength; unsigned length; - if (hasIndexedProperties(structure()->indexingType())) { - vectorLength = m_butterfly->vectorLength(); - length = m_butterfly->publicLength(); - } else { + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: vectorLength = 0; length = 0; + break; + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + vectorLength = m_butterfly->vectorLength(); + length = m_butterfly->publicLength(); + break; + default: + CRASH(); + return 0; } - return getNewVectorLength(vectorLength, length, desiredLength); } -template<IndexingType indexingShape> -unsigned JSObject::countElements(Butterfly* butterfly) +unsigned JSObject::countElementsInContiguous(Butterfly* butterfly) { unsigned numValues = 0; for (unsigned i = butterfly->publicLength(); i--;) { - switch (indexingShape) { - case Int32Shape: - case ContiguousShape: - if (butterfly->contiguous()[i]) - numValues++; - break; - - case DoubleShape: { - double value = butterfly->contiguousDouble()[i]; - if (value == value) - numValues++; - break; - } - - default: - CRASH(); - } + if (butterfly->contiguous()[i]) + numValues++; } return numValues; } -unsigned JSObject::countElements() -{ - switch (structure()->indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - return 0; - - case ALL_INT32_INDEXING_TYPES: - return countElements<Int32Shape>(m_butterfly); - - case ALL_DOUBLE_INDEXING_TYPES: - return countElements<DoubleShape>(m_butterfly); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - return countElements<ContiguousShape>(m_butterfly); - - default: - CRASH(); - return 0; - } -} - bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength) { // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map @@ -2348,24 +1839,19 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength return true; } -void JSObject::ensureLengthSlow(JSGlobalData& globalData, unsigned length) +void JSObject::ensureContiguousLengthSlow(JSGlobalData& globalData, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); - ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType())); + ASSERT(hasContiguous(structure()->indexingType())); ASSERT(length > m_butterfly->vectorLength()); unsigned newVectorLength = std::min( length << 1, MAX_STORAGE_VECTOR_LENGTH); - unsigned oldVectorLength = m_butterfly->vectorLength(); m_butterfly = m_butterfly->growArrayRight( globalData, structure(), structure()->outOfLineCapacity(), true, - oldVectorLength * sizeof(EncodedJSValue), + m_butterfly->vectorLength() * sizeof(EncodedJSValue), newVectorLength * sizeof(EncodedJSValue)); - if (hasDouble(structure()->indexingType())) { - for (unsigned i = oldVectorLength; i < newVectorLength; ++i) - m_butterfly->contiguousDouble()[i] = QNaN; - } m_butterfly->setVectorLength(newVectorLength); } @@ -2395,10 +1881,8 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope switch (object->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return false; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = object->m_butterfly; if (i >= butterfly->vectorLength()) @@ -2410,17 +1894,6 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope return true; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = object->m_butterfly; - if (i >= butterfly->vectorLength()) - return false; - double value = butterfly->contiguousDouble()[i]; - if (value != value) - return false; - descriptor.setDescriptor(JSValue(JSValue::EncodeAsDouble, value), 0); - return true; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); if (i >= storage->length()) diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index f9ae73ed4..82455390f 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -151,16 +151,30 @@ public: unsigned getArrayLength() const { - if (!hasIndexedProperties(structure()->indexingType())) + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: return 0; - return m_butterfly->publicLength(); + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + return m_butterfly->publicLength(); + default: + ASSERT_NOT_REACHED(); + return 0; + } } unsigned getVectorLength() { - if (!hasIndexedProperties(structure()->indexingType())) + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: return 0; - return m_butterfly->vectorLength(); + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + return m_butterfly->vectorLength(); + default: + ASSERT_NOT_REACHED(); + return 0; + } } JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); @@ -200,19 +214,9 @@ public: { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return false; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return i < m_butterfly->vectorLength() && m_butterfly->contiguous()[i]; - case ALL_DOUBLE_INDEXING_TYPES: { - if (i >= m_butterfly->vectorLength()) - return false; - double value = m_butterfly->contiguousDouble()[i]; - if (value != value) - return false; - return true; - } case ALL_ARRAY_STORAGE_INDEXING_TYPES: return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i]; default: @@ -224,11 +228,8 @@ public: JSValue getIndexQuickly(unsigned i) { switch (structure()->indexingType()) { - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return m_butterfly->contiguous()[i].get(); - case ALL_DOUBLE_INDEXING_TYPES: - return JSValue(JSValue::EncodeAsDouble, m_butterfly->contiguousDouble()[i]); case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->m_vector[i].get(); default: @@ -242,19 +243,10 @@ public: switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: break; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: if (i < m_butterfly->publicLength()) return m_butterfly->contiguous()[i].get(); break; - case ALL_DOUBLE_INDEXING_TYPES: { - if (i >= m_butterfly->publicLength()) - break; - double result = m_butterfly->contiguousDouble()[i]; - if (result != result) - break; - return JSValue(JSValue::EncodeAsDouble, result); - } case ALL_ARRAY_STORAGE_INDEXING_TYPES: if (i < m_butterfly->arrayStorage()->vectorLength()) return m_butterfly->arrayStorage()->m_vector[i].get(); @@ -287,10 +279,7 @@ public: { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return false; - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: case NonArrayWithArrayStorage: case ArrayWithArrayStorage: @@ -309,10 +298,7 @@ public: { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return false; - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: case ALL_ARRAY_STORAGE_INDEXING_TYPES: return i < m_butterfly->vectorLength(); @@ -325,14 +311,6 @@ public: void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v) { switch (structure()->indexingType()) { - case ALL_INT32_INDEXING_TYPES: { - ASSERT(i < m_butterfly->vectorLength()); - if (!v.isInt32()) { - convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(globalData, i, v); - return; - } - // Fall through to contiguous case. - } case ALL_CONTIGUOUS_INDEXING_TYPES: { ASSERT(i < m_butterfly->vectorLength()); m_butterfly->contiguous()[i].set(globalData, this, v); @@ -340,22 +318,6 @@ public: m_butterfly->setPublicLength(i + 1); break; } - case ALL_DOUBLE_INDEXING_TYPES: { - ASSERT(i < m_butterfly->vectorLength()); - if (!v.isNumber()) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); - return; - } - double value = v.asNumber(); - if (value != value) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); - return; - } - m_butterfly->contiguousDouble()[i] = value; - if (i >= m_butterfly->publicLength()) - m_butterfly->setPublicLength(i + 1); - break; - } case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); WriteBarrier<Unknown>& x = storage->m_vector[i]; @@ -376,40 +338,12 @@ public: void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v) { switch (structure()->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: { - setIndexQuicklyToUndecided(globalData, i, v); - break; - } - case ALL_INT32_INDEXING_TYPES: { - ASSERT(i < m_butterfly->publicLength()); - ASSERT(i < m_butterfly->vectorLength()); - if (!v.isInt32()) { - convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(globalData, i, v); - break; - } - // Fall through. - } case ALL_CONTIGUOUS_INDEXING_TYPES: { ASSERT(i < m_butterfly->publicLength()); ASSERT(i < m_butterfly->vectorLength()); m_butterfly->contiguous()[i].set(globalData, this, v); break; } - case ALL_DOUBLE_INDEXING_TYPES: { - ASSERT(i < m_butterfly->publicLength()); - ASSERT(i < m_butterfly->vectorLength()); - if (!v.isNumber()) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); - return; - } - double value = v.asNumber(); - if (value != value) { - convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v); - return; - } - m_butterfly->contiguousDouble()[i] = value; - break; - } case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); ASSERT(i < storage->length()); @@ -426,9 +360,6 @@ public: { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return false; case ALL_ARRAY_STORAGE_INDEXING_TYPES: @@ -443,9 +374,6 @@ public: { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return false; case ALL_ARRAY_STORAGE_INDEXING_TYPES: @@ -643,30 +571,6 @@ public: // foo->attemptToInterceptPutByIndexOnHole(...); bool attemptToInterceptPutByIndexOnHoleForPrototype(ExecState*, JSValue thisValue, unsigned propertyName, JSValue, bool shouldThrow); - // Returns 0 if int32 storage cannot be created - either because - // indexing should be sparse, we're having a bad time, or because - // we already have a more general form of storage (double, - // contiguous, array storage). - WriteBarrier<Unknown>* ensureInt32(JSGlobalData& globalData) - { - if (LIKELY(hasInt32(structure()->indexingType()))) - return m_butterfly->contiguousInt32(); - - return ensureInt32Slow(globalData); - } - - // Returns 0 if double storage cannot be created - either because - // indexing should be sparse, we're having a bad time, or because - // we already have a more general form of storage (contiguous, - // or array storage). - double* ensureDouble(JSGlobalData& globalData) - { - if (LIKELY(hasDouble(structure()->indexingType()))) - return m_butterfly->contiguousDouble(); - - return ensureDoubleSlow(globalData); - } - // Returns 0 if contiguous storage cannot be created - either because // indexing should be sparse or because we're having a bad time. WriteBarrier<Unknown>* ensureContiguous(JSGlobalData& globalData) @@ -689,6 +593,14 @@ public: return ensureArrayStorageSlow(globalData); } + Butterfly* ensureIndexedStorage(JSGlobalData& globalData) + { + if (LIKELY(hasIndexedProperties(structure()->indexingType()))) + return m_butterfly; + + return ensureIndexedStorageSlow(globalData); + } + static size_t offsetOfInlineStorage(); static ptrdiff_t butterflyOffset() @@ -749,47 +661,19 @@ protected: return 0; } } - - Butterfly* createInitialUndecided(JSGlobalData&, unsigned length); - WriteBarrier<Unknown>* createInitialInt32(JSGlobalData&, unsigned length); - double* createInitialDouble(JSGlobalData&, unsigned length); - WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length); - - void convertUndecidedForValue(JSGlobalData&, JSValue); - void convertInt32ForValue(JSGlobalData&, JSValue); - + ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength); ArrayStorage* createInitialArrayStorage(JSGlobalData&); - - WriteBarrier<Unknown>* convertUndecidedToInt32(JSGlobalData&); - double* convertUndecidedToDouble(JSGlobalData&); - WriteBarrier<Unknown>* convertUndecidedToContiguous(JSGlobalData&); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&); - - double* convertInt32ToDouble(JSGlobalData&); - WriteBarrier<Unknown>* convertInt32ToContiguous(JSGlobalData&); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&); - - WriteBarrier<Unknown>* convertDoubleToContiguous(JSGlobalData&); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition); - ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&); - + WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length); ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength); ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition); ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&); - ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData&); bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException); - template<IndexingType indexingShape> - void putByIndexBeyondVectorLengthWithoutAttributes(ExecState*, unsigned propertyName, JSValue); + void putByIndexBeyondVectorLengthContiguousWithoutAttributes(ExecState*, unsigned propertyName, JSValue); void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*); bool increaseVectorLength(JSGlobalData&, unsigned newLength); @@ -803,33 +687,24 @@ protected: // Call this if you want setIndexQuickly to succeed and you're sure that // the array is contiguous. - void ensureLength(JSGlobalData& globalData, unsigned length) + void ensureContiguousLength(JSGlobalData& globalData, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); - ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType())); + ASSERT(hasContiguous(structure()->indexingType())); if (m_butterfly->vectorLength() < length) - ensureLengthSlow(globalData, length); + ensureContiguousLengthSlow(globalData, length); if (m_butterfly->publicLength() < length) m_butterfly->setPublicLength(length); } - template<IndexingType indexingShape> - unsigned countElements(Butterfly*); + unsigned countElementsInContiguous(Butterfly*); - // This is relevant to undecided, int32, double, and contiguous. - unsigned countElements(); - - // This strange method returns a pointer to the start of the indexed data - // as if it contained JSValues. But it won't always contain JSValues. - // Make sure you cast this to the appropriate type before using. template<IndexingType indexingType> WriteBarrier<Unknown>* indexingData() { switch (indexingType) { - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return m_butterfly->contiguous(); @@ -845,7 +720,6 @@ protected: WriteBarrier<Unknown>* currentIndexingData() { switch (structure()->indexingType()) { - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return m_butterfly->contiguous(); @@ -858,32 +732,10 @@ protected: } } - JSValue getHolyIndexQuickly(unsigned i) - { - switch (structure()->indexingType()) { - case ALL_INT32_INDEXING_TYPES: - case ALL_CONTIGUOUS_INDEXING_TYPES: - return m_butterfly->contiguous()[i].get(); - case ALL_DOUBLE_INDEXING_TYPES: { - double value = m_butterfly->contiguousDouble()[i]; - if (value == value) - return JSValue(JSValue::EncodeAsDouble, value); - return JSValue(); - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return m_butterfly->arrayStorage()->m_vector[i].get(); - default: - CRASH(); - return JSValue(); - } - } - template<IndexingType indexingType> unsigned relevantLength() { switch (indexingType) { - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return m_butterfly->publicLength(); @@ -901,8 +753,6 @@ protected: unsigned currentRelevantLength() { switch (structure()->indexingType()) { - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: return m_butterfly->publicLength(); @@ -928,8 +778,6 @@ private: void isObject(); void isString(); - Butterfly* createInitialIndexedStorage(JSGlobalData&, unsigned length, size_t elementSize); - ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData&, ArrayStorage*); template<PutMode> @@ -952,18 +800,11 @@ private: JS_EXPORT_PRIVATE bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&); - ArrayStorage* constructConvertedArrayStorageWithoutCopyingElements(JSGlobalData&, unsigned neededLength); - - JS_EXPORT_PRIVATE void setIndexQuicklyToUndecided(JSGlobalData&, unsigned index, JSValue); - JS_EXPORT_PRIVATE void convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(JSGlobalData&, unsigned index, JSValue); - JS_EXPORT_PRIVATE void convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData&, unsigned index, JSValue); - - void ensureLengthSlow(JSGlobalData&, unsigned length); + void ensureContiguousLengthSlow(JSGlobalData&, unsigned length); - WriteBarrier<Unknown>* ensureInt32Slow(JSGlobalData&); - double* ensureDoubleSlow(JSGlobalData&); WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&); ArrayStorage* ensureArrayStorageSlow(JSGlobalData&); + Butterfly* ensureIndexedStorageSlow(JSGlobalData&); protected: Butterfly* m_butterfly; diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index 8f245f98d..e7f8cad17 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -215,8 +215,8 @@ char* JSValue::description() const #endif } else if (isCell()) { snprintf( - description, size, "Cell: %p -> %p (%p: %s, %s)", - asCell(), isObject() ? asObject(*this)->butterfly() : 0, asCell()->structure(), asCell()->structure()->classInfo()->className, + description, size, "Cell: %p (%p: %s, %s)", + asCell(), asCell()->structure(), asCell()->structure()->classInfo()->className, indexingTypeToString(asCell()->structure()->indexingTypeIncludingHistory())); } else if (isTrue()) snprintf(description, size, "True"); diff --git a/Source/JavaScriptCore/runtime/JSValueInlines.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h index c5a42f67f..224982e9e 100644 --- a/Source/JavaScriptCore/runtime/JSValueInlines.h +++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef JSValueInlines_h -#define JSValueInlines_h +#ifndef JSValueInlineMethods_h +#define JSValueInlineMethods_h #include "JSValue.h" @@ -493,5 +493,4 @@ namespace JSC { } // namespace JSC -#endif // JSValueInlines_h - +#endif // JSValueInlineMethods_h diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp index bf27327bf..cd854417b 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.cpp +++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp @@ -27,8 +27,8 @@ #include "config.h" #include "LiteralParser.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "JSArray.h" #include "JSString.h" #include "Lexer.h" @@ -548,7 +548,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState) switch(state) { startParseArray: case StartParseArray: { - JSArray* array = constructEmptyArray(m_exec, 0); + JSArray* array = constructEmptyArray(m_exec); objectStack.append(array); // fallthrough } diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 7e74a914b..7df047d28 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -21,8 +21,8 @@ #include "config.h" #include "ObjectConstructor.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "Error.h" #include "ExceptionHelpers.h" #include "JSFunction.h" @@ -182,7 +182,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exe return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested property names of a value that is not an object."))); PropertyNameArray properties(exec); asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, IncludeDontEnumProperties); - JSArray* names = constructEmptyArray(exec, 0); + JSArray* names = constructEmptyArray(exec); size_t numProperties = properties.size(); for (size_t i = 0; i < numProperties; i++) names->push(exec, jsOwnedString(exec, properties[i].string())); @@ -196,7 +196,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec) return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested keys of a value that is not an object."))); PropertyNameArray properties(exec); asObject(exec->argument(0))->methodTable()->getOwnPropertyNames(asObject(exec->argument(0)), exec, properties, ExcludeDontEnumProperties); - JSArray* keys = constructEmptyArray(exec, 0); + JSArray* keys = constructEmptyArray(exec); size_t numProperties = properties.size(); for (size_t i = 0; i < numProperties; i++) keys->push(exec, jsOwnedString(exec, properties[i].string())); diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index ed14e895f..01df7e98c 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -26,7 +26,7 @@ #include "Interpreter.h" #include "JSProxy.h" #include "JSString.h" -#include "JSValueInlines.h" +#include "JSValueInlineMethods.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp index 19f3b81ad..ce9c2d2db 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "RegExpMatchesArray.h" -#include "ButterflyInlines.h" +#include "ButterflyInlineMethods.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 00dd1ed74..35de40912 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -21,8 +21,8 @@ #include "config.h" #include "RegExpObject.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "Error.h" #include "ExceptionHelpers.h" #include "JSArray.h" diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index 93009d806..5aafe8bb3 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -22,9 +22,9 @@ #include "config.h" #include "StringPrototype.h" -#include "ButterflyInlines.h" +#include "ButterflyInlineMethods.h" #include "CachedCall.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" #include "Error.h" #include "Executable.h" #include "JSGlobalObjectFunctions.h" @@ -870,7 +870,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) return JSValue::encode(jsNull()); } - return JSValue::encode(constructArray(exec, static_cast<ArrayAllocationProfile*>(0), list)); + return JSValue::encode(constructArray(exec, list)); } EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) @@ -973,7 +973,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // 3. Let A be a new array created as if by the expression new Array() // where Array is the standard built-in constructor with that name. - JSArray* result = constructEmptyArray(exec, 0); + JSArray* result = constructEmptyArray(exec); // 4. Let lengthA be 0. unsigned resultLength = 0; @@ -1388,10 +1388,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec) return throwVMTypeError(exec); String s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - String color = a0.toWTFString(exec); - color.replaceWithLiteral('"', """); - - return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", color, "\">", s, "</font>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec)->value(exec), "\">", s, "</font>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) @@ -1436,10 +1433,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) return JSValue::encode(jsNontrivialString(exec, impl)); } - String fontSize = a0.toWTFString(exec); - fontSize.replaceWithLiteral('"', """); - - return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", fontSize, "\">", s, "</font>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec)->value(exec), "\">", s, "</font>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec) @@ -1449,10 +1443,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec) return throwVMTypeError(exec); String s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - String anchor = a0.toWTFString(exec); - anchor.replaceWithLiteral('"', """); - - return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", anchor, "\">", s, "</a>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec)->value(exec), "\">", s, "</a>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) @@ -1462,8 +1453,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) return throwVMTypeError(exec); String s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - String linkText = a0.toWTFString(exec); - linkText.replaceWithLiteral('"', """); + String linkText = a0.toString(exec)->value(exec); unsigned linkTextSize = linkText.length(); unsigned stringSize = s.length(); diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index e930c022a..e733c7e23 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -543,13 +543,12 @@ Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure* unsigned attributes = toAttributes(transitionKind); IndexingType indexingType = newIndexingType(structure->indexingTypeIncludingHistory(), transitionKind); - if (JSGlobalObject* globalObject = structure->m_globalObject.get()) { - if (globalObject->isOriginalArrayStructure(structure)) { - Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType); - if (result->indexingTypeIncludingHistory() == indexingType) { - structure->notifyTransitionFromThisStructure(); - return result; - } + JSGlobalObject* globalObject = structure->globalObject(); + if (structure == globalObject->arrayStructure()) { + Structure* transition = globalObject->arrayStructureWithArrayStorage(); + if (transition->indexingTypeIncludingHistory() == indexingType) { + structure->notifyTransitionFromThisStructure(); + return transition; } } diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h index 5291ed540..3ab7b2014 100644 --- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h @@ -43,9 +43,6 @@ static const unsigned FirstInternalAttribute = 1 << 6; // Use for transitions th // Support for attributes used to indicate transitions not related to properties. // If any of these are used, the string portion of the key should be 0. enum NonPropertyTransition { - AllocateUndecided, - AllocateInt32, - AllocateDouble, AllocateContiguous, AllocateArrayStorage, AllocateSlowPutArrayStorage, @@ -61,23 +58,14 @@ inline unsigned toAttributes(NonPropertyTransition transition) inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition transition) { switch (transition) { - case AllocateUndecided: - ASSERT(!hasIndexedProperties(oldType)); - return oldType | UndecidedShape; - case AllocateInt32: - ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType)); - return (oldType & ~IndexingShapeMask) | Int32Shape; - case AllocateDouble: - ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType)); - return (oldType & ~IndexingShapeMask) | DoubleShape; case AllocateContiguous: - ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType)); - return (oldType & ~IndexingShapeMask) | ContiguousShape; + ASSERT(!hasIndexedProperties(oldType)); + return oldType | ContiguousShape; case AllocateArrayStorage: - ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType)); + ASSERT(!hasIndexedProperties(oldType) || hasContiguous(oldType)); return (oldType & ~IndexingShapeMask) | ArrayStorageShape; case AllocateSlowPutArrayStorage: - ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType) || hasContiguous(oldType)); + ASSERT(!hasIndexedProperties(oldType) || hasContiguous(oldType)); return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape; case SwitchToSlowPutArrayStorage: ASSERT(hasFastArrayStorage(oldType)); |