From d441d6f39bb846989d95bcf5caf387b42414718d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 13 Sep 2013 12:51:20 +0200 Subject: Import Qt5x2 branch of QtWebkit for Qt 5.2 Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen --- Source/JavaScriptCore/runtime/ArgList.cpp | 4 +- Source/JavaScriptCore/runtime/ArgList.h | 3 +- Source/JavaScriptCore/runtime/Arguments.cpp | 41 +- Source/JavaScriptCore/runtime/Arguments.h | 34 +- Source/JavaScriptCore/runtime/ArrayConstructor.cpp | 7 +- Source/JavaScriptCore/runtime/ArrayConstructor.h | 4 +- Source/JavaScriptCore/runtime/ArrayPrototype.cpp | 218 ++--- Source/JavaScriptCore/runtime/ArrayPrototype.h | 4 +- Source/JavaScriptCore/runtime/ArrayStorage.h | 6 +- .../runtime/BatchedTransitionOptimizer.h | 8 +- Source/JavaScriptCore/runtime/BigInteger.h | 2 +- .../JavaScriptCore/runtime/BooleanConstructor.cpp | 15 +- Source/JavaScriptCore/runtime/BooleanConstructor.h | 4 +- Source/JavaScriptCore/runtime/BooleanObject.cpp | 9 +- Source/JavaScriptCore/runtime/BooleanObject.h | 14 +- Source/JavaScriptCore/runtime/BooleanPrototype.cpp | 17 +- Source/JavaScriptCore/runtime/BooleanPrototype.h | 4 +- Source/JavaScriptCore/runtime/Butterfly.h | 68 +- Source/JavaScriptCore/runtime/ButterflyInlines.h | 51 +- .../runtime/CachedTranscendentalFunction.h | 2 +- Source/JavaScriptCore/runtime/CallData.cpp | 1 + Source/JavaScriptCore/runtime/CallData.h | 2 +- Source/JavaScriptCore/runtime/CodeCache.cpp | 143 ++-- Source/JavaScriptCore/runtime/CodeCache.h | 256 ++++-- .../JavaScriptCore/runtime/CommonIdentifiers.cpp | 12 +- Source/JavaScriptCore/runtime/CommonIdentifiers.h | 69 +- Source/JavaScriptCore/runtime/CommonSlowPaths.h | 4 +- Source/JavaScriptCore/runtime/Completion.cpp | 26 +- Source/JavaScriptCore/runtime/Completion.h | 7 +- Source/JavaScriptCore/runtime/ConstructData.cpp | 1 + Source/JavaScriptCore/runtime/ConstructData.h | 2 +- Source/JavaScriptCore/runtime/DateConstructor.cpp | 35 +- Source/JavaScriptCore/runtime/DateConstructor.h | 4 +- Source/JavaScriptCore/runtime/DateInstance.cpp | 24 +- Source/JavaScriptCore/runtime/DateInstance.h | 12 +- Source/JavaScriptCore/runtime/DatePrototype.cpp | 64 +- Source/JavaScriptCore/runtime/DatePrototype.h | 4 +- Source/JavaScriptCore/runtime/Error.cpp | 30 +- Source/JavaScriptCore/runtime/Error.h | 8 +- Source/JavaScriptCore/runtime/ErrorConstructor.cpp | 7 +- Source/JavaScriptCore/runtime/ErrorConstructor.h | 4 +- Source/JavaScriptCore/runtime/ErrorInstance.cpp | 5 +- Source/JavaScriptCore/runtime/ErrorInstance.h | 20 +- Source/JavaScriptCore/runtime/ErrorPrototype.cpp | 7 +- Source/JavaScriptCore/runtime/ErrorPrototype.h | 4 +- Source/JavaScriptCore/runtime/ExceptionHelpers.cpp | 93 ++- Source/JavaScriptCore/runtime/ExceptionHelpers.h | 53 +- Source/JavaScriptCore/runtime/Executable.cpp | 124 +-- Source/JavaScriptCore/runtime/Executable.h | 205 ++--- Source/JavaScriptCore/runtime/ExecutionHarness.h | 8 +- .../JavaScriptCore/runtime/FunctionConstructor.cpp | 9 +- .../JavaScriptCore/runtime/FunctionConstructor.h | 4 +- .../runtime/FunctionExecutableDump.cpp | 37 + .../runtime/FunctionExecutableDump.h | 49 ++ .../JavaScriptCore/runtime/FunctionPrototype.cpp | 17 +- Source/JavaScriptCore/runtime/FunctionPrototype.h | 4 +- .../JavaScriptCore/runtime/GCActivityCallback.cpp | 53 +- Source/JavaScriptCore/runtime/GCActivityCallback.h | 22 +- .../runtime/GCActivityCallbackBlackBerry.cpp | 12 +- Source/JavaScriptCore/runtime/GetterSetter.cpp | 1 + Source/JavaScriptCore/runtime/GetterSetter.h | 12 +- Source/JavaScriptCore/runtime/Identifier.cpp | 64 +- Source/JavaScriptCore/runtime/Identifier.h | 52 +- Source/JavaScriptCore/runtime/IndexingHeader.h | 32 +- Source/JavaScriptCore/runtime/IndexingType.cpp | 9 +- Source/JavaScriptCore/runtime/IndexingType.h | 25 +- Source/JavaScriptCore/runtime/InternalFunction.cpp | 15 +- Source/JavaScriptCore/runtime/InternalFunction.h | 6 +- Source/JavaScriptCore/runtime/Intrinsic.h | 2 + Source/JavaScriptCore/runtime/JSAPIValueWrapper.h | 12 +- Source/JavaScriptCore/runtime/JSActivation.cpp | 19 +- Source/JavaScriptCore/runtime/JSActivation.h | 30 +- Source/JavaScriptCore/runtime/JSArray.cpp | 185 ++--- Source/JavaScriptCore/runtime/JSArray.h | 70 +- Source/JavaScriptCore/runtime/JSBoundFunction.cpp | 10 +- Source/JavaScriptCore/runtime/JSBoundFunction.h | 4 +- Source/JavaScriptCore/runtime/JSCJSValue.cpp | 326 ++++++++ Source/JavaScriptCore/runtime/JSCJSValue.h | 499 ++++++++++++ Source/JavaScriptCore/runtime/JSCJSValueInlines.h | 810 +++++++++++++++++++ Source/JavaScriptCore/runtime/JSCell.cpp | 29 +- Source/JavaScriptCore/runtime/JSCell.h | 189 +---- Source/JavaScriptCore/runtime/JSCellInlines.h | 204 +++++ Source/JavaScriptCore/runtime/JSDateMath.cpp | 102 +-- .../JavaScriptCore/runtime/JSDestructibleObject.h | 39 + Source/JavaScriptCore/runtime/JSExportMacros.h | 2 +- Source/JavaScriptCore/runtime/JSFunction.cpp | 73 +- Source/JavaScriptCore/runtime/JSFunction.h | 66 +- Source/JavaScriptCore/runtime/JSFunctionInlines.h | 69 ++ Source/JavaScriptCore/runtime/JSGlobalData.cpp | 531 ------------ Source/JavaScriptCore/runtime/JSGlobalData.h | 506 ------------ Source/JavaScriptCore/runtime/JSGlobalObject.cpp | 311 ++++--- Source/JavaScriptCore/runtime/JSGlobalObject.h | 876 ++++++++++---------- .../runtime/JSGlobalObjectFunctions.cpp | 11 +- .../runtime/JSGlobalObjectFunctions.h | 58 +- Source/JavaScriptCore/runtime/JSLock.cpp | 54 +- Source/JavaScriptCore/runtime/JSLock.h | 29 +- Source/JavaScriptCore/runtime/JSNameScope.cpp | 3 +- Source/JavaScriptCore/runtime/JSNameScope.h | 8 +- Source/JavaScriptCore/runtime/JSNotAnObject.cpp | 2 +- Source/JavaScriptCore/runtime/JSNotAnObject.h | 8 +- Source/JavaScriptCore/runtime/JSONObject.cpp | 103 +-- Source/JavaScriptCore/runtime/JSONObject.h | 4 +- Source/JavaScriptCore/runtime/JSObject.cpp | 712 ++++++++-------- Source/JavaScriptCore/runtime/JSObject.h | 610 ++++++-------- .../runtime/JSPropertyNameIterator.cpp | 8 +- .../runtime/JSPropertyNameIterator.h | 29 +- Source/JavaScriptCore/runtime/JSProxy.cpp | 18 +- Source/JavaScriptCore/runtime/JSProxy.h | 28 +- Source/JavaScriptCore/runtime/JSScope.cpp | 23 +- Source/JavaScriptCore/runtime/JSScope.h | 20 +- .../runtime/JSSegmentedVariableObject.cpp | 2 + .../runtime/JSSegmentedVariableObject.h | 9 +- Source/JavaScriptCore/runtime/JSString.cpp | 12 +- Source/JavaScriptCore/runtime/JSString.h | 892 ++++++++++----------- Source/JavaScriptCore/runtime/JSStringBuilder.h | 4 +- Source/JavaScriptCore/runtime/JSStringJoiner.cpp | 22 +- Source/JavaScriptCore/runtime/JSStringJoiner.h | 13 +- .../JavaScriptCore/runtime/JSSymbolTableObject.cpp | 3 +- .../JavaScriptCore/runtime/JSSymbolTableObject.h | 22 +- Source/JavaScriptCore/runtime/JSTypeInfo.h | 3 + Source/JavaScriptCore/runtime/JSValue.cpp | 323 -------- Source/JavaScriptCore/runtime/JSValue.h | 497 ------------ Source/JavaScriptCore/runtime/JSValueInlines.h | 497 ------------ Source/JavaScriptCore/runtime/JSVariableObject.cpp | 2 + Source/JavaScriptCore/runtime/JSVariableObject.h | 5 +- Source/JavaScriptCore/runtime/JSWithScope.cpp | 2 + Source/JavaScriptCore/runtime/JSWithScope.h | 16 +- Source/JavaScriptCore/runtime/JSWrapperObject.cpp | 4 +- Source/JavaScriptCore/runtime/JSWrapperObject.h | 32 +- Source/JavaScriptCore/runtime/LiteralParser.cpp | 42 +- Source/JavaScriptCore/runtime/LiteralParser.h | 2 +- Source/JavaScriptCore/runtime/Lookup.cpp | 24 +- Source/JavaScriptCore/runtime/Lookup.h | 47 +- Source/JavaScriptCore/runtime/MathObject.cpp | 45 +- Source/JavaScriptCore/runtime/MathObject.h | 4 +- Source/JavaScriptCore/runtime/MemoryStatistics.cpp | 2 +- Source/JavaScriptCore/runtime/MemoryStatistics.h | 2 +- Source/JavaScriptCore/runtime/NameConstructor.cpp | 9 +- Source/JavaScriptCore/runtime/NameConstructor.h | 4 +- Source/JavaScriptCore/runtime/NameInstance.cpp | 7 +- Source/JavaScriptCore/runtime/NameInstance.h | 16 +- Source/JavaScriptCore/runtime/NamePrototype.cpp | 5 +- Source/JavaScriptCore/runtime/NamePrototype.h | 4 +- .../runtime/NativeErrorConstructor.cpp | 1 + .../runtime/NativeErrorConstructor.h | 12 +- .../runtime/NativeErrorPrototype.cpp | 7 +- .../JavaScriptCore/runtime/NumberConstructor.cpp | 11 +- Source/JavaScriptCore/runtime/NumberConstructor.h | 4 +- Source/JavaScriptCore/runtime/NumberObject.cpp | 13 +- Source/JavaScriptCore/runtime/NumberObject.h | 14 +- Source/JavaScriptCore/runtime/NumberPrototype.cpp | 38 +- Source/JavaScriptCore/runtime/NumberPrototype.h | 4 +- .../JavaScriptCore/runtime/ObjectConstructor.cpp | 50 +- Source/JavaScriptCore/runtime/ObjectConstructor.h | 30 +- Source/JavaScriptCore/runtime/ObjectPrototype.cpp | 59 +- Source/JavaScriptCore/runtime/ObjectPrototype.h | 17 +- Source/JavaScriptCore/runtime/Operations.cpp | 26 +- Source/JavaScriptCore/runtime/Operations.h | 526 +++++------- Source/JavaScriptCore/runtime/Options.cpp | 63 +- Source/JavaScriptCore/runtime/Options.h | 47 +- .../JavaScriptCore/runtime/PropertyDescriptor.cpp | 4 +- Source/JavaScriptCore/runtime/PropertyDescriptor.h | 2 +- .../JavaScriptCore/runtime/PropertyMapHashTable.h | 131 ++- Source/JavaScriptCore/runtime/PropertyNameArray.h | 12 +- Source/JavaScriptCore/runtime/PropertyOffset.h | 21 +- Source/JavaScriptCore/runtime/PropertySlot.cpp | 1 + Source/JavaScriptCore/runtime/PropertySlot.h | 2 +- Source/JavaScriptCore/runtime/PropertyTable.cpp | 146 ++++ Source/JavaScriptCore/runtime/Protect.h | 2 +- Source/JavaScriptCore/runtime/PrototypeMap.cpp | 75 ++ Source/JavaScriptCore/runtime/PrototypeMap.h | 65 ++ Source/JavaScriptCore/runtime/RegExp.cpp | 64 +- Source/JavaScriptCore/runtime/RegExp.h | 26 +- Source/JavaScriptCore/runtime/RegExpCache.cpp | 14 +- Source/JavaScriptCore/runtime/RegExpCache.h | 5 +- .../JavaScriptCore/runtime/RegExpCachedResult.cpp | 7 +- Source/JavaScriptCore/runtime/RegExpCachedResult.h | 12 +- .../JavaScriptCore/runtime/RegExpConstructor.cpp | 11 +- Source/JavaScriptCore/runtime/RegExpConstructor.h | 20 +- .../JavaScriptCore/runtime/RegExpMatchesArray.cpp | 23 +- Source/JavaScriptCore/runtime/RegExpMatchesArray.h | 8 +- Source/JavaScriptCore/runtime/RegExpObject.cpp | 13 +- Source/JavaScriptCore/runtime/RegExpObject.h | 12 +- Source/JavaScriptCore/runtime/RegExpPrototype.cpp | 7 +- Source/JavaScriptCore/runtime/RegExpPrototype.h | 4 +- Source/JavaScriptCore/runtime/SmallStrings.cpp | 32 +- Source/JavaScriptCore/runtime/SmallStrings.h | 27 +- .../JavaScriptCore/runtime/SparseArrayValueMap.cpp | 23 +- .../JavaScriptCore/runtime/SparseArrayValueMap.h | 8 +- .../runtime/StrictEvalActivation.cpp | 3 +- .../JavaScriptCore/runtime/StrictEvalActivation.h | 6 +- .../JavaScriptCore/runtime/StringConstructor.cpp | 12 +- Source/JavaScriptCore/runtime/StringConstructor.h | 6 +- Source/JavaScriptCore/runtime/StringObject.cpp | 13 +- Source/JavaScriptCore/runtime/StringObject.h | 16 +- Source/JavaScriptCore/runtime/StringPrototype.cpp | 159 ++-- Source/JavaScriptCore/runtime/StringPrototype.h | 19 +- .../runtime/StringRecursionChecker.cpp | 3 +- .../runtime/StringRecursionChecker.h | 10 +- Source/JavaScriptCore/runtime/Structure.cpp | 469 ++++++----- Source/JavaScriptCore/runtime/Structure.h | 843 +++++++++---------- Source/JavaScriptCore/runtime/StructureChain.cpp | 5 +- Source/JavaScriptCore/runtime/StructureChain.h | 16 +- Source/JavaScriptCore/runtime/StructureInlines.h | 226 ++++++ .../JavaScriptCore/runtime/StructureRareData.cpp | 83 ++ Source/JavaScriptCore/runtime/StructureRareData.h | 76 ++ .../runtime/StructureRareDataInlines.h | 60 ++ .../runtime/StructureTransitionTable.h | 22 +- Source/JavaScriptCore/runtime/SymbolTable.cpp | 4 +- Source/JavaScriptCore/runtime/SymbolTable.h | 661 ++++++++------- Source/JavaScriptCore/runtime/Terminator.h | 47 -- Source/JavaScriptCore/runtime/TimeoutChecker.cpp | 147 ---- Source/JavaScriptCore/runtime/TimeoutChecker.h | 74 -- Source/JavaScriptCore/runtime/Uint16WithFraction.h | 2 +- Source/JavaScriptCore/runtime/VM.cpp | 572 +++++++++++++ Source/JavaScriptCore/runtime/VM.h | 529 ++++++++++++ Source/JavaScriptCore/runtime/VMStackBounds.h | 71 ++ Source/JavaScriptCore/runtime/Watchdog.cpp | 199 +++++ Source/JavaScriptCore/runtime/Watchdog.h | 116 +++ Source/JavaScriptCore/runtime/WatchdogMac.cpp | 72 ++ Source/JavaScriptCore/runtime/WatchdogNone.cpp | 50 ++ Source/JavaScriptCore/runtime/WeakGCMap.h | 118 +-- Source/JavaScriptCore/runtime/WriteBarrier.h | 34 +- 223 files changed, 9780 insertions(+), 8099 deletions(-) create mode 100644 Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp create mode 100644 Source/JavaScriptCore/runtime/FunctionExecutableDump.h create mode 100644 Source/JavaScriptCore/runtime/JSCJSValue.cpp create mode 100644 Source/JavaScriptCore/runtime/JSCJSValue.h create mode 100644 Source/JavaScriptCore/runtime/JSCJSValueInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSCellInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSFunctionInlines.h delete mode 100644 Source/JavaScriptCore/runtime/JSGlobalData.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSGlobalData.h delete mode 100644 Source/JavaScriptCore/runtime/JSValue.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSValue.h delete mode 100644 Source/JavaScriptCore/runtime/JSValueInlines.h create mode 100644 Source/JavaScriptCore/runtime/PropertyTable.cpp create mode 100644 Source/JavaScriptCore/runtime/PrototypeMap.cpp create mode 100644 Source/JavaScriptCore/runtime/PrototypeMap.h create mode 100644 Source/JavaScriptCore/runtime/StructureInlines.h create mode 100644 Source/JavaScriptCore/runtime/StructureRareData.cpp create mode 100644 Source/JavaScriptCore/runtime/StructureRareData.h create mode 100644 Source/JavaScriptCore/runtime/StructureRareDataInlines.h delete mode 100644 Source/JavaScriptCore/runtime/Terminator.h delete mode 100644 Source/JavaScriptCore/runtime/TimeoutChecker.cpp delete mode 100644 Source/JavaScriptCore/runtime/TimeoutChecker.h create mode 100644 Source/JavaScriptCore/runtime/VM.cpp create mode 100644 Source/JavaScriptCore/runtime/VM.h create mode 100644 Source/JavaScriptCore/runtime/VMStackBounds.h create mode 100644 Source/JavaScriptCore/runtime/Watchdog.cpp create mode 100644 Source/JavaScriptCore/runtime/Watchdog.h create mode 100644 Source/JavaScriptCore/runtime/WatchdogMac.cpp create mode 100644 Source/JavaScriptCore/runtime/WatchdogNone.cpp (limited to 'Source/JavaScriptCore/runtime') diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp index 301abd530..74240418c 100644 --- a/Source/JavaScriptCore/runtime/ArgList.cpp +++ b/Source/JavaScriptCore/runtime/ArgList.cpp @@ -22,9 +22,9 @@ #include "ArgList.h" #include "HeapRootVisitor.h" -#include "JSValue.h" +#include "JSCJSValue.h" #include "JSObject.h" - +#include "Operations.h" using std::min; diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h index 1fb1ce911..84a0cdd8b 100644 --- a/Source/JavaScriptCore/runtime/ArgList.h +++ b/Source/JavaScriptCore/runtime/ArgList.h @@ -33,12 +33,11 @@ class SlotVisitor; class MarkedArgumentBuffer { WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer); - friend class JSGlobalData; + friend class VM; friend class ArgList; private: static const size_t inlineCapacity = 8; - typedef Vector VectorType; typedef HashSet ListSet; public: diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index ba73b2cf2..a188885e6 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -28,6 +28,7 @@ #include "JSActivation.h" #include "JSFunction.h" #include "JSGlobalObject.h" +#include "Operations.h" using namespace std; @@ -126,7 +127,7 @@ bool Arguments::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName p Arguments* thisObject = jsCast(cell); unsigned i = propertyName.asIndex(); if (JSValue value = thisObject->tryGetArgument(i)) { - ASSERT(i < PropertyName::NotAnIndex); + RELEASE_ASSERT(i < PropertyName::NotAnIndex); slot.setValue(value); return true; } @@ -155,7 +156,7 @@ bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prop Arguments* thisObject = jsCast(object); unsigned i = propertyName.asIndex(); if (JSValue value = thisObject->tryGetArgument(i)) { - ASSERT(i < PropertyName::NotAnIndex); + RELEASE_ASSERT(i < PropertyName::NotAnIndex); descriptor.setDescriptor(value, None); return true; } @@ -197,7 +198,7 @@ void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyN void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) { Arguments* thisObject = jsCast(cell); - if (thisObject->trySetArgument(exec->globalData(), i, value)) + if (thisObject->trySetArgument(exec->vm(), i, value)) return; PutPropertySlot slot(shouldThrow); @@ -208,19 +209,19 @@ void Arguments::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JS { Arguments* thisObject = jsCast(cell); unsigned i = propertyName.asIndex(); - if (thisObject->trySetArgument(exec->globalData(), i, value)) + if (thisObject->trySetArgument(exec->vm(), i, value)) return; if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { thisObject->m_overrodeLength = true; - thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); + thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { if (!thisObject->m_isStrictMode) { thisObject->m_overrodeCallee = true; - thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); + thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); return; } thisObject->createStrictModeCalleeIfNecessary(exec); @@ -246,13 +247,13 @@ bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) { - if (exec->globalData().isInDefineOwnProperty()) + if (exec->vm().isInDefineOwnProperty()) return Base::deleteProperty(cell, exec, propertyName); Arguments* thisObject = jsCast(cell); unsigned i = propertyName.asIndex(); if (i < thisObject->m_numArguments) { - ASSERT(i < PropertyName::NotAnIndex); + RELEASE_ASSERT(i < PropertyName::NotAnIndex); if (!Base::deleteProperty(cell, exec, propertyName)) return false; if (thisObject->tryDeleteArgument(i)) @@ -283,7 +284,7 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNam Arguments* thisObject = jsCast(object); unsigned i = propertyName.asIndex(); if (i < thisObject->m_numArguments) { - ASSERT(i < PropertyName::NotAnIndex); + RELEASE_ASSERT(i < PropertyName::NotAnIndex); // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. PropertySlot slot; if (!thisObject->isDeletedArgument(i) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) { @@ -305,7 +306,7 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNam // i. If Desc.[[Value]] is present, then // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. if (descriptor.value()) - thisObject->trySetArgument(exec->globalData(), i, descriptor.value()); + thisObject->trySetArgument(exec->vm(), i, descriptor.value()); // ii. If Desc.[[Writable]] is present and its value is false, then // 1. Call the [[Delete]] internal method of map passing P and false as arguments. if (descriptor.writablePresent() && !descriptor.writable()) @@ -316,10 +317,10 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNam } if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { - thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); + thisObject->putDirect(exec->vm(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); thisObject->m_overrodeLength = true; } else if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { - thisObject->putDirect(exec->globalData(), propertyName, thisObject->m_callee.get(), DontEnum); + thisObject->putDirect(exec->vm(), propertyName, thisObject->m_callee.get(), DontEnum); thisObject->m_overrodeCallee = true; } else if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); @@ -355,24 +356,24 @@ void Arguments::tearOff(CallFrame* callFrame) if (!callFrame->isInlineCallFrame()) { for (size_t i = 0; i < m_numArguments; ++i) - trySetArgument(callFrame->globalData(), i, callFrame->argumentAfterCapture(i)); + trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i)); return; } tearOffForInlineCallFrame( - callFrame->globalData(), callFrame->registers(), callFrame->inlineCallFrame()); + callFrame->vm(), callFrame->registers(), callFrame->inlineCallFrame()); } void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) { - ASSERT(activation); + RELEASE_ASSERT(activation); if (isTornOff()) return; if (!m_numArguments) return; - m_activation.set(exec->globalData(), this, activation); + m_activation.set(exec->vm(), this, activation); tearOff(exec); } @@ -388,11 +389,11 @@ void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); tearOffForInlineCallFrame( - callFrame->globalData(), callFrame->registers() + inlineCallFrame->stackOffset, + callFrame->vm(), callFrame->registers() + inlineCallFrame->stackOffset, inlineCallFrame); } -void Arguments::tearOffForInlineCallFrame(JSGlobalData& globalData, Register* registers, InlineCallFrame* inlineCallFrame) +void Arguments::tearOffForInlineCallFrame(VM& vm, Register* registers, InlineCallFrame* inlineCallFrame) { for (size_t i = 0; i < m_numArguments; ++i) { ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; @@ -427,10 +428,10 @@ void Arguments::tearOffForInlineCallFrame(JSGlobalData& globalData, Register* re value = recovery.constant(); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); break; } - trySetArgument(globalData, i, value); + trySetArgument(vm, i, value); } } diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 8ae991422..58ac782b6 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -40,16 +40,16 @@ class Arguments : public JSDestructibleObject { public: typedef JSDestructibleObject Base; - static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame) + static Arguments* create(VM& vm, CallFrame* callFrame) { - Arguments* arguments = new (NotNull, allocateCell(globalData.heap)) Arguments(callFrame); + Arguments* arguments = new (NotNull, allocateCell(vm.heap)) Arguments(callFrame); arguments->finishCreation(callFrame); return arguments; } - static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) + static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { - Arguments* arguments = new (NotNull, allocateCell(globalData.heap)) Arguments(callFrame); + Arguments* arguments = new (NotNull, allocateCell(vm.heap)) Arguments(callFrame); arguments->finishCreation(callFrame, inlineCallFrame); return arguments; } @@ -62,7 +62,7 @@ private: Arguments(CallFrame*); Arguments(CallFrame*, NoParametersType); - void tearOffForInlineCallFrame(JSGlobalData& globalData, Register*, InlineCallFrame*); + void tearOffForInlineCallFrame(VM& vm, Register*, InlineCallFrame*); public: static const ClassInfo s_info; @@ -84,9 +84,9 @@ public: bool isTornOff() const { return m_registerArray; } void didTearOffActivation(ExecState*, JSActivation*); - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: @@ -110,7 +110,7 @@ private: void createStrictModeCalleeIfNecessary(ExecState*); bool isArgument(size_t); - bool trySetArgument(JSGlobalData&, size_t argument, JSValue); + bool trySetArgument(VM&, size_t argument, JSValue); JSValue tryGetArgument(size_t argument); bool isDeletedArgument(size_t); bool tryDeleteArgument(size_t); @@ -148,12 +148,12 @@ inline Arguments* asArguments(JSValue value) } inline Arguments::Arguments(CallFrame* callFrame) - : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) + : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) { } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) - : JSDestructibleObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) + : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) { } @@ -177,11 +177,11 @@ inline bool Arguments::tryDeleteArgument(size_t argument) return true; } -inline bool Arguments::trySetArgument(JSGlobalData& globalData, size_t argument, JSValue value) +inline bool Arguments::trySetArgument(VM& vm, size_t argument, JSValue value) { if (!isArgument(argument)) return false; - this->argument(argument).set(globalData, this, value); + this->argument(argument).set(vm, this, value); return true; } @@ -227,13 +227,13 @@ inline WriteBarrierBase& Arguments::argument(size_t argument) inline void Arguments::finishCreation(CallFrame* callFrame) { - Base::finishCreation(callFrame->globalData()); + Base::finishCreation(callFrame->vm()); ASSERT(inherits(&s_info)); JSFunction* callee = jsCast(callFrame->callee()); m_numArguments = callFrame->argumentCount(); m_registers = reinterpret_cast*>(callFrame->registers()); - m_callee.set(callFrame->globalData(), this, callee); + m_callee.set(callFrame->vm(), this, callee); m_overrodeLength = false; m_overrodeCallee = false; m_overrodeCaller = false; @@ -256,13 +256,13 @@ inline void Arguments::finishCreation(CallFrame* callFrame) inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { - Base::finishCreation(callFrame->globalData()); + Base::finishCreation(callFrame->vm()); ASSERT(inherits(&s_info)); - JSFunction* callee = inlineCallFrame->callee.get(); + JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame); m_numArguments = inlineCallFrame->arguments.size() - 1; m_registers = reinterpret_cast*>(callFrame->registers()) + inlineCallFrame->stackOffset; - m_callee.set(callFrame->globalData(), this, callee); + m_callee.set(callFrame->vm(), this, callee); m_overrodeLength = false; m_overrodeCallee = false; m_overrodeCaller = false; diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index a3fce45f2..752055716 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -32,6 +32,7 @@ #include "JSArray.h" #include "JSFunction.h" #include "Lookup.h" +#include "Operations.h" namespace JSC { @@ -60,9 +61,9 @@ ArrayConstructor::ArrayConstructor(JSGlobalObject* globalObject, Structure* stru void ArrayConstructor::finishCreation(ExecState* exec, ArrayPrototype* arrayPrototype) { - Base::finishCreation(exec->globalData(), arrayPrototype->classInfo()->className); - putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); - putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + Base::finishCreation(exec->vm(), arrayPrototype->classInfo()->className); + putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); } bool ArrayConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot) diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h index f9f35c491..727475b47 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.h +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h @@ -42,9 +42,9 @@ public: static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index e6d37fb02..ba1c7b725 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved. * Copyright (C) 2003 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * @@ -28,6 +28,7 @@ #include "CachedCall.h" #include "CodeBlock.h" #include "CopiedSpaceInlines.h" +#include "Error.h" #include "Interpreter.h" #include "JIT.h" #include "JSStringBuilder.h" @@ -123,16 +124,16 @@ ArrayPrototype* ArrayPrototype::create(ExecState* exec, JSGlobalObject* globalOb // ECMA 15.4.4 ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure) - : JSArray(globalObject->globalData(), structure, 0) + : JSArray(globalObject->vm(), structure, 0) { } void ArrayPrototype::finishCreation(JSGlobalObject* globalObject) { - JSGlobalData& globalData = globalObject->globalData(); - Base::finishCreation(globalData); + VM& vm = globalObject->vm(); + Base::finishCreation(vm); ASSERT(inherits(&s_info)); - notifyUsedAsPrototype(globalData); + vm.prototypeMap.addPrototype(this); } bool ArrayPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) @@ -194,11 +195,11 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument template void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) { - ASSERT(currentCount > resultCount); + RELEASE_ASSERT(currentCount > resultCount); unsigned count = currentCount - resultCount; - ASSERT(header <= length); - ASSERT(currentCount <= (length - header)); + RELEASE_ASSERT(header <= length); + RELEASE_ASSERT(currentCount <= (length - header)); if (isJSArray(thisObj)) { JSArray* array = asArray(thisObj); @@ -232,11 +233,11 @@ void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned current template void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) { - ASSERT(resultCount > currentCount); + RELEASE_ASSERT(resultCount > currentCount); unsigned count = resultCount - currentCount; - ASSERT(header <= length); - ASSERT(currentCount <= (length - header)); + RELEASE_ASSERT(header <= length); + RELEASE_ASSERT(currentCount <= (length - header)); // Guard against overflow. if (count > (UINT_MAX - length)) { @@ -303,64 +304,27 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); - unsigned totalSize = length ? length - 1 : 0; - Vector, 256> strBuffer(length); - bool allStrings8Bit = true; - + String separator(",", String::ConstructFromLiteral); + JSStringJoiner stringJoiner(separator, length); for (unsigned k = 0; k < length; k++) { JSValue element; if (thisObj->canGetIndexQuickly(k)) element = thisObj->getIndexQuickly(k); - else + else { element = thisObj->get(exec, k); - - if (element.isUndefinedOrNull()) - continue; - - String str = element.toWTFString(exec); - strBuffer[k] = str.impl(); - totalSize += str.length(); - allStrings8Bit = allStrings8Bit && str.is8Bit(); - - if (!strBuffer.data()) { - throwOutOfMemoryError(exec); - } - - if (exec->hadException()) - break; - } - if (!totalSize) - return JSValue::encode(jsEmptyString(exec)); - - if (allStrings8Bit) { - Vector buffer; - buffer.reserveCapacity(totalSize); - if (!buffer.data()) - return JSValue::encode(throwOutOfMemoryError(exec)); - - for (unsigned i = 0; i < length; i++) { - if (i) - buffer.append(','); - if (RefPtr rep = strBuffer[i]) - buffer.append(rep->characters8(), rep->length()); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } - ASSERT(buffer.size() == totalSize); - return JSValue::encode(jsString(exec, String::adopt(buffer))); - } - Vector buffer; - buffer.reserveCapacity(totalSize); - if (!buffer.data()) - return JSValue::encode(throwOutOfMemoryError(exec)); - - for (unsigned i = 0; i < length; i++) { - if (i) - buffer.append(','); - if (RefPtr rep = strBuffer[i]) - buffer.append(rep->characters(), rep->length()); + if (element.isUndefinedOrNull()) + stringJoiner.append(String()); + else + stringJoiner.append(element.toWTFString(exec)); + + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } - ASSERT(buffer.size() == totalSize); - return JSValue::encode(jsString(exec, String::adopt(buffer))); + return JSValue::encode(stringJoiner.join(exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) @@ -403,7 +367,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) } } - return JSValue::encode(stringJoiner.build(exec)); + return JSValue::encode(stringJoiner.join(exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) @@ -449,7 +413,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) stringJoiner.append(String()); } - return JSValue::encode(stringJoiner.build(exec)); + return JSValue::encode(stringJoiner.join(exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) @@ -644,39 +608,36 @@ inline JSValue getOrHole(JSObject* obj, ExecState* exec, unsigned propertyName) return JSValue(); } -EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) +static bool attemptFastSort(ExecState* exec, JSObject* thisObj, JSValue function, CallData& callData, CallType& callType) { - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (!length || exec->hadException()) - return JSValue::encode(thisObj); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - - if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->hasSparseMap() && !shouldUseSlowPut(thisObj->structure()->indexingType())) { - if (isNumericCompareFunction(exec, callType, callData)) - asArray(thisObj)->sortNumeric(exec, function, callType, callData); - else if (callType != CallTypeNone) - asArray(thisObj)->sort(exec, function, callType, callData); - else - asArray(thisObj)->sort(exec); - return JSValue::encode(thisObj); - } + if (thisObj->classInfo() != &JSArray::s_info + || asArray(thisObj)->hasSparseMap() + || shouldUseSlowPut(thisObj->structure()->indexingType())) + return false; + + if (isNumericCompareFunction(exec, callType, callData)) + asArray(thisObj)->sortNumeric(exec, function, callType, callData); + else if (callType != CallTypeNone) + asArray(thisObj)->sort(exec, function, callType, callData); + else + asArray(thisObj)->sort(exec); + return true; +} +static bool performSlowSort(ExecState* exec, JSObject* thisObj, unsigned length, JSValue function, CallData& callData, CallType& callType) +{ // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { JSValue iObj = getOrHole(thisObj, exec, i); if (exec->hadException()) - return JSValue::encode(jsUndefined()); + return false; unsigned themin = i; JSValue minObj = iObj; for (unsigned j = i + 1; j < length; ++j) { JSValue jObj = getOrHole(thisObj, exec, j); if (exec->hadException()) - return JSValue::encode(jsUndefined()); + return false; double compareResult; if (!jObj) compareResult = 1; @@ -704,21 +665,94 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) if (minObj) { thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true); if (exec->hadException()) - return JSValue::encode(jsUndefined()); + return false; } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, i)) { throwTypeError(exec, "Unable to delete property."); - return JSValue::encode(jsUndefined()); + return false; } if (iObj) { thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true); if (exec->hadException()) - return JSValue::encode(jsUndefined()); + return false; } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, themin)) { throwTypeError(exec, "Unable to delete property."); - return JSValue::encode(jsUndefined()); + return false; } } } + return true; +} + +EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) +{ + JSObject* thisObj = exec->hostThisValue().toObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (!length || exec->hadException()) + return JSValue::encode(thisObj); + + JSValue function = exec->argument(0); + CallData callData; + CallType callType = getCallData(function, callData); + + if (attemptFastSort(exec, thisObj, function, callData, callType)) + return JSValue::encode(thisObj); + + // Assume that for small-ish arrays, doing the slow sort directly is better. + if (length < 1000) + return performSlowSort(exec, thisObj, length, function, callData, callType) ? JSValue::encode(thisObj) : JSValue::encode(jsUndefined()); + + JSGlobalObject* globalObject = JSGlobalObject::create( + exec->vm(), JSGlobalObject::createStructure(exec->vm(), jsNull())); + JSArray* flatArray = constructEmptyArray(globalObject->globalExec(), 0); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + PropertyNameArray nameArray(exec); + thisObj->methodTable()->getPropertyNames(thisObj, exec, nameArray, IncludeDontEnumProperties); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + Vector keys; + for (size_t i = 0; i < nameArray.size(); ++i) { + PropertyName name = nameArray[i]; + uint32_t index = name.asIndex(); + if (index == PropertyName::NotAnIndex) + continue; + + JSValue value = getOrHole(thisObj, exec, index); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (!value) + continue; + keys.append(index); + flatArray->push(exec, value); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + + if (!attemptFastSort(exec, flatArray, function, callData, callType) + && !performSlowSort(exec, flatArray, flatArray->length(), function, callData, callType)) + return JSValue::encode(jsUndefined()); + + for (size_t i = 0; i < keys.size(); ++i) { + size_t index = keys[i]; + if (index < flatArray->length()) + continue; + + if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, index)) { + throwTypeError(exec, "Unable to delete property."); + return JSValue::encode(jsUndefined()); + } + } + + for (size_t i = flatArray->length(); i--;) { + JSValue value = getOrHole(flatArray, exec, i); + RELEASE_ASSERT(value); + thisObj->methodTable()->putByIndex(thisObj, exec, i, value, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + return JSValue::encode(thisObj); } @@ -747,17 +781,17 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) deleteCount = static_cast(deleteDouble); } - JSArray* resObj = JSArray::tryCreateUninitialized(exec->globalData(), exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount); + JSArray* resObj = JSArray::tryCreateUninitialized(exec->vm(), exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount); if (!resObj) return JSValue::encode(throwOutOfMemoryError(exec)); JSValue result = resObj; - JSGlobalData& globalData = exec->globalData(); + VM& vm = exec->vm(); for (unsigned k = 0; k < deleteCount; k++) { JSValue v = getProperty(exec, thisObj, k + begin); if (exec->hadException()) return JSValue::encode(jsUndefined()); - resObj->initializeIndex(globalData, k, v); + resObj->initializeIndex(vm, k, v); } unsigned additionalArgs = std::max(exec->argumentCount() - 2, 0); @@ -1290,7 +1324,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) JSValue searchElement = exec->argument(0); do { - ASSERT(index < length); + RELEASE_ASSERT(index < length); JSValue e = getProperty(exec, thisObj, index); if (exec->hadException()) return JSValue::encode(jsUndefined()); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index c23bcdec1..37ba6eb7e 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -40,9 +40,9 @@ public: static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayClass); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayClass); } protected: diff --git a/Source/JavaScriptCore/runtime/ArrayStorage.h b/Source/JavaScriptCore/runtime/ArrayStorage.h index ffd84b281..a0287c921 100644 --- a/Source/JavaScriptCore/runtime/ArrayStorage.h +++ b/Source/JavaScriptCore/runtime/ArrayStorage.h @@ -49,7 +49,7 @@ private: ArrayStorage() { } // Not directly instantiable. Can only be created as part of a Butterfly. public: - static ArrayStorage* from(Butterfly* butterfly) { return reinterpret_cast(butterfly); } + static ArrayStorage* from(Butterfly* butterfly) { return reinterpret_cast_ptr(butterfly); } static ArrayStorage* from(IndexingHeader* indexingHeader) { return indexingHeader->arrayStorage(); } Butterfly* butterfly() { return reinterpret_cast(this); } @@ -72,7 +72,9 @@ public: { return m_sparseMap && m_sparseMap->sparseMode(); } - + + ContiguousJSValues vector() { return ContiguousJSValues(m_vector, vectorLength()); } + WriteBarrier m_sparseMap; unsigned m_indexBias; unsigned m_numValuesInVector; diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index 178bf3fe9..76def7138 100644 --- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -34,8 +34,8 @@ namespace JSC { class BatchedTransitionOptimizer { WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer); public: - BatchedTransitionOptimizer(JSGlobalData& globalData, JSObject* object) - : m_globalData(&globalData) + BatchedTransitionOptimizer(VM& vm, JSObject* object) + : m_vm(&vm) , m_object(object) { } @@ -43,11 +43,11 @@ public: ~BatchedTransitionOptimizer() { if (m_object->structure()->isDictionary()) - m_object->flattenDictionaryObject(*m_globalData); + m_object->flattenDictionaryObject(*m_vm); } private: - JSGlobalData* m_globalData; + VM* m_vm; JSObject* m_object; }; diff --git a/Source/JavaScriptCore/runtime/BigInteger.h b/Source/JavaScriptCore/runtime/BigInteger.h index 833829df6..0a0c477c2 100644 --- a/Source/JavaScriptCore/runtime/BigInteger.h +++ b/Source/JavaScriptCore/runtime/BigInteger.h @@ -35,7 +35,7 @@ class BigInteger { public: BigInteger(double number) { - ASSERT(isfinite(number) && !signbit(number)); + ASSERT(std::isfinite(number) && !std::signbit(number)); ASSERT(number == floor(number)); bool sign; diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 0485350ce..453983b7a 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -23,6 +23,7 @@ #include "BooleanPrototype.h" #include "JSGlobalObject.h" +#include "Operations.h" namespace JSC { @@ -37,18 +38,18 @@ BooleanConstructor::BooleanConstructor(JSGlobalObject* globalObject, Structure* void BooleanConstructor::finishCreation(ExecState* exec, BooleanPrototype* booleanPrototype) { - Base::finishCreation(exec->globalData(), booleanPrototype->classInfo()->className); - putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); + Base::finishCreation(exec->vm(), booleanPrototype->classInfo()->className); + putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); + putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); } // ECMA 15.6.2 JSObject* constructBoolean(ExecState* exec, const ArgList& args) { - BooleanObject* obj = BooleanObject::create(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); - obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); + BooleanObject* obj = BooleanObject::create(exec->vm(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); + obj->setInternalValue(exec->vm(), jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -78,8 +79,8 @@ CallType BooleanConstructor::getCallData(JSCell*, CallData& callData) JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue) { - BooleanObject* obj = BooleanObject::create(exec->globalData(), globalObject->booleanObjectStructure()); - obj->setInternalValue(exec->globalData(), immediateBooleanValue); + BooleanObject* obj = BooleanObject::create(exec->vm(), globalObject->booleanObjectStructure()); + obj->setInternalValue(exec->vm(), immediateBooleanValue); return obj; } diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h index f395374ae..760d5d3b1 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.h +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h @@ -40,9 +40,9 @@ public: static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index 355993864..3f7f2f621 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.cpp +++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp @@ -22,6 +22,7 @@ #include "BooleanObject.h" #include "JSScope.h" +#include "Operations.h" namespace JSC { @@ -29,14 +30,14 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanObject); const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanObject) }; -BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure) - : JSWrapperObject(globalData, structure) +BooleanObject::BooleanObject(VM& vm, Structure* structure) + : JSWrapperObject(vm, structure) { } -void BooleanObject::finishCreation(JSGlobalData& globalData) +void BooleanObject::finishCreation(VM& vm) { - Base::finishCreation(globalData); + Base::finishCreation(vm); ASSERT(inherits(&s_info)); } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index b6fcccdcf..299f34174 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -27,24 +27,24 @@ namespace JSC { class BooleanObject : public JSWrapperObject { protected: - JS_EXPORT_PRIVATE BooleanObject(JSGlobalData&, Structure*); - JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&); + JS_EXPORT_PRIVATE BooleanObject(VM&, Structure*); + JS_EXPORT_PRIVATE void finishCreation(VM&); public: typedef JSWrapperObject Base; - static BooleanObject* create(JSGlobalData& globalData, Structure* structure) + static BooleanObject* create(VM& vm, Structure* structure) { - BooleanObject* boolean = new (NotNull, allocateCell(globalData.heap)) BooleanObject(globalData, structure); - boolean->finishCreation(globalData); + BooleanObject* boolean = new (NotNull, allocateCell(vm.heap)) BooleanObject(vm, structure); + boolean->finishCreation(vm); return boolean; } static JS_EXPORTDATA const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } }; diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp index a331c6c15..a5b8390a8 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -26,6 +26,7 @@ #include "JSFunction.h" #include "JSString.h" #include "ObjectPrototype.h" +#include "Operations.h" namespace JSC { @@ -50,14 +51,14 @@ const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanPrototype); BooleanPrototype::BooleanPrototype(ExecState* exec, Structure* structure) - : BooleanObject(exec->globalData(), structure) + : BooleanObject(exec->vm(), structure) { } void BooleanPrototype::finishCreation(ExecState* exec, JSGlobalObject*) { - Base::finishCreation(exec->globalData()); - setInternalValue(exec->globalData(), jsBoolean(false)); + Base::finishCreation(exec->vm()); + setInternalValue(exec->vm(), jsBoolean(false)); ASSERT(inherits(&s_info)); } @@ -76,22 +77,22 @@ bool BooleanPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exe EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec) { - JSGlobalData* globalData = &exec->globalData(); + VM* vm = &exec->vm(); JSValue thisValue = exec->hostThisValue(); if (thisValue == jsBoolean(false)) - return JSValue::encode(globalData->smallStrings.falseString(globalData)); + return JSValue::encode(vm->smallStrings.falseString()); if (thisValue == jsBoolean(true)) - return JSValue::encode(globalData->smallStrings.trueString(globalData)); + return JSValue::encode(vm->smallStrings.trueString()); if (!thisValue.inherits(&BooleanObject::s_info)) return throwVMTypeError(exec); if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false)) - return JSValue::encode(globalData->smallStrings.falseString(globalData)); + return JSValue::encode(vm->smallStrings.falseString()); ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true)); - return JSValue::encode(globalData->smallStrings.trueString(globalData)); + return JSValue::encode(vm->smallStrings.trueString()); } EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.h b/Source/JavaScriptCore/runtime/BooleanPrototype.h index 05790a755..43b81cb61 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.h +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.h @@ -38,9 +38,9 @@ public: static const ClassInfo s_info; - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/Butterfly.h b/Source/JavaScriptCore/runtime/Butterfly.h index bbbda9461..eb6d82a76 100644 --- a/Source/JavaScriptCore/runtime/Butterfly.h +++ b/Source/JavaScriptCore/runtime/Butterfly.h @@ -34,10 +34,45 @@ namespace JSC { -class JSGlobalData; +class VM; class CopyVisitor; struct ArrayStorage; +template struct ContiguousData { + ContiguousData() + : m_data(0) +#if !ASSERT_DISABLED + , m_length(0) +#endif + { + } + ContiguousData(T* data, size_t length) + : m_data(data) +#if !ASSERT_DISABLED + , m_length(length) +#endif + { + UNUSED_PARAM(length); + } + + const T& operator[](size_t index) const { ASSERT(index < m_length); return m_data[index]; } + T& operator[](size_t index) { ASSERT(index < m_length); return m_data[index]; } + + T* data() const { return m_data; } +#if !ASSERT_DISABLED + size_t length() const { return m_length; } +#endif + +private: + T* m_data; +#if !ASSERT_DISABLED + size_t m_length; +#endif +}; + +typedef ContiguousData ContiguousDoubles; +typedef ContiguousData > ContiguousJSValues; + class Butterfly { WTF_MAKE_NONCOPYABLE(Butterfly); private: @@ -69,10 +104,10 @@ public: static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); } static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); } - static Butterfly* createUninitialized(JSGlobalData&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); + static Butterfly* createUninitialized(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); - static Butterfly* create(JSGlobalData&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes); - static Butterfly* create(JSGlobalData&, Structure*); + static Butterfly* create(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes); + static Butterfly* create(VM&, Structure*); static Butterfly* createUninitializedDuringCollection(CopyVisitor&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); IndexingHeader* indexingHeader() { return IndexingHeader::from(this); } @@ -86,11 +121,12 @@ public: void setVectorLength(uint32_t value) { indexingHeader()->setVectorLength(value); } template - T* indexingPayload() { return reinterpret_cast(this); } + T* indexingPayload() { return reinterpret_cast_ptr(this); } ArrayStorage* arrayStorage() { return indexingPayload(); } - WriteBarrier* contiguousInt32() { return indexingPayload >(); } - double* contiguousDouble() { return indexingPayload(); } - WriteBarrier* contiguous() { return indexingPayload >(); } + ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload >(), vectorLength()); } + + ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload(), vectorLength()); } + ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload >(), vectorLength()); } static Butterfly* fromContiguous(WriteBarrier* contiguous) { @@ -111,20 +147,20 @@ public: void* base(size_t preCapacity, size_t propertyCapacity) { return propertyStorage() - propertyCapacity - preCapacity; } void* base(Structure*); - static Butterfly* createOrGrowArrayRight(Butterfly*, JSGlobalData&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); + static Butterfly* createOrGrowArrayRight(Butterfly*, VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // The butterfly reallocation methods perform the reallocation itself but do not change any // of the meta-data to reflect that the reallocation occurred. Note that this set of // methods is not exhaustive and is not intended to encapsulate all possible allocation // modes of butterflies - there are code paths that allocate butterflies by calling // directly into Heap::tryAllocateStorage. - Butterfly* growPropertyStorage(JSGlobalData&, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity); - Butterfly* growPropertyStorage(JSGlobalData&, Structure* oldStructure, size_t oldPropertyCapacity, size_t newPropertyCapacity); - Butterfly* growPropertyStorage(JSGlobalData&, Structure* oldStructure, size_t newPropertyCapacity); - Butterfly* growArrayRight(JSGlobalData&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much. - Butterfly* growArrayRight(JSGlobalData&, Structure*, size_t newIndexingPayloadSizeInBytes); - Butterfly* resizeArray(JSGlobalData&, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes); - Butterfly* resizeArray(JSGlobalData&, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header. + Butterfly* growPropertyStorage(VM&, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity); + Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t oldPropertyCapacity, size_t newPropertyCapacity); + Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t newPropertyCapacity); + Butterfly* growArrayRight(VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much. + Butterfly* growArrayRight(VM&, Structure*, size_t newIndexingPayloadSizeInBytes); + Butterfly* resizeArray(VM&, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes); + Butterfly* resizeArray(VM&, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header. Butterfly* unshift(Structure*, size_t numberOfSlots); Butterfly* shift(Structure*, size_t numberOfSlots); }; diff --git a/Source/JavaScriptCore/runtime/ButterflyInlines.h b/Source/JavaScriptCore/runtime/ButterflyInlines.h index f01458950..a0e2af19d 100644 --- a/Source/JavaScriptCore/runtime/ButterflyInlines.h +++ b/Source/JavaScriptCore/runtime/ButterflyInlines.h @@ -30,33 +30,32 @@ #include "Butterfly.h" #include "CopiedSpaceInlines.h" #include "CopyVisitor.h" -#include "JSGlobalData.h" +#include "VM.h" #include "Structure.h" namespace JSC { -inline Butterfly* Butterfly::createUninitialized(JSGlobalData& globalData, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) +inline Butterfly* Butterfly::createUninitialized(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) { void* temp; size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); - if (!globalData.heap.tryAllocateStorage(size, &temp)) - CRASH(); + RELEASE_ASSERT(vm.heap.tryAllocateStorage(size, &temp)); Butterfly* result = fromBase(temp, preCapacity, propertyCapacity); return result; } -inline Butterfly* Butterfly::create(JSGlobalData& globalData, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes) +inline Butterfly* Butterfly::create(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes) { Butterfly* result = createUninitialized( - globalData, preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); + vm, preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); if (hasIndexingHeader) *result->indexingHeader() = indexingHeader; return result; } -inline Butterfly* Butterfly::create(JSGlobalData& globalData, Structure* structure) +inline Butterfly* Butterfly::create(VM& vm, Structure* structure) { - return create(globalData, 0, structure->outOfLineCapacity(), hasIndexingHeader(structure->indexingType()), IndexingHeader(), 0); + return create(vm, 0, structure->outOfLineCapacity(), hasIndexingHeader(structure->indexingType()), IndexingHeader(), 0); } inline Butterfly* Butterfly::createUninitializedDuringCollection(CopyVisitor& visitor, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) @@ -73,11 +72,11 @@ inline void* Butterfly::base(Structure* structure) return base(indexingHeader()->preCapacity(structure), structure->outOfLineCapacity()); } -inline Butterfly* Butterfly::growPropertyStorage(JSGlobalData& globalData, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity) +inline Butterfly* Butterfly::growPropertyStorage(VM& vm, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity) { - ASSERT(newPropertyCapacity > oldPropertyCapacity); + RELEASE_ASSERT(newPropertyCapacity > oldPropertyCapacity); Butterfly* result = createUninitialized( - globalData, preCapacity, newPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); + vm, preCapacity, newPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); memcpy( result->propertyStorage() - oldPropertyCapacity, propertyStorage() - oldPropertyCapacity, @@ -85,51 +84,51 @@ inline Butterfly* Butterfly::growPropertyStorage(JSGlobalData& globalData, size_ return result; } -inline Butterfly* Butterfly::growPropertyStorage(JSGlobalData& globalData, Structure* structure, size_t oldPropertyCapacity, size_t newPropertyCapacity) +inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* structure, size_t oldPropertyCapacity, size_t newPropertyCapacity) { return growPropertyStorage( - globalData, indexingHeader()->preCapacity(structure), oldPropertyCapacity, + vm, indexingHeader()->preCapacity(structure), oldPropertyCapacity, hasIndexingHeader(structure->indexingType()), indexingHeader()->indexingPayloadSizeInBytes(structure), newPropertyCapacity); } -inline Butterfly* Butterfly::growPropertyStorage(JSGlobalData& globalData, Structure* oldStructure, size_t newPropertyCapacity) +inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* oldStructure, size_t newPropertyCapacity) { return growPropertyStorage( - globalData, oldStructure, oldStructure->outOfLineCapacity(), newPropertyCapacity); + vm, oldStructure, oldStructure->outOfLineCapacity(), newPropertyCapacity); } -inline Butterfly* Butterfly::createOrGrowArrayRight(Butterfly* oldButterfly, JSGlobalData& globalData, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::createOrGrowArrayRight(Butterfly* oldButterfly, VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) { if (!oldButterfly) - return create(globalData, 0, propertyCapacity, true, IndexingHeader(), newIndexingPayloadSizeInBytes); - return oldButterfly->growArrayRight(globalData, oldStructure, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); + return create(vm, 0, propertyCapacity, true, IndexingHeader(), newIndexingPayloadSizeInBytes); + return oldButterfly->growArrayRight(vm, oldStructure, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); } -inline Butterfly* Butterfly::growArrayRight(JSGlobalData& globalData, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) { ASSERT_UNUSED(oldStructure, !indexingHeader()->preCapacity(oldStructure)); ASSERT_UNUSED(oldStructure, hadIndexingHeader == hasIndexingHeader(oldStructure->indexingType())); void* theBase = base(0, propertyCapacity); size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes); size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes); - if (!globalData.heap.tryReallocateStorage(&theBase, oldSize, newSize)) + if (!vm.heap.tryReallocateStorage(&theBase, oldSize, newSize)) return 0; return fromBase(theBase, 0, propertyCapacity); } -inline Butterfly* Butterfly::growArrayRight(JSGlobalData& globalData, Structure* oldStructure, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t newIndexingPayloadSizeInBytes) { return growArrayRight( - globalData, oldStructure, oldStructure->outOfLineCapacity(), + vm, oldStructure, oldStructure->outOfLineCapacity(), hasIndexingHeader(oldStructure->indexingType()), indexingHeader()->indexingPayloadSizeInBytes(oldStructure), newIndexingPayloadSizeInBytes); } -inline Butterfly* Butterfly::resizeArray(JSGlobalData& globalData, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::resizeArray(VM& vm, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes) { Butterfly* result = createUninitialized( - globalData, newPreCapacity, propertyCapacity, newHasIndexingHeader, newIndexingPayloadSizeInBytes); + vm, newPreCapacity, propertyCapacity, newHasIndexingHeader, newIndexingPayloadSizeInBytes); // FIXME: This could be made much more efficient if we used the property size, // not the capacity. void* to = result->propertyStorage() - propertyCapacity; @@ -141,11 +140,11 @@ inline Butterfly* Butterfly::resizeArray(JSGlobalData& globalData, size_t proper return result; } -inline Butterfly* Butterfly::resizeArray(JSGlobalData& globalData, Structure* structure, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::resizeArray(VM& vm, Structure* structure, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes) { bool hasIndexingHeader = JSC::hasIndexingHeader(structure->indexingType()); return resizeArray( - globalData, structure->outOfLineCapacity(), hasIndexingHeader, + vm, structure->outOfLineCapacity(), hasIndexingHeader, indexingHeader()->indexingPayloadSizeInBytes(structure), newPreCapacity, hasIndexingHeader, newIndexingPayloadSizeInBytes); } diff --git a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h b/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h index 62a01dbcb..392d64fa5 100644 --- a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h +++ b/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h @@ -26,7 +26,7 @@ #ifndef CachedTranscendentalFunction_h #define CachedTranscendentalFunction_h -#include "JSValue.h" +#include "JSCJSValue.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/CallData.cpp b/Source/JavaScriptCore/runtime/CallData.cpp index ff71fa0cb..8e1d19486 100644 --- a/Source/JavaScriptCore/runtime/CallData.cpp +++ b/Source/JavaScriptCore/runtime/CallData.cpp @@ -29,6 +29,7 @@ #include "Executable.h" #include "Interpreter.h" #include "JSFunction.h" +#include "Operations.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/CallData.h b/Source/JavaScriptCore/runtime/CallData.h index 7df36c72a..3bbac734f 100644 --- a/Source/JavaScriptCore/runtime/CallData.h +++ b/Source/JavaScriptCore/runtime/CallData.h @@ -29,7 +29,7 @@ #ifndef CallData_h #define CallData_h -#include "JSValue.h" +#include "JSCJSValue.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp index 068919528..de904ae71 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.cpp +++ b/Source/JavaScriptCore/runtime/CodeCache.cpp @@ -29,127 +29,129 @@ #include "BytecodeGenerator.h" #include "CodeSpecializationKind.h" +#include "Operations.h" #include "Parser.h" #include "StrongInlines.h" #include "UnlinkedCodeBlock.h" namespace JSC { -CodeCache::CodeCache() +const double CodeCacheMap::workingSetTime = 10.0; +const int64_t CodeCacheMap::globalWorkingSetMaxBytes = 16000000; +const size_t CodeCacheMap::globalWorkingSetMaxEntries = 2000; +const unsigned CodeCacheMap::nonGlobalWorkingSetScale = 20; +const int64_t CodeCacheMap::nonGlobalWorkingSetMaxBytes = CodeCacheMap::globalWorkingSetMaxBytes / CodeCacheMap::nonGlobalWorkingSetScale; +const size_t CodeCacheMap::nonGlobalWorkingSetMaxEntries = CodeCacheMap::globalWorkingSetMaxEntries / CodeCacheMap::nonGlobalWorkingSetScale; + +void CodeCacheMap::pruneSlowCase() { + m_minCapacity = std::max(m_size - m_sizeAtLastPrune, static_cast(0)); + m_sizeAtLastPrune = m_size; + m_timeAtLastPrune = monotonicallyIncreasingTime(); + + if (m_capacity < m_minCapacity) + m_capacity = m_minCapacity; + + while (m_size > m_capacity || !canPruneQuickly()) { + MapType::iterator it = m_map.begin(); + m_size -= it->key.length(); + m_map.remove(it); + } } -CodeCache::~CodeCache() +CodeCache::CodeCache(CodeCacheKind kind) +: m_sourceCode(kind == GlobalCodeCache ? CodeCacheMap::globalWorkingSetMaxBytes : CodeCacheMap::nonGlobalWorkingSetMaxBytes, + kind == GlobalCodeCache ? CodeCacheMap::globalWorkingSetMaxEntries : CodeCacheMap::nonGlobalWorkingSetMaxEntries) { } -CodeCache::CodeBlockKey CodeCache::makeCodeBlockKey(const SourceCode& source, CodeCache::CodeType type, JSParserStrictness strictness) +CodeCache::~CodeCache() { - return std::make_pair(source.toString(), (type << 1) | strictness); } template struct CacheTypes { }; template <> struct CacheTypes { typedef JSC::ProgramNode RootNode; - static const CodeCache::CodeType codeType = CodeCache::ProgramType; + static const SourceCodeKey::CodeType codeType = SourceCodeKey::ProgramType; }; template <> struct CacheTypes { typedef JSC::EvalNode RootNode; - static const CodeCache::CodeType codeType = CodeCache::EvalType; + static const SourceCodeKey::CodeType codeType = SourceCodeKey::EvalType; }; template -UnlinkedCodeBlockType* CodeCache::getCodeBlock(JSGlobalData& globalData, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedCodeBlockType* CodeCache::generateBytecode(VM& vm, JSScope* scope, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - CodeBlockKey key = makeCodeBlockKey(source, CacheTypes::codeType, strictness); - bool storeInCache = false; - if (debuggerMode == DebuggerOff && profilerMode == ProfilerOff) { - const Strong* result = m_cachedCodeBlocks.find(key); - if (result) { - UnlinkedCodeBlockType* unlinkedCode = jsCast(result->get()); - unsigned firstLine = source.firstLine() + unlinkedCode->firstLine(); - executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount()); - return unlinkedCode; - } - storeInCache = true; - } - typedef typename CacheTypes::RootNode RootNode; - RefPtr rootNode = parse(&globalData, source, 0, Identifier(), strictness, JSParseProgramCode, error); + RefPtr rootNode = parse(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error); if (!rootNode) return 0; - executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine()); + executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine(), rootNode->startColumn()); - UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&globalData, executable->executableInfo()); + UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&vm, executable->executableInfo()); unlinkedCode->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), rootNode->lastLine() - rootNode->lineNo()); - OwnPtr generator(adoptPtr(new BytecodeGenerator(globalData, rootNode.get(), unlinkedCode, debuggerMode, profilerMode))); + OwnPtr generator(adoptPtr(new BytecodeGenerator(vm, scope, rootNode.get(), unlinkedCode, debuggerMode, profilerMode))); error = generator->generate(); rootNode->destroyData(); if (error.m_type != ParserError::ErrorNone) return 0; - - if (storeInCache) - m_cachedCodeBlocks.add(key, Strong(globalData, unlinkedCode)); - return unlinkedCode; } -UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(JSGlobalData& globalData, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +template +UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, JSScope* scope, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return getCodeBlock(globalData, executable, source, strictness, debuggerMode, profilerMode, error); -} + // We completely skip the cache if we're an eval that isn't at the top of the scope chain. + if (CacheTypes::codeType == SourceCodeKey::EvalType) { + if (scope->next() && !scope->isActivationObject()) + return generateBytecode(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); + } -UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(JSGlobalData& globalData, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - return getCodeBlock(globalData, executable, source, strictness, debuggerMode, profilerMode, error); -} + SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes::codeType, strictness); + CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); + bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff; -UnlinkedFunctionCodeBlock* CodeCache::generateFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - RefPtr body = parse(&globalData, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error); + if (!addResult.isNewEntry && canCache) { + UnlinkedCodeBlockType* unlinkedCode = jsCast(addResult.iterator->value.cell.get()); + unsigned firstLine = source.firstLine() + unlinkedCode->firstLine(); + unsigned startColumn = source.firstLine() ? source.startColumn() : 0; + executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount(), startColumn); + return unlinkedCode; + } + UnlinkedCodeBlockType* unlinkedCode = generateBytecode(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); - if (!body) { - ASSERT(error.m_type != ParserError::ErrorNone); - return 0; + if (!canCache || !unlinkedCode) { + m_sourceCode.remove(addResult.iterator); + return unlinkedCode; } - if (executable->forceUsesArguments()) - body->setUsesArguments(); - body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle()); - executable->recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine()); - - UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&globalData, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct)); - OwnPtr generator(adoptPtr(new BytecodeGenerator(globalData, body.get(), result, debuggerMode, profilerMode))); - error = generator->generate(); - body->destroyData(); - if (error.m_type != ParserError::ErrorNone) - return 0; - m_cachedFunctionCode.add(result, Strong(globalData, result)); - return result; + addResult.iterator->value = SourceCodeValue(vm, unlinkedCode, m_sourceCode.age()); + return unlinkedCode; } -UnlinkedFunctionCodeBlock* CodeCache::getFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error); + return getCodeBlock(vm, 0, executable, source, strictness, debuggerMode, profilerMode, error); } -CodeCache::GlobalFunctionKey CodeCache::makeGlobalFunctionKey(const SourceCode& source, const String& name) +UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, JSScope* scope, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return GlobalFunctionKey(source.toString(), name); + return getCodeBlock(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); } -UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, ParserError& error) +UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error) { - GlobalFunctionKey key = makeGlobalFunctionKey(source, name.string()); - const Strong* result = m_cachedGlobalFunctions.find(key); - if (result) - return result->get(); + SourceCodeKey key = SourceCodeKey(source, name.string(), SourceCodeKey::FunctionType, JSParseNormal); + CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); + if (!addResult.isNewEntry) + return jsCast(addResult.iterator->value.cell.get()); - RefPtr program = parse(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); + RefPtr program = parse(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); if (!program) { ASSERT(error.m_type != ParserError::ErrorNone); + m_sourceCode.remove(addResult.iterator); return 0; } @@ -159,21 +161,16 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlo ASSERT(exprStatement->isExprStatement()); ExpressionNode* funcExpr = static_cast(exprStatement)->expr(); ASSERT(funcExpr); - ASSERT(funcExpr->isFuncExprNode()); + RELEASE_ASSERT(funcExpr->isFuncExprNode()); FunctionBodyNode* body = static_cast(funcExpr)->body(); ASSERT(body); ASSERT(body->ident().isNull()); - UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&globalData, source, body); - functionExecutable->m_nameValue.set(globalData, functionExecutable, jsString(&globalData, name.string())); + UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body); + functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string())); - m_cachedGlobalFunctions.add(key, Strong(globalData, functionExecutable)); + addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age()); return functionExecutable; } -void CodeCache::usedFunctionCode(JSGlobalData& globalData, UnlinkedFunctionCodeBlock* codeBlock) -{ - m_cachedFunctionCode.add(codeBlock, Strong(globalData, codeBlock)); -} - } diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h index 733de42d6..986b266c2 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.h +++ b/Source/JavaScriptCore/runtime/CodeCache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,9 +28,10 @@ #include "CodeSpecializationKind.h" #include "ParserModes.h" +#include "SourceCode.h" #include "Strong.h" #include "WeakRandom.h" - +#include #include #include #include @@ -40,88 +41,239 @@ namespace JSC { class EvalExecutable; +class FunctionBodyNode; class Identifier; +class JSScope; class ProgramExecutable; class UnlinkedCodeBlock; class UnlinkedEvalCodeBlock; class UnlinkedFunctionCodeBlock; class UnlinkedFunctionExecutable; class UnlinkedProgramCodeBlock; -class JSGlobalData; +class VM; struct ParserError; class SourceCode; class SourceProvider; -template class CacheMap { - typedef typename HashMap::iterator iterator; +class SourceCodeKey { public: - CacheMap() - : m_randomGenerator((static_cast(randomNumber() * std::numeric_limits::max()))) + enum CodeType { EvalType, ProgramType, FunctionType }; + + SourceCodeKey() { } - const EntryType* find(const KeyType& key) + + SourceCodeKey(const SourceCode& sourceCode, const String& name, CodeType codeType, JSParserStrictness jsParserStrictness) + : m_sourceCode(sourceCode) + , m_name(name) + , m_flags((codeType << 1) | jsParserStrictness) + , m_hash(string().impl()->hash()) { - 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) + + SourceCodeKey(WTF::HashTableDeletedValueType) + : m_sourceCode(WTF::HashTableDeletedValue) { - iterator result = m_map.find(key); - if (result != m_map.end()) { - m_data[result->value].second = value; - return; + } + + bool isHashTableDeletedValue() const { return m_sourceCode.isHashTableDeletedValue(); } + + unsigned hash() const { return m_hash; } + + size_t length() const { return m_sourceCode.length(); } + + bool isNull() const { return m_sourceCode.isNull(); } + + // To save memory, we compute our string on demand. It's expected that source + // providers cache their strings to make this efficient. + String string() const { return m_sourceCode.toString(); } + + bool operator==(const SourceCodeKey& other) const + { + return m_hash == other.m_hash + && length() == other.length() + && m_flags == other.m_flags + && m_name == other.m_name + && string() == other.string(); + } + +private: + SourceCode m_sourceCode; + String m_name; + unsigned m_flags; + unsigned m_hash; +}; + +struct SourceCodeKeyHash { + static unsigned hash(const SourceCodeKey& key) { return key.hash(); } + static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +struct SourceCodeKeyHashTraits : SimpleClassHashTraits { + static const bool hasIsEmptyValueFunction = true; + static bool isEmptyValue(const SourceCodeKey& sourceCodeKey) { return sourceCodeKey.isNull(); } +}; + +struct SourceCodeValue { + SourceCodeValue() + { + } + + SourceCodeValue(VM& vm, JSCell* cell, int64_t age) + : cell(vm, cell) + , age(age) + { + } + + Strong cell; + int64_t age; +}; + +class CodeCacheMap { +public: + typedef HashMap MapType; + typedef MapType::iterator iterator; + typedef MapType::AddResult AddResult; + + CodeCacheMap(int64_t workingSetMaxBytes, size_t workingSetMaxEntries) + : m_size(0) + , m_sizeAtLastPrune(0) + , m_timeAtLastPrune(monotonicallyIncreasingTime()) + , m_minCapacity(0) + , m_capacity(0) + , m_age(0) + , m_workingSetMaxBytes(workingSetMaxBytes) + , m_workingSetMaxEntries(workingSetMaxEntries) + { + } + + AddResult add(const SourceCodeKey& key, const SourceCodeValue& value) + { + prune(); + + AddResult addResult = m_map.add(key, value); + if (addResult.isNewEntry) { + m_size += key.length(); + m_age += key.length(); + return addResult; + } + + int64_t age = m_age - addResult.iterator->value.age; + if (age > m_capacity) { + // A requested object is older than the cache's capacity. We can + // infer that requested objects are subject to high eviction probability, + // so we grow the cache to improve our hit rate. + m_capacity += recencyBias * oldObjectSamplingMultiplier * key.length(); + } else if (age < m_capacity / 2) { + // A requested object is much younger than the cache's capacity. We can + // infer that requested objects are subject to low eviction probability, + // so we shrink the cache to save memory. + m_capacity -= recencyBias * key.length(); + if (m_capacity < m_minCapacity) + m_capacity = m_minCapacity; } - 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); + + addResult.iterator->value.age = m_age; + m_age += key.length(); + return addResult; } + + void remove(iterator it) + { + m_size -= it->key.length(); + m_map.remove(it); + } + + void clear() + { + m_size = 0; + m_age = 0; + m_map.clear(); + } + + int64_t age() { return m_age; } + + static const int64_t globalWorkingSetMaxBytes; + static const size_t globalWorkingSetMaxEntries; + + // We have a smaller cap for the per-codeblock CodeCache that approximates the + // linked EvalCodeCache limits, but still allows us to keep large string based + // evals at least partially cached. + static const unsigned nonGlobalWorkingSetScale; + static const int64_t nonGlobalWorkingSetMaxBytes; + static const size_t nonGlobalWorkingSetMaxEntries; + private: - HashMap m_map; - FixedArray, CacheSize> m_data; - WeakRandom m_randomGenerator; + // This constant factor biases cache capacity toward allowing a minimum + // working set to enter the cache before it starts evicting. + static const double workingSetTime; + + // This constant factor biases cache capacity toward recent activity. We + // want to adapt to changing workloads. + static const int64_t recencyBias = 4; + + // This constant factor treats a sampled event for one old object as if it + // happened for many old objects. Most old objects are evicted before we can + // sample them, so we need to extrapolate from the ones we do sample. + static const int64_t oldObjectSamplingMultiplier = 32; + + size_t numberOfEntries() const { return static_cast(m_map.size()); } + bool canPruneQuickly() const { return numberOfEntries() < m_workingSetMaxEntries; } + + void pruneSlowCase(); + void prune() + { + if (m_size <= m_capacity && canPruneQuickly()) + return; + + if (monotonicallyIncreasingTime() - m_timeAtLastPrune < workingSetTime + && m_size - m_sizeAtLastPrune < m_workingSetMaxBytes + && canPruneQuickly()) + return; + + pruneSlowCase(); + } + + MapType m_map; + int64_t m_size; + int64_t m_sizeAtLastPrune; + double m_timeAtLastPrune; + int64_t m_minCapacity; + int64_t m_capacity; + int64_t m_age; + const int64_t m_workingSetMaxBytes; + const size_t m_workingSetMaxEntries; }; -class CodeCache { +// Caches top-level code such as